From de2bed70c8b40299db03b3563a30853e1b5cac74 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 07:39:39 +1000 Subject: [PATCH 001/120] feat: Add modify to public api --- packages/dataparcels/src/parcel/Parcel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 75e5b8ab..eecc8418 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -340,8 +340,9 @@ export default class Parcel { unshift = (value: *) => this._methods.unshift(value); // Modify methods + modify = (updater: Function): Parcel => this._methods.modify(updater); modifyValue = (updater: Function): Parcel => this._methods.modifyValue(updater); - modifyChange = (batcher: Function): Parcel => this._methods.modifyChange(batcher); + modifyChange = (updater: Function): Parcel => this._methods.modifyChange(updater); modifyChangeValue = (updater: Function): Parcel => this._methods.modifyChangeValue(updater); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); From b9caecde53003527fd8330602fe25374bd7a86eb Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 07:39:56 +1000 Subject: [PATCH 002/120] feat: stub modify function --- packages/dataparcels/src/parcel/methods/ModifyMethods.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index dd0840d0..39a39af3 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -15,6 +15,13 @@ import pipeWith from 'unmutable/lib/util/pipeWith'; export default (_this: Parcel): Object => ({ + modify: (updater: Function): Parcel => { + Types(`modify() expects param "updater" to be`, `function`)(updater); + return _this._create({ + id: _this._id.pushModifier('m') + }); + }, + modifyValue: (updater: Function): Parcel => { Types(`modifyValue() expects param "updater" to be`, `function`)(updater); return pipeWith( From be0c81a3162b57fcb8af4682b14242c7cf4478b0 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 07:46:15 +1000 Subject: [PATCH 003/120] refactor: organise private variables --- packages/dataparcels/src/parcel/Parcel.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index eecc8418..823e0f25 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -138,20 +138,23 @@ export default class Parcel { // private // + // from constructor + _id: ParcelId; _methods: { [key: string]: * }; _onHandleChange: ?Function; _onDispatch: ?Function; _parcelData: ParcelData; - _id: ParcelId; - _matchPipes: MatchPipe[]; - _treeshare: Treeshare; _parcelTypes: ParcelTypes; _parent: ?Parcel; - _dispatchBuffer: ?Function; + _treeshare: Treeshare; _isFirst: boolean = false; _isLast: boolean = false; - _log: boolean = false; - _logName: string = ""; + + // from methods + _dispatchBuffer: ?Function; // used by batch() + _log: boolean = false; // used by log() + _logName: string = ""; // used by log() + _matchPipes: MatchPipe[]; // used by matchPipe() and passed to all subsequent parcels _create = (createParcelConfig: CreateParcelConfigType): Parcel => { let { From 5470617bfe158d0689e24d723091141b29e529e4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 07:46:49 +1000 Subject: [PATCH 004/120] refactor: remove unused isFirst and isLast member vars --- packages/dataparcels/src/parcel/Parcel.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 823e0f25..eb033467 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -147,8 +147,6 @@ export default class Parcel { _parcelTypes: ParcelTypes; _parent: ?Parcel; _treeshare: Treeshare; - _isFirst: boolean = false; - _isLast: boolean = false; // from methods _dispatchBuffer: ?Function; // used by batch() From d73ff46102ea1a60fe03bed8ec8925ceca9a4f2d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 08:03:28 +1000 Subject: [PATCH 005/120] fix: unget should not have index as a key --- packages/dataparcels/src/change/Action.js | 11 ++++------- packages/dataparcels/src/change/ChangeRequest.js | 3 +-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/dataparcels/src/change/Action.js b/packages/dataparcels/src/change/Action.js index fb28f365..aca017b8 100644 --- a/packages/dataparcels/src/change/Action.js +++ b/packages/dataparcels/src/change/Action.js @@ -1,19 +1,16 @@ // @flow -import type { - Key, - Index -} from '../types/Types'; +import type {Key} from '../types/Types'; type ActionData = { type?: string, payload?: Object, - keyPath?: Array + keyPath?: Array }; export default class Action { type: string = ""; payload: Object = {}; - keyPath: Array = []; + keyPath: Array = []; constructor(actionData: ActionData = {}) { this.type = actionData.type || this.type; @@ -21,7 +18,7 @@ export default class Action { this.keyPath = actionData.keyPath || this.keyPath; } - _unget = (key: Key|Index): Action => { + _unget = (key: Key): Action => { let {type, payload, keyPath} = this; return new Action({ type, diff --git a/packages/dataparcels/src/change/ChangeRequest.js b/packages/dataparcels/src/change/ChangeRequest.js index 9cf6f225..a4364189 100644 --- a/packages/dataparcels/src/change/ChangeRequest.js +++ b/packages/dataparcels/src/change/ChangeRequest.js @@ -1,7 +1,6 @@ // @flow import type Parcel from '../parcel/Parcel'; import type {Key} from '../types/Types'; -import type {Index} from '../types/Types'; import type {ParcelData} from '../types/Types'; import type Action from './Action'; @@ -33,7 +32,7 @@ export default class ChangeRequest { return changeRequest; }; - _unget = (key: Key|Index): ChangeRequest => { + _unget = (key: Key): ChangeRequest => { return this._create({ actions: this._actions.map(ii => ii._unget(key)) }); From 17a7e9dd792a80f090e16b6a2fe3ecc74b59aa5c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 08:12:02 +1000 Subject: [PATCH 006/120] BREAKING CHANGE: Remove ActionCreators from public API --- packages/dataparcels/src/index.js | 1 - packages/react-dataparcels/src/index.js | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index b915e6b0..24260782 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -3,7 +3,6 @@ import Parcel from './parcel/Parcel'; export default Parcel; export {default as Action} from './change/Action'; -export {default as ActionCreators} from './change/ActionCreators'; export {default as ChangeRequest} from './change/ChangeRequest'; export type {ParcelData} from './types/Types'; diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index a204c17b..aaa87b16 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -3,7 +3,6 @@ import dataparcels from 'dataparcels'; export default dataparcels; export {Action} from 'dataparcels'; -export {ActionCreators} from 'dataparcels'; export {ChangeRequest} from 'dataparcels'; export type {ParcelData} from 'dataparcels'; From b2c5e3ab5e406856a28967caafe067b91f7b4af8 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 3 Oct 2018 08:38:09 +1000 Subject: [PATCH 007/120] feat: Add keyPathModifiers to Action --- packages/dataparcels/src/change/Action.js | 70 +++++++++++++++++++---- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/packages/dataparcels/src/change/Action.js b/packages/dataparcels/src/change/Action.js index aca017b8..80e78616 100644 --- a/packages/dataparcels/src/change/Action.js +++ b/packages/dataparcels/src/change/Action.js @@ -1,29 +1,77 @@ // @flow import type {Key} from '../types/Types'; +import has from 'unmutable/lib/has'; +import set from 'unmutable/lib/set'; +import unshift from 'unmutable/lib/unshift'; + type ActionData = { type?: string, payload?: Object, keyPath?: Array }; +type CreateActionData = { + type?: string, + payload?: Object, + keyPath?: Array, + keyPathModifiers?: Array +}; + +type KeyPathModifiers = { + key?: Key, + pre?: Function, + post?: Function +}; + export default class Action { type: string = ""; payload: Object = {}; keyPath: Array = []; + keyPathModifiers: Array = []; + + constructor({type, payload, keyPath}: ActionData = {}) { + this.type = type || this.type; + this.payload = payload || this.payload; + this.keyPath = keyPath || this.keyPath; - constructor(actionData: ActionData = {}) { - this.type = actionData.type || this.type; - this.payload = actionData.payload || this.payload; - this.keyPath = actionData.keyPath || this.keyPath; + if(keyPath) { + this.keyPathModifiers = keyPath.map(key => ({key})); + } } - _unget = (key: Key): Action => { - let {type, payload, keyPath} = this; + _create = (create: CreateActionData): Action => { return new Action({ - type, - payload, - keyPath: [key, ...keyPath] + ...this.toJS(), + ...create + }); + }; + + _updateFirstKeyPathModifier = (obj: *, keyPathModifiers: Array): Array => { + let first = keyPathModifiers[0]; + let fn = (!first || !has("key")(first)) + ? unshift(obj) + : set(0, {...obj, ...first}); + + return fn(keyPathModifiers); + }; + + _unget = (key: Key): Action => { + return this._create({ + keyPath: unshift(key)(this.keyPath), + keyPathModifiers: this._updateFirstKeyPathModifier({key}, this.keyPathModifiers) + }); + }; + + _addPre = (pre: Function) => { + return this._create({ + keyPathModifiers: this._updateFirstKeyPathModifier({pre}, this.keyPathModifiers) + }); + }; + + _addPost = (post: Function) => { + return this._create({ + keyPathModifiers: this._updateFirstKeyPathModifier({post}, this.keyPathModifiers) }); }; @@ -40,7 +88,7 @@ export default class Action { }; toJS = (): ActionData => { - let {type, payload, keyPath} = this; - return {type, payload, keyPath}; + let {type, payload, keyPath, keyPathModifiers} = this; + return {type, payload, keyPath, keyPathModifiers}; }; } From 4203e0055c94ae5a027a0efa134516576434f2a1 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 26 Nov 2018 21:17:50 +1100 Subject: [PATCH 008/120] amend: remove parcel.modify() --- packages/dataparcels/src/parcel/Parcel.js | 1 - packages/dataparcels/src/parcel/methods/ModifyMethods.js | 7 ------- 2 files changed, 8 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 1588ac43..27e31f03 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -345,7 +345,6 @@ export default class Parcel { unshift = (value: *) => this._methods.unshift(value); // Modify methods - modify = (updater: Function): Parcel => this._methods.modify(updater); modifyValue = (updater: Function): Parcel => this._methods.modifyValue(updater); modifyChangeBatch = (batcher: Function): Parcel => this._methods.modifyChangeBatch(batcher); modifyChangeValue = (updater: Function): Parcel => this._methods.modifyChangeValue(updater); diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 329d71b4..bb21b2af 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -23,13 +23,6 @@ let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; export default (_this: Parcel): Object => ({ - modify: (updater: Function): Parcel => { - Types(`modify() expects param "updater" to be`, `function`)(updater); - return _this._create({ - id: _this._id.pushModifier('m') - }); - }, - modifyValue: (updater: Function): Parcel => { Types(`modifyValue()`, `updater`, `function`)(updater); From aaa354e12ee0a1f6f265741385979b302ff1f91c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:03:39 +1100 Subject: [PATCH 009/120] refactor: make parcelData functions more consistently named --- packages/dataparcels/src/parcelData/insert.js | 2 +- packages/dataparcels/src/parcelData/insertAfter.js | 3 +++ packages/dataparcels/src/parcelData/insertBefore.js | 3 +++ packages/dataparcels/src/parcelData/swapNext.js | 3 +++ packages/dataparcels/src/parcelData/swapNextPrev.js | 2 +- packages/dataparcels/src/parcelData/swapPrev.js | 3 +++ 6 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 packages/dataparcels/src/parcelData/insertAfter.js create mode 100644 packages/dataparcels/src/parcelData/insertBefore.js create mode 100644 packages/dataparcels/src/parcelData/swapNext.js create mode 100644 packages/dataparcels/src/parcelData/swapPrev.js diff --git a/packages/dataparcels/src/parcelData/insert.js b/packages/dataparcels/src/parcelData/insert.js index e0d2a900..bc0ac18b 100644 --- a/packages/dataparcels/src/parcelData/insert.js +++ b/packages/dataparcels/src/parcelData/insert.js @@ -11,7 +11,7 @@ import updateChildKeys from './updateChildKeys'; import insert from 'unmutable/lib/insert'; import size from 'unmutable/lib/size'; -export default (key: Key|Index, newValue: *, after: boolean = false) => (parcelData: ParcelData): ParcelData => { +export default (after: boolean) => (key: Key|Index, newValue: *) => (parcelData: ParcelData): ParcelData => { let parcelDataWithChildKeys = prepareChildKeys()(parcelData); let index: ?Index = keyOrIndexToIndex(key)(parcelDataWithChildKeys); diff --git a/packages/dataparcels/src/parcelData/insertAfter.js b/packages/dataparcels/src/parcelData/insertAfter.js new file mode 100644 index 00000000..82323cbd --- /dev/null +++ b/packages/dataparcels/src/parcelData/insertAfter.js @@ -0,0 +1,3 @@ +// @flow +import insert from './insert'; +export default insert(true); diff --git a/packages/dataparcels/src/parcelData/insertBefore.js b/packages/dataparcels/src/parcelData/insertBefore.js new file mode 100644 index 00000000..50f14de3 --- /dev/null +++ b/packages/dataparcels/src/parcelData/insertBefore.js @@ -0,0 +1,3 @@ +// @flow +import insert from './insert'; +export default insert(false); diff --git a/packages/dataparcels/src/parcelData/swapNext.js b/packages/dataparcels/src/parcelData/swapNext.js new file mode 100644 index 00000000..973b4f75 --- /dev/null +++ b/packages/dataparcels/src/parcelData/swapNext.js @@ -0,0 +1,3 @@ +// @flow +import swapNextPrev from './swapNextPrev'; +export default swapNextPrev(true); diff --git a/packages/dataparcels/src/parcelData/swapNextPrev.js b/packages/dataparcels/src/parcelData/swapNextPrev.js index bd47329d..226883b3 100644 --- a/packages/dataparcels/src/parcelData/swapNextPrev.js +++ b/packages/dataparcels/src/parcelData/swapNextPrev.js @@ -10,7 +10,7 @@ import wrapNumber from './wrapNumber'; import size from 'unmutable/lib/size'; import swap from 'unmutable/lib/swap'; -export default (key: Key|Index, next: boolean = false) => (parcelData: ParcelData): ParcelData => { +export default (next: boolean) => (key: Key|Index) => (parcelData: ParcelData): ParcelData => { let parcelDataWithChildKeys = prepareChildKeys()(parcelData); let indexA: ?Index = keyOrIndexToIndex(key)(parcelDataWithChildKeys); diff --git a/packages/dataparcels/src/parcelData/swapPrev.js b/packages/dataparcels/src/parcelData/swapPrev.js new file mode 100644 index 00000000..0d86bd4e --- /dev/null +++ b/packages/dataparcels/src/parcelData/swapPrev.js @@ -0,0 +1,3 @@ +// @flow +import swapNextPrev from './swapNextPrev'; +export default swapNextPrev(false); From 95f3258abbdc65a6c342714eff00a05c4939d218 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:04:08 +1100 Subject: [PATCH 010/120] refactor: remove unused parcelData.set argument --- .../dataparcels/src/parcelData/setSelf.js | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/packages/dataparcels/src/parcelData/setSelf.js b/packages/dataparcels/src/parcelData/setSelf.js index 2ad47a27..c3771f19 100644 --- a/packages/dataparcels/src/parcelData/setSelf.js +++ b/packages/dataparcels/src/parcelData/setSelf.js @@ -1,28 +1,21 @@ // @flow -import type {ParcelData} from '../types/Types'; +import type {ParcelDataEvaluator} from '../types/Types'; import isParentValue from './isParentValue'; import updateChild from './updateChild'; import updateChildKeys from './updateChildKeys'; import del from 'unmutable/lib/delete'; -import pipeWith from 'unmutable/lib/util/pipeWith'; +import set from 'unmutable/lib/set'; +import pipeIf from 'unmutable/lib/util/pipeIf'; +import pipe from 'unmutable/lib/util/pipe'; -export default (value: *, keepChild: boolean) => (parcelData: ParcelData): ParcelData => { - let result = { - ...parcelData, - value - }; - - result = keepChild ? result : del('child')(result); - - if(!isParentValue(value)) { - return result; - } - - return pipeWith( - result, +export default (value: *): ParcelDataEvaluator => pipe( + set('value', value), + del('child'), + pipeIf( + () => isParentValue(value), updateChild(), updateChildKeys() - ); -}; + ) +); From f3b99ae05da338c6d82d017cbdd647c103a93dc9 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:05:26 +1100 Subject: [PATCH 011/120] refactor: Add internal ParcelDataEvaluator flow type --- packages/dataparcels/src/types/Types.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index ca89b77f..9e6131c9 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -14,6 +14,8 @@ export type ParcelData = { meta?: ParcelMeta }; +export type ParcelDataEvaluator = (parcelData: ParcelData) => ParcelData; + export type ParcelConfig = { handleChange?: Function, value?: *, From 7d40f30925fc1acd5acc70f54036a3137707f0cc Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:06:42 +1100 Subject: [PATCH 012/120] feat: Add Action.keyPathModifiers to enable functions in actions --- packages/dataparcels/src/change/Action.js | 67 +++--- .../src/change/ActionKeyPathModifier.js | 55 +++++ .../src/change/__test__/Action-test.js | 199 +++++++++++++++++- .../src/util/__test__/GetAction-testUtil.js | 13 ++ 4 files changed, 289 insertions(+), 45 deletions(-) create mode 100644 packages/dataparcels/src/change/ActionKeyPathModifier.js create mode 100644 packages/dataparcels/src/util/__test__/GetAction-testUtil.js diff --git a/packages/dataparcels/src/change/Action.js b/packages/dataparcels/src/change/Action.js index 80e78616..afc2bc3b 100644 --- a/packages/dataparcels/src/change/Action.js +++ b/packages/dataparcels/src/change/Action.js @@ -1,43 +1,45 @@ // @flow +import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; -import has from 'unmutable/lib/has'; -import set from 'unmutable/lib/set'; import unshift from 'unmutable/lib/unshift'; +import update from 'unmutable/lib/update'; + +import ActionKeyPathModifier from './ActionKeyPathModifier'; type ActionData = { type?: string, payload?: Object, - keyPath?: Array + keyPath?: Array, + keyPathModifiers?: Array }; type CreateActionData = { type?: string, payload?: Object, - keyPath?: Array, - keyPathModifiers?: Array -}; - -type KeyPathModifiers = { - key?: Key, - pre?: Function, - post?: Function + keyPath?: Array, + keyPathModifiers?: Array }; export default class Action { type: string = ""; payload: Object = {}; - keyPath: Array = []; - keyPathModifiers: Array = []; + keyPath: Array = []; + keyPathModifiers: Array; + + constructor({type, payload, keyPath, keyPathModifiers}: ActionData = {}) { + + if(keyPathModifiers) { + this.keyPathModifiers = keyPathModifiers; + } else if(!this.keyPathModifiers && keyPath) { + this.keyPathModifiers = keyPath.map(key => new ActionKeyPathModifier({key})); + } else { + this.keyPathModifiers = []; + } - constructor({type, payload, keyPath}: ActionData = {}) { this.type = type || this.type; this.payload = payload || this.payload; this.keyPath = keyPath || this.keyPath; - - if(keyPath) { - this.keyPathModifiers = keyPath.map(key => ({key})); - } } _create = (create: CreateActionData): Action => { @@ -47,32 +49,29 @@ export default class Action { }); }; - _updateFirstKeyPathModifier = (obj: *, keyPathModifiers: Array): Array => { - let first = keyPathModifiers[0]; - let fn = (!first || !has("key")(first)) - ? unshift(obj) - : set(0, {...obj, ...first}); + _add = (updater: Function): Action => { + let fn = this.keyPathModifiers.length === 0 + ? unshift(updater(new ActionKeyPathModifier())) + : update(0, updater); - return fn(keyPathModifiers); + return this._create({ + keyPathModifiers: fn(this.keyPathModifiers) + }); }; _unget = (key: Key): Action => { return this._create({ - keyPath: unshift(key)(this.keyPath), - keyPathModifiers: this._updateFirstKeyPathModifier({key}, this.keyPathModifiers) + keyPathModifiers: unshift(new ActionKeyPathModifier()._addKey(key))(this.keyPathModifiers), + keyPath: unshift(key)(this.keyPath) }); }; - _addPre = (pre: Function) => { - return this._create({ - keyPathModifiers: this._updateFirstKeyPathModifier({pre}, this.keyPathModifiers) - }); + _addPre = (pre: Function): Action => { + return this._add(_ => _._addPre(pre)); }; - _addPost = (post: Function) => { - return this._create({ - keyPathModifiers: this._updateFirstKeyPathModifier({post}, this.keyPathModifiers) - }); + _addPost = (post: Function): Action => { + return this._add(_ => _._addPost(post)); }; shouldBeSynchronous = (): boolean => { diff --git a/packages/dataparcels/src/change/ActionKeyPathModifier.js b/packages/dataparcels/src/change/ActionKeyPathModifier.js new file mode 100644 index 00000000..816304d6 --- /dev/null +++ b/packages/dataparcels/src/change/ActionKeyPathModifier.js @@ -0,0 +1,55 @@ +// @flow +import type {Index} from '../types/Types'; +import type {Key} from '../types/Types'; + +import push from 'unmutable/lib/push'; +import unshift from 'unmutable/lib/unshift'; + +type ActionKeyPathModifierData = { + key?: Key|Index, + pre?: Function[], + post?: Function[] +}; + +export default class ActionKeyPathModifier { + key: ?Key|Index; + pre: Function[] = []; + post: Function[] = []; + + constructor({key, pre, post}: ActionKeyPathModifierData = {}) { + this.key = key !== undefined ? key : this.key; + this.pre = pre || this.pre; + this.post = post || this.post; + } + + _create = (create: ActionKeyPathModifierData): ActionKeyPathModifier => { + // $FlowFixMe + return new ActionKeyPathModifier({ + ...this.toJS(), + ...create + }); + }; + + _addKey = (key: Key|Index): ActionKeyPathModifier => { + return this._create({ + key + }); + }; + + _addPre = (pre: Function): ActionKeyPathModifier => { + return this._create({ + pre: unshift(pre)(this.pre) + }); + }; + + _addPost = (post: Function): ActionKeyPathModifier => { + return this._create({ + post: push(post)(this.post) + }); + }; + + toJS = (): any => { + let {key, pre, post} = this; + return {key, pre, post}; + }; +} diff --git a/packages/dataparcels/src/change/__test__/Action-test.js b/packages/dataparcels/src/change/__test__/Action-test.js index a081b10b..7fed22b1 100644 --- a/packages/dataparcels/src/change/__test__/Action-test.js +++ b/packages/dataparcels/src/change/__test__/Action-test.js @@ -1,33 +1,35 @@ // @flow import Action from '../Action'; +import ActionKeyPathModifier from '../ActionKeyPathModifier'; test('Action should build an action', () => { let expectedDefaultData = { type: "", payload: {}, - keyPath: [] + keyPath: [], + keyPathModifiers: [] }; - expect(expectedDefaultData).toEqual(new Action().toJS()); + expect(new Action().toJS()).toEqual(expectedDefaultData); }); test('Action should build an action with a type', () => { - expect("???").toBe(new Action({type: "???"}).type); + expect(new Action({type: "???"}).type).toBe("???"); }); test('Action should build an action with a payload', () => { - expect({a: 1}).toEqual(new Action({type: "???", payload: {a: 1}}).payload); + expect(new Action({type: "???", payload: {a: 1}}).payload).toEqual({a: 1}); }); test('Action should build an action with a default payload', () => { - expect({}).toEqual(new Action({type: "???"}).payload); + expect(new Action({type: "???"}).payload).toEqual({}); }); test('Action should build an action with a keyPath', () => { - expect(['a', 'b']).toEqual(new Action({type: "???", keyPath: ['a', 'b']}).keyPath); + expect(new Action({type: "???", keyPath: ['a', 'b']}).keyPath).toEqual(['a', 'b']); }); test('Action should build an action with a default keyPath', () => { - expect([]).toEqual(new Action({type: "???"}).keyPath); + expect(new Action({type: "???"}).keyPath).toEqual([]); }); test('Action should be synchronous if it has a type of ping, else not', () => { @@ -36,22 +38,197 @@ test('Action should be synchronous if it has a type of ping, else not', () => { expect(new Action({type: "???"}).shouldBeSynchronous()).toBe(false); }); -test('Action should unshift key to front of keyPath when ungetting', () => { +test('Action _unget should unshift key to front of empty keyPath', () => { let action = { + type: "woo", + payload: {abc: 123}, + keyPath: [], + keyPathModifiers: [] + }; + + let {keyPath, keyPathModifiers} = new Action(action) + ._unget('a') + .toJS(); + + expect(keyPath).toEqual(['a']); + expect(keyPathModifiers.map(_ => _.toJS())).toEqual([ + {key: "a", pre: [], post: []} + ]); +}); + +test('Action _unget should unshift key to front of keyPath', () => { + let action = { type: "woo", payload: {abc: 123}, keyPath: ['a'] }; - let expectedAction = { + let {keyPath, keyPathModifiers} = new Action(action) + ._unget('b') + .toJS(); + + expect(keyPath).toEqual(['b', 'a']); + expect(keyPathModifiers.map(_ => _.toJS())).toEqual([ + {key: "b", pre: [], post: []}, + {key: "a", pre: [], post: []} + ]); +}); + +test('Action _unget should unshift key into new keypathmodifier where pre already exists', () => { + let fn = ii => ii; + + let action = { + type: "woo", + payload: {abc: 123}, + keyPath: [], + keyPathModifiers: [ + new ActionKeyPathModifier({key: undefined, pre: [fn]}) + ] + }; + + let {keyPath, keyPathModifiers} = new Action(action) + ._unget('a') + .toJS(); + + expect(keyPath).toEqual(['a']); + expect(keyPathModifiers.map(_ => _.toJS())).toEqual([ + {key: "a", pre: [], post: []}, + {key: undefined, pre: [fn], post: []} + ]); +}); + +test('Action _addPre and _addPost should put pre and post functions in empty keyPathModifiers', () => { + let action = { + type: "woo", + payload: {abc: 123}, + keyPath: [] + }; + + let pre = ii => ii; + let post = ii => ii; + + let withPre = new Action(action) + ._addPre(pre) + .toJS() + .keyPathModifiers; + + let withPost = new Action(action) + ._addPost(post) + .toJS() + .keyPathModifiers; + + expect(withPre.map(_ => _.toJS())).toEqual([ + {key: undefined, pre: [pre], post: []} + ]); + + expect(withPost.map(_ => _.toJS())).toEqual([ + {key: undefined, post: [post], pre: []} + ]); +}); + +test('Action _addPre and _addPost should put pre and post functions into first keyPathModifiers', () => { + let action = { + type: "woo", + payload: {abc: 123}, + keyPath: ['a'], + keyPathModifiers: [ + new ActionKeyPathModifier({key: 'a'}) + ] + }; + + let pre = ii => ii; + let post = ii => ii; + + let withPre = new Action(action) + ._addPre(pre) + .toJS() + .keyPathModifiers; + + let withPost = new Action(action) + ._addPost(post) + .toJS() + .keyPathModifiers; + + expect(withPre.map(_ => _.toJS())).toEqual([ + {key: 'a', pre: [pre], post: []} + ]); + + expect(withPost.map(_ => _.toJS())).toEqual([ + {key: 'a', pre: [], post: [post]} + ]); +}); + +test('Action _addPre and _addPost should put pre and post functions in same keyPathModifiers', () => { + let action = { + type: "woo", + payload: {abc: 123}, + keyPath: ['a'], + keyPathModifiers: [ + new ActionKeyPathModifier({key: 'a'}) + ] + }; + + let pre = ii => ii; + let post = ii => ii; + + let withPreAndPost = new Action(action) + ._addPre(pre) + ._addPost(post) + .toJS() + .keyPathModifiers; + + expect(withPreAndPost.map(_ => _.toJS())).toEqual([ + {key: 'a', post: [post], pre: [pre]} + ]); +}); + +test('Action _addPre twice should put pre functions in same keyPathModifiers, in reverse order', () => { + let action = { type: "woo", payload: {abc: 123}, - keyPath: ['b', 'a'] + keyPath: ['a'], + keyPathModifiers: [ + new ActionKeyPathModifier({key: 'a'}) + ] }; - expect(expectedAction).toEqual(new Action(action)._unget('b').toJS()); + let pre = ii => ii; + let pre2 = ii => ii; + + let withPre = new Action(action) + ._addPre(pre) + ._addPre(pre2) + .toJS() + .keyPathModifiers; + + expect(withPre.map(_ => _.toJS())).toEqual([ + {key: 'a', post: [], pre: [pre2, pre]} + ]); }); +test('Action _addPost twice should put post functions in same keyPathModifiers', () => { + let action = { + type: "woo", + payload: {abc: 123}, + keyPath: ['a'], + keyPathModifiers: [ + new ActionKeyPathModifier({key: 'a'}) + ] + }; + + let post = ii => ii; + let post2 = ii => ii; + + let withPost = new Action(action) + ._addPost(post) + ._addPost(post2) + .toJS() + .keyPathModifiers; + + expect(withPost.map(_ => _.toJS())).toEqual([ + {key: 'a', post: [post, post2], pre: []} + ]); +}); test('Action should be value action if it isnt ping or setMeta', () => { expect(new Action({type: "ping"}).isValueAction()).toBe(false); expect(new Action({type: "set"}).isValueAction()).toBe(true); diff --git a/packages/dataparcels/src/util/__test__/GetAction-testUtil.js b/packages/dataparcels/src/util/__test__/GetAction-testUtil.js new file mode 100644 index 00000000..7574fe81 --- /dev/null +++ b/packages/dataparcels/src/util/__test__/GetAction-testUtil.js @@ -0,0 +1,13 @@ +// @flow + +import del from 'unmutable/lib/delete'; +import first from 'unmutable/lib/first'; +import method from 'unmutable/lib/method'; +import pipe from 'unmutable/lib/util/pipe'; + +export default pipe( + method('actions')(), + first(), + method('toJS')(), + del('keyPathModifiers') +); From 27ec6441d4df3cb8d92605bd6c4a024757dcdbd7 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:07:36 +1100 Subject: [PATCH 013/120] refactor: remove needless todo comment --- packages/dataparcels/src/change/__test__/ChangeRequest-test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js index 2fcd4336..80907399 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js @@ -52,8 +52,6 @@ test('ChangeRequest merge() should merge other change requests actions', () => { let merged = a.merge(b); expect([...actionsA, ...actionsB]).toEqual(merged.actions()); - - // TODO - test originId, originPath and meta }); From 3cae540437363203a744870022d95460f7b0e6fd Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:08:11 +1100 Subject: [PATCH 014/120] feat: Adjust tests to cope with keyPathModifiers --- .../__test__/ElementParcelMethods-test.js | 18 ++++++----- .../__test__/IndexedParcelMethods-test.js | 32 ++++++++++--------- .../__test__/ParcelChangeMethods-test.js | 13 ++++---- .../parcel/__test__/ParentGetMethods-test.js | 7 ++-- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js b/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js index f8aa95c8..13bcf938 100644 --- a/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js @@ -1,6 +1,8 @@ // @flow import Parcel from '../Parcel'; +import GetAction from '../../util/__test__/GetAction-testUtil'; + test('ElementParcel.insertBefore() should insert', () => { expect.assertions(4); @@ -37,7 +39,7 @@ test('ElementParcel.insertBefore() should insert', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get(1) @@ -47,7 +49,7 @@ test('ElementParcel.insertBefore() should insert', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get("#b") @@ -90,7 +92,7 @@ test('ElementParcel.insertAfter() should insert', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get(1) @@ -100,7 +102,7 @@ test('ElementParcel.insertAfter() should insert', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get("#b") @@ -142,7 +144,7 @@ test('ElementParcel.swap() should swap', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get(0) @@ -182,7 +184,7 @@ test('ElementParcel.swapNext() should swapNext', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get(0) @@ -198,7 +200,7 @@ test('ElementParcel.swapNext() should swapNext', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swapNext("#a"); }); @@ -237,7 +239,7 @@ test('ElementParcel.swapPrev() should swapPrev', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }) .get("#b") diff --git a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js index e01319bf..bdb6ce73 100644 --- a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js @@ -1,6 +1,8 @@ // @flow import Parcel from '../Parcel'; +import GetAction from '../../util/__test__/GetAction-testUtil'; + test('IndexedParcel.delete() should delete', () => { var data = { @@ -42,9 +44,9 @@ test('IndexedParcel.delete() should delete', () => { }).delete("#a"); expect(indexedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(indexedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedAction); + expect(GetAction(indexedHandleChange.mock.calls[0][1])).toEqual(expectedAction); expect(keyedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(keyedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedAction); + expect(GetAction(keyedHandleChange.mock.calls[0][1])).toEqual(expectedAction); }); @@ -124,9 +126,9 @@ test('IndexedParcel.insertBefore() should insertBefore', () => { }).insertBefore("#b", 4); expect(indexedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(indexedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedAction); + expect(GetAction(indexedHandleChange.mock.calls[0][1])).toEqual(expectedAction); expect(keyedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(keyedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedActionWithKey); + expect(GetAction(keyedHandleChange.mock.calls[0][1])).toEqual(expectedActionWithKey); }); @@ -183,9 +185,9 @@ test('IndexedParcel.insertAfter() should insertAfter', () => { }).insertAfter("#b", 4); expect(indexedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(indexedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedAction); + expect(GetAction(indexedHandleChange.mock.calls[0][1])).toEqual(expectedAction); expect(keyedHandleChange.mock.calls[0][0].data).toEqual(expectedData); - expect(keyedHandleChange.mock.calls[0][1].actions()[0].toJS()).toEqual(expectedActionWithKey); + expect(GetAction(keyedHandleChange.mock.calls[0][1])).toEqual(expectedActionWithKey); }); test('IndexedParcel.push() should push', () => { @@ -224,7 +226,7 @@ test('IndexedParcel.push() should push', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).push(4); }); @@ -261,7 +263,7 @@ test('IndexedParcel.pop() should pop', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).pop(); }); @@ -298,7 +300,7 @@ test('IndexedParcel.shift() should shift', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).shift(); }); @@ -338,7 +340,7 @@ test('IndexedParcel.swap() should swap', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swap(0,2); }); @@ -376,7 +378,7 @@ test('IndexedParcel.swapNext() should swapNext', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swapNext(0); @@ -390,7 +392,7 @@ test('IndexedParcel.swapNext() should swapNext', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swapNext("#a"); }); @@ -429,7 +431,7 @@ test('IndexedParcel.swapPrev() should swapPrev', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swapPrev(1); @@ -443,7 +445,7 @@ test('IndexedParcel.swapPrev() should swapPrev', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).swapPrev("#b"); }); @@ -484,7 +486,7 @@ test('IndexedParcel.unshift() should unshift', () => { ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).unshift(4); }); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 031262ae..cf50d4f3 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -1,5 +1,6 @@ // @flow import Parcel from '../Parcel'; +import GetAction from '../../util/__test__/GetAction-testUtil'; test('Parcel.set() should call the Parcels handleChange function with the new parcelData', () => { expect.assertions(3); @@ -28,7 +29,7 @@ test('Parcel.set() should call the Parcels handleChange function with the new pa handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); expect(expectedData).toEqual(changeRequest.nextData); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).set(456); }); @@ -95,7 +96,7 @@ test('Parcel.update() should call the Parcels handleChange function with the new ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).update((ii) => { expect(expectedArg).toEqual(ii); @@ -129,7 +130,7 @@ test('Parcel.onChange() should work like set that only accepts a single argument ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).onChange(456); }); @@ -160,7 +161,7 @@ test('Parcel.onChangeDOM() should work like onChange but take the value from eve ...data, handleChange: (parcel, changeRequest) => { expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }).onChangeDOM({ currentTarget: { @@ -204,7 +205,7 @@ test('Parcel.setMeta() should call the Parcels handleChange function with the ne if(changes === 1) { expect(expectedMeta).toEqual(parcel.meta); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); parcel.setMeta({ def: 456 }); @@ -253,7 +254,7 @@ test('Parcel.updateMeta() should call the Parcels handleChange function with the if(changes === 1) { expect(expectedMeta).toEqual(parcel.meta); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); parcel.updateMeta(meta => { expect({abc: 123}).toEqual(meta) return { diff --git a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js index a3d9db88..8454123c 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js @@ -1,6 +1,7 @@ // @flow import Parcel from '../Parcel'; import TestTimeExecution from '../../util/__test__/TestTimeExecution-testUtil'; +import GetAction from '../../util/__test__/GetAction-testUtil'; import map from 'unmutable/lib/map'; import range from 'unmutable/lib/util/range'; @@ -37,7 +38,7 @@ test('ParentParcel.get(key) should return a new child Parcel', () => { b: 4 }, handleChange: (parcel, changeRequest) => { - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); expect(expectedValue).toEqual(parcel.value); } }; @@ -125,7 +126,7 @@ test('ParentParcel.get(key).get(key) should return a new child Parcel and chain }, handleChange: (parcel, changeRequest) => { expect(parcel.value).toEqual(expectedValue); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }; @@ -214,7 +215,7 @@ test('ParentParcel.getIn(keyPath) should return a new descendant Parcel', () => }, handleChange: (parcel, changeRequest) => { expect(parcel.value).toEqual(expectedValue); - expect(expectedAction).toEqual(changeRequest.actions()[0].toJS()); + expect(expectedAction).toEqual(GetAction(changeRequest)); } }; From a28e85df91d887e47cdb100a417da84ced05c0e4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:08:36 +1100 Subject: [PATCH 015/120] refactor: replace Reducer with ChangeRequestReducer --- .../dataparcels/src/change/ChangeRequest.js | 21 +- .../src/change/ChangeRequestReducer.js | 96 +++++++ packages/dataparcels/src/change/Reducer.js | 175 ------------- .../__test__/ChangeRequestReducer-test.js | 234 ++++++++++++++++++ ....js => ChangeRequestReducerDelete-test.js} | 21 +- ...js => ChangeRequestReducerIndexed-test.js} | 18 +- .../__test__/ChangeRequestReducerPing-test.js | 33 +++ ...est.js => ChangeRequestReducerSet-test.js} | 41 +-- ...js => ChangeRequestReducerSetMeta-test.js} | 25 +- .../src/change/__test__/Reducer-test.js | 14 -- .../src/change/__test__/ReducerPing-test.js | 26 -- .../src/parcelData/__test__/update-test.js | 73 ++++++ packages/dataparcels/src/parcelData/update.js | 67 +++++ 13 files changed, 586 insertions(+), 258 deletions(-) create mode 100644 packages/dataparcels/src/change/ChangeRequestReducer.js delete mode 100644 packages/dataparcels/src/change/Reducer.js create mode 100644 packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js rename packages/dataparcels/src/change/__test__/{ReducerDelete-test.js => ChangeRequestReducerDelete-test.js} (60%) rename packages/dataparcels/src/change/__test__/{ReducerIndexed-test.js => ChangeRequestReducerIndexed-test.js} (93%) create mode 100644 packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js rename packages/dataparcels/src/change/__test__/{ReducerSet-test.js => ChangeRequestReducerSet-test.js} (83%) rename packages/dataparcels/src/change/__test__/{ReducerSetMeta-test.js => ChangeRequestReducerSetMeta-test.js} (71%) delete mode 100644 packages/dataparcels/src/change/__test__/Reducer-test.js delete mode 100644 packages/dataparcels/src/change/__test__/ReducerPing-test.js create mode 100644 packages/dataparcels/src/parcelData/__test__/update-test.js create mode 100644 packages/dataparcels/src/parcelData/update.js diff --git a/packages/dataparcels/src/change/ChangeRequest.js b/packages/dataparcels/src/change/ChangeRequest.js index 58aff85c..c83cc4fc 100644 --- a/packages/dataparcels/src/change/ChangeRequest.js +++ b/packages/dataparcels/src/change/ChangeRequest.js @@ -1,12 +1,13 @@ // @flow import type Parcel from '../parcel/Parcel'; import type {Key} from '../types/Types'; +import type {Index} from '../types/Types'; import type {ParcelData} from '../types/Types'; import type Action from './Action'; import {ReadOnlyError} from '../errors/Errors'; import {ChangeRequestUnbasedError} from '../errors/Errors'; -import Reducer from '../change/Reducer'; +import ChangeRequestReducer from '../change/ChangeRequestReducer'; import parcelGet from '../parcelData/get'; import pipe from 'unmutable/lib/util/pipe'; @@ -36,12 +37,24 @@ export default class ChangeRequest { return changeRequest; }; - _unget = (key: Key): ChangeRequest => { + _createMapActions = (updater: Function): ChangeRequest => { return this._create({ - actions: this._actions.map(ii => ii._unget(key)) + actions: this._actions.map(updater) }); }; + _unget = (key: Key): ChangeRequest => { + return this._createMapActions(ii => ii._unget(key)); + }; + + _addPre = (pre: Function): ChangeRequest => { + return this._createMapActions(ii => ii._addPre(pre)); + }; + + _addPost = (post: Function): ChangeRequest => { + return this._createMapActions(ii => ii._addPost(post)); + }; + _setBaseParcel = (baseParcel: Parcel): ChangeRequest => { return this._create({ baseParcel @@ -65,7 +78,7 @@ export default class ChangeRequest { .get(this._baseParcel._id.id()) .data; - let data = Reducer(parcelDataFromRegistry, this._actions); + let data = ChangeRequestReducer(this)(parcelDataFromRegistry); this._cachedData = data; return data; } diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js new file mode 100644 index 00000000..57b4e61a --- /dev/null +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -0,0 +1,96 @@ +// @flow +import type ChangeRequest from './ChangeRequest'; +import type Action from './Action'; +import type {ParcelDataEvaluator} from '../types/Types'; + +import butLast from 'unmutable/lib/butLast'; +import identity from 'unmutable/lib/identity'; +import last from 'unmutable/lib/last'; +import pipe from 'unmutable/lib/util/pipe'; +import composeWith from 'unmutable/lib/util/composeWith'; + +import {ReducerInvalidActionError} from '../errors/Errors'; +import {ReducerSwapKeyError} from '../errors/Errors'; + +import del from '../parcelData/delete'; +import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; +import insertAfter from '../parcelData/insertAfter'; +import insertBefore from '../parcelData/insertBefore'; +import pop from '../parcelData/pop'; +import push from '../parcelData/push'; +import setMeta from '../parcelData/setMeta'; +import setSelf from '../parcelData/setSelf'; +import shift from '../parcelData/shift'; +import swap from '../parcelData/swap'; +import swapNext from '../parcelData/swapNext'; +import swapPrev from '../parcelData/swapPrev'; +import unshift from '../parcelData/unshift'; +import update from '../parcelData/update'; + +const actionMap = { + delete: ({lastKey}) => del(lastKey), + insertAfter: ({lastKey, value}) => insertAfter(lastKey, value), + insertBefore: ({lastKey, value}) => insertBefore(lastKey, value), + ping: () => identity(), + pop: () => pop(), + push: ({value}) => push(value), + setMeta: ({meta}) => setMeta(meta), + set: ({value}) => setSelf(value), + shift: () => shift(), + swap: ({lastKey, swapKey}) => { + if(typeof swapKey === "undefined") { + throw ReducerSwapKeyError(); + } + return swap(lastKey, swapKey); + }, + swapNext: ({lastKey}) => swapNext(lastKey), + swapPrev: ({lastKey}) => swapPrev(lastKey), + unshift: ({value}) => unshift(value) +}; + +const parentActionMap = { + delete: true, + insertAfter: true, + insertBefore: true, + swap: true, + swapNext: true, + swapPrev: true +}; + +const doAction = ({keyPath, type, payload}: Action): ParcelDataEvaluator => { + let fn = actionMap[type]; + if(!fn) { + throw ReducerInvalidActionError(type); + } + return fn({ + ...payload, + lastKey: last()(keyPath) + }); +}; + +const doDeepAction = (action: Action): ParcelDataEvaluator => { + let {keyPathModifiers, type} = action; + let parentActionEmpty: ?Function = parentActionMap[type]; + + if(parentActionEmpty) { + if(action.keyPath.length === 0) { + return type === "delete" ? deleteSelfWithMarker : identity(); + } + keyPathModifiers = butLast()(keyPathModifiers); + } + + return composeWith( + ...keyPathModifiers.map(({key, pre, post}) => (next) => pipe( + ...pre, + (key || key === 0) ? update(key, next) : next, + ...post + )), + doAction(action) + ); +}; + +export default (changeRequest: ChangeRequest): ParcelDataEvaluator => pipe( + ...changeRequest + .actions() + .map(doDeepAction) +); diff --git a/packages/dataparcels/src/change/Reducer.js b/packages/dataparcels/src/change/Reducer.js deleted file mode 100644 index 28fc7b14..00000000 --- a/packages/dataparcels/src/change/Reducer.js +++ /dev/null @@ -1,175 +0,0 @@ -// @flow -import type {Index} from '../types/Types'; -import type {Key} from '../types/Types'; -import type {ParcelData} from '../types/Types'; - -import {ReducerInvalidActionError} from '../errors/Errors'; -import {ReducerSwapKeyError} from '../errors/Errors'; - -import butLast from 'unmutable/lib/butLast'; -import isEmpty from 'unmutable/lib/isEmpty'; -import last from 'unmutable/lib/last'; - -import parcelDelete from '../parcelData/delete'; -import parcelDeleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; -import parcelInsert from '../parcelData/insert'; - -import parcelPop from '../parcelData/pop'; -import parcelPush from '../parcelData/push'; -import parcelSetMeta from '../parcelData/setMeta'; -import parcelSetSelf from '../parcelData/setSelf'; -import parcelShift from '../parcelData/shift'; -import parcelSwap from '../parcelData/swap'; -import parcelSwapNextPrev from '../parcelData/swapNextPrev'; -import parcelUnshift from '../parcelData/unshift'; -import parcelUpdateIn from '../parcelData/updateIn'; - -import Action from './Action'; - -export default function MultiReducer(parcelData: ParcelData, action: Action|Action[]): ParcelData { - let actionArray: Action[] = Array.isArray(action) ? action : [action]; - let reduced: ParcelData = actionArray.reduce(Reducer, parcelData); - return { - value: undefined, - ...reduced - }; -} - -function Reducer(parcelData: ParcelData, action: Action|Action[]): ParcelData { - if(!(action instanceof Action)) { - throw Error(`Reducer must receive an Action`); - } - - let { - keyPath, - payload: { - value, - meta - }, - type - } = action; - - let keyPathLast: Key|Index = last()(keyPath); - let keyPathButLast: Array = butLast()(keyPath); - let keyPathIsEmpty: boolean = isEmpty()(keyPath); - - let updateIn = (keyPath, updater) => parcelUpdateIn(keyPath, updater)(parcelData); - - switch(type) { - case "delete": { - if(keyPathIsEmpty) { - return parcelDeleteSelfWithMarker(); - } - return updateIn( - keyPathButLast, - parcelDelete(keyPathLast) - ); - } - - case "insertAfter": { - if(keyPathIsEmpty) { - return parcelData; - } - return updateIn( - keyPathButLast, - parcelInsert(keyPathLast, value, true) - ); - } - - case "insertBefore": { - if(keyPathIsEmpty) { - return parcelData; - } - return updateIn( - keyPathButLast, - parcelInsert(keyPathLast, value, false) - ); - } - - case "ping": { - return parcelData; - } - - case "pop": { - return updateIn( - keyPath, - parcelPop() - ); - } - - case "push": { - return updateIn( - keyPath, - parcelPush(value) - ); - } - - case "set": { - return updateIn( - keyPath, - parcelSetSelf(value, false) - ); - - } - - case "setMeta": { - return updateIn( - keyPath, - parcelSetMeta(meta) - ); - } - - case "shift": { - return updateIn( - keyPath, - parcelShift() - ); - } - - case "swap": { - if(keyPathIsEmpty) { - return parcelData; - } - let {swapKey} = action.payload; - if(typeof swapKey === "undefined") { - throw ReducerSwapKeyError(); - } - - return updateIn( - keyPathButLast, - parcelSwap(keyPathLast, swapKey) - ); - } - - case "swapNext": { - if(keyPathIsEmpty) { - return parcelData; - } - - return updateIn( - keyPathButLast, - parcelSwapNextPrev(keyPathLast, true) - ); - } - - case "swapPrev": { - if(keyPathIsEmpty) { - return parcelData; - } - - return updateIn( - keyPathButLast, - parcelSwapNextPrev(keyPathLast, false) - ); - } - - case "unshift": { - return updateIn( - keyPath, - parcelUnshift(value) - ); - } - } - - throw ReducerInvalidActionError(type); -} diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js new file mode 100644 index 00000000..9cbcef7e --- /dev/null +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js @@ -0,0 +1,234 @@ +// @flow +import ActionCreators from '../ActionCreators'; +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; +import Action from '../Action'; + +import push from 'unmutable/lib/push'; +import update from 'unmutable/lib/update'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +const makeReducer = (actions) => pipeWith( + new ChangeRequest(actions), + ChangeRequestReducer +); + +test('ChangeRequestReducer should pass through with no actions', () => { + var data = { + value: 123, + key: "^", + child: undefined + }; + + let actions = []; + + expect(makeReducer(actions)(data)).toEqual(data); +}); + +test('ChangeRequestReducer should process a single "set" action', () => { + var data = { + value: 123, + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators.setSelf(456) + ]; + + let expectedData = { + ...data, + value: 456 + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process two "set" actions', () => { + var data = { + value: 123, + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators.setSelf(456), + ActionCreators.setSelf(789) + ]; + + let expectedData = { + ...data, + value: 789 + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process single "push" action', () => { + var data = { + value: ["A"], + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators.push("B") + ]; + + let expectedData = { + ...data, + value: ["A","B"], + child: [{key: '#a'}, {key: '#b'}] + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process single "push" action with pre functions', () => { + var data = { + value: ["A"], + key: "^", + child: undefined + }; + + let pushValue = (newValue) => update('value', push(newValue)) + let pre1 = jest.fn(pushValue("1")); + let pre2 = jest.fn(pushValue("2")); + + let actions = [ + ActionCreators + .push("B") + ._addPre(pre1) + ._addPre(pre2) + ]; + + let expectedData = { + ...data, + value: ["A","2","1","B"], + child: [{key: '#a'}, {key: '#b'}, {key: '#c'}, {key: '#d'}] + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process single "push" action with post functions', () => { + var data = { + value: ["A"], + key: "^", + child: undefined + }; + + let pushValue = (newValue) => update('value', push(newValue)) + let post1 = jest.fn(pushValue("1")); + let post2 = jest.fn(pushValue("2")); + + let actions = [ + ActionCreators + .push("B") + ._addPost(post1) + ._addPost(post2) + ]; + + let expectedData = { + ...data, + value: ["A","B","1","2"], + child: [{key: '#a'}, {key: '#b'}] + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process a single "set" action at a depth of 1', () => { + var data = { + value: {abc: 123}, + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators + .setSelf(456) + ._unget('abc') + ]; + + let expectedData = { + ...data, + value: {abc: 456}, + child: { + abc: { + child: undefined, + key: "abc" + } + } + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process a single "set" action at a depth of 2', () => { + var data = { + value: { + abc: { + def: 123 + } + }, + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators + .setSelf(456) + ._unget('def') + ._unget('abc') + ]; + + let expectedData = { + ...data, + value: { + abc: { + def: 456 + } + }, + child: { + abc: { + child: { + def: { + child: undefined, + key: "def" + } + }, + key: "abc" + } + } + }; + + expect(makeReducer(actions)(data)).toEqual(expectedData); +}); + +test('ChangeRequestReducer should process aa complicated bunch of pre and post functions', () => { + var data = { + value: {abc: 123}, + key: "^", + child: undefined + }; + + let actions = [ + ActionCreators + .setSelf(456) + ._addPost(update('value', value => value + 1)) // 456 -> 457 + ._unget('abc') + ._addPost(update('value', value => ({...value, alsoAlso: value.abc}))) // {abc: 457, also: 788} -> {abc: 457, also: 788, alsoAlso: 457} + ._addPre(update('value', update('also', also => also - 1))) // {abc: 123} -> {abc: 123, also: 788} + ._addPre(update('value', value => ({...value, also: 789}))) // {abc: 123} -> {abc: 123, also: 789} + // wierdly, looking at this syntax, the value starts at the bottom and goes up + ]; + + let expectedValue = { + abc: 457, + also: 788, + alsoAlso: 457 + }; + + expect(makeReducer(actions)(data).value).toEqual(expectedValue); +}); diff --git a/packages/dataparcels/src/change/__test__/ReducerDelete-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerDelete-test.js similarity index 60% rename from packages/dataparcels/src/change/__test__/ReducerDelete-test.js rename to packages/dataparcels/src/change/__test__/ChangeRequestReducerDelete-test.js index 16ae340a..31d700ca 100644 --- a/packages/dataparcels/src/change/__test__/ReducerDelete-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerDelete-test.js @@ -1,9 +1,16 @@ // @flow -import Reducer from '../Reducer'; +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; import Action from '../Action'; import DeletedParcelMarker from '../../parcelData/DeletedParcelMarker'; +import pipeWith from 'unmutable/lib/util/pipeWith'; -test('Reducer should delete key', () => { +const makeReducer = (action) => pipeWith( + new ChangeRequest(action), + ChangeRequestReducer +); + +test('ChangeRequestReducer should delete key', () => { var data = { value: { a: 1, @@ -21,10 +28,10 @@ test('Reducer should delete key', () => { b: 2 }; - expect(Reducer(data, action).value).toEqual(expectedValue); + expect(makeReducer(action)(data).value).toEqual(expectedValue); }); -test('Reducer should delete deep key', () => { +test('ChangeRequestReducer should delete deep key', () => { var data = { value: { a: { @@ -48,10 +55,10 @@ test('Reducer should delete deep key', () => { c: 3 }; - expect(Reducer(data, action).value).toEqual(expectedValue); + expect(makeReducer(action)(data).value).toEqual(expectedValue); }); -test('Reducer should set value to DeletedParcelMarker symbol if deleted with no keypath', () => { +test('ChangeRequestReducer should set value to DeletedParcelMarker symbol if deleted with no keypath', () => { var data = { value: { a: 1, @@ -69,5 +76,5 @@ test('Reducer should set value to DeletedParcelMarker symbol if deleted with no value: DeletedParcelMarker }; - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); diff --git a/packages/dataparcels/src/change/__test__/ReducerIndexed-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js similarity index 93% rename from packages/dataparcels/src/change/__test__/ReducerIndexed-test.js rename to packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js index 68f3d3bd..3b2a2dfe 100644 --- a/packages/dataparcels/src/change/__test__/ReducerIndexed-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js @@ -1,7 +1,13 @@ // @flow - -import Reducer from '../Reducer'; +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; import Action from '../Action'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +const makeReducer = (action) => pipeWith( + new ChangeRequest(action), + ChangeRequestReducer +); let data = { value: [0,1,2], @@ -22,7 +28,7 @@ let EXPECTED_KEY_AND_META = { "swapPrev" ].forEach((type: string) => { test(`Reducer ${type} action should return unchanged parcelData if keyPath is empty`, () => { - expect(Reducer(data, new Action({type}))).toEqual(data); + expect(makeReducer(new Action({type}))(data)).toEqual(data); }); }); @@ -32,12 +38,12 @@ test('Reducer swap action should throw error if payload.swapKey doesnt exist', ( keyPath: [0] }); - expect(() => Reducer(data, action)).toThrowError(`swap actions must have a swapKey in their payload`); + expect(() => makeReducer(action)(data)).toThrowError(`swap actions must have a swapKey in their payload`); }); const TestIndex = (arr) => arr.map(({action, expectedData}) => { test(`Reducer ${action.type} action should ${action.type} with keyPath ${JSON.stringify(action.keyPath)}`, () => { - expect(Reducer(data, new Action(action))).toEqual(expectedData); + expect(makeReducer(new Action(action))(data)).toEqual(expectedData); }); let deepAction = { @@ -75,7 +81,7 @@ const TestIndex = (arr) => arr.map(({action, expectedData}) => { }; test(`Reducer ${action.type} action should ${action.type} deeply with keyPath ${JSON.stringify(deepAction.keyPath)}`, () => { - expect(Reducer(deepData, new Action(deepAction))).toEqual(deepExpectedData); + expect(makeReducer(new Action(deepAction))(deepData)).toEqual(deepExpectedData); }); }); diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js new file mode 100644 index 00000000..7dea799a --- /dev/null +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js @@ -0,0 +1,33 @@ +// @flow +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; +import Action from '../Action'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +const makeReducer = (action) => pipeWith( + new ChangeRequest(action), + ChangeRequestReducer +); + +test('ChangeRequestReducer should ping', () => { + var data = { + value: [ + 0, + 1, + 2 + ], + key: "^", + child: undefined + }; + var action = new Action({ + type: "ping" + }); + + var expectedValue = [ + 0, + 1, + 2 + ]; + expect(makeReducer(action)(data).value).toEqual(expectedValue); +}); + diff --git a/packages/dataparcels/src/change/__test__/ReducerSet-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerSet-test.js similarity index 83% rename from packages/dataparcels/src/change/__test__/ReducerSet-test.js rename to packages/dataparcels/src/change/__test__/ChangeRequestReducerSet-test.js index 524e5dfb..1ae27916 100644 --- a/packages/dataparcels/src/change/__test__/ReducerSet-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerSet-test.js @@ -1,8 +1,15 @@ // @flow -import Reducer from '../Reducer'; +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; import Action from '../Action'; +import pipeWith from 'unmutable/lib/util/pipeWith'; -test('Reducer should set with empty keyPath', () => { +const makeReducer = (action) => pipeWith( + new ChangeRequest(action), + ChangeRequestReducer +); + +test('ChangeRequestReducer should set with empty keyPath', () => { var data = { value: 123, meta: { @@ -27,10 +34,10 @@ test('Reducer should set with empty keyPath', () => { // value should be replaced // key and meta should be untouched - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set with empty keyPath and clear existing child', () => { +test('ChangeRequestReducer should set with empty keyPath and clear existing child', () => { var data = { value: { a: { @@ -75,10 +82,10 @@ test('Reducer should set with empty keyPath and clear existing child', () => { // value should be replaced // key and meta should be untouched // child should be removed - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set with keyPath of 1 element', () => { +test('ChangeRequestReducer should set with keyPath of 1 element', () => { var data = { value: { a: 1, @@ -127,10 +134,10 @@ test('Reducer should set with keyPath of 1 element', () => { // value should be replaced at keypath // key and meta should be untouched // top level child should be kept - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should clear child from set key', () => { +test('ChangeRequestReducer should clear child from set key', () => { var data = { value: { a: { @@ -192,10 +199,10 @@ test('Reducer should clear child from set key', () => { // child should be removed at keyPath // top level key and meta should be untouched // child.b.meta should be untouched - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set with keyPath of 2 elements', () => { +test('ChangeRequestReducer should set with keyPath of 2 elements', () => { var data = { value: { a: {}, @@ -251,10 +258,10 @@ test('Reducer should set with keyPath of 2 elements', () => { // value should be replaced at keypath // key and meta should be untouched // top level child should be kept - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set with keyPath of 2 elements on arrays', () => { +test('ChangeRequestReducer should set with keyPath of 2 elements on arrays', () => { var data = { value: [ [], @@ -307,10 +314,10 @@ test('Reducer should set with keyPath of 2 elements on arrays', () => { // key and meta should be untouched // top level child should be kept // keys should be generated for existing value, and for newly set value - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set with an unkeyed array and give it keys', () => { +test('ChangeRequestReducer should set with an unkeyed array and give it keys', () => { var data = { value: 9, meta: { @@ -351,10 +358,10 @@ test('Reducer should set with an unkeyed array and give it keys', () => { // key and meta should be untouched // top level child should be kept // keys should be generated for newly set value - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); -test('Reducer should set (with a keyPath) with an unkeyed array and give it keys', () => { +test('ChangeRequestReducer should set (with a keyPath) with an unkeyed array and give it keys', () => { var data = { value: { a: [0,0,0] @@ -401,5 +408,5 @@ test('Reducer should set (with a keyPath) with an unkeyed array and give it keys // key and meta should be untouched // top level child should be kept // keys should be generated for newly set value - expect(Reducer(data, action)).toEqual(expectedData); + expect(makeReducer(action)(data)).toEqual(expectedData); }); diff --git a/packages/dataparcels/src/change/__test__/ReducerSetMeta-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerSetMeta-test.js similarity index 71% rename from packages/dataparcels/src/change/__test__/ReducerSetMeta-test.js rename to packages/dataparcels/src/change/__test__/ChangeRequestReducerSetMeta-test.js index 6b57cd10..48088958 100644 --- a/packages/dataparcels/src/change/__test__/ReducerSetMeta-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerSetMeta-test.js @@ -1,8 +1,15 @@ // @flow -import Reducer from '../Reducer'; +import ChangeRequest from '../ChangeRequest'; +import ChangeRequestReducer from '../ChangeRequestReducer'; import Action from '../Action'; +import pipeWith from 'unmutable/lib/util/pipeWith'; -test('Reducer should setMeta with empty keyPath', () => { +const makeReducer = (action) => pipeWith( + new ChangeRequest(action), + ChangeRequestReducer +); + +test('ChangeRequestReducer should setMeta with empty keyPath', () => { var data = { value: { a: 1, @@ -24,10 +31,10 @@ test('Reducer should setMeta with empty keyPath', () => { abc: 123 }; - expect(Reducer(data, action).meta).toEqual(expectedMeta); + expect(makeReducer(action)(data).meta).toEqual(expectedMeta); }); -test('Reducer should setMeta merge', () => { +test('ChangeRequestReducer should setMeta merge', () => { var data = { value: { a: 1, @@ -53,10 +60,10 @@ test('Reducer should setMeta merge', () => { def: 456 }; - expect(Reducer(data, action).meta).toEqual(expectedMeta); + expect(makeReducer(action)(data).meta).toEqual(expectedMeta); }); -test('Reducer should setMeta with keyPath', () => { +test('ChangeRequestReducer should setMeta with keyPath', () => { var data = { value: { a: 1, @@ -86,10 +93,10 @@ test('Reducer should setMeta with keyPath', () => { } }; - expect(Reducer(data, action).child).toEqual(expectedChild); + expect(makeReducer(action)(data).child).toEqual(expectedChild); }); -test('Reducer should merge setMeta with keyPath', () => { +test('ChangeRequestReducer should merge setMeta with keyPath', () => { var data = { value: { a: 1, @@ -130,6 +137,6 @@ test('Reducer should merge setMeta with keyPath', () => { } }; - expect(Reducer(data, action).child).toEqual(expectedChild); + expect(makeReducer(action)(data).child).toEqual(expectedChild); }); diff --git a/packages/dataparcels/src/change/__test__/Reducer-test.js b/packages/dataparcels/src/change/__test__/Reducer-test.js deleted file mode 100644 index 7c20d161..00000000 --- a/packages/dataparcels/src/change/__test__/Reducer-test.js +++ /dev/null @@ -1,14 +0,0 @@ -// @flow -import Reducer from '../Reducer'; -import Action from '../Action'; - -test('Reducer should throw error if action is not provided', () => { - var data = { - value: 123, - key: "^", - child: undefined - }; - - // $FlowFixMe - intential misuse of types - expect(() => Reducer(data)).toThrowError(`Reducer must receive an Action`); -}); diff --git a/packages/dataparcels/src/change/__test__/ReducerPing-test.js b/packages/dataparcels/src/change/__test__/ReducerPing-test.js deleted file mode 100644 index aa6eb0ee..00000000 --- a/packages/dataparcels/src/change/__test__/ReducerPing-test.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow -import Reducer from '../Reducer'; -import Action from '../Action'; - -test('Reducer should ping', () => { - var data = { - value: [ - 0, - 1, - 2 - ], - key: "^", - child: undefined - }; - var action = new Action({ - type: "ping" - }); - - var expectedValue = [ - 0, - 1, - 2 - ]; - expect(expectedValue).toEqual(Reducer(data, action).value); -}); - diff --git a/packages/dataparcels/src/parcelData/__test__/update-test.js b/packages/dataparcels/src/parcelData/__test__/update-test.js new file mode 100644 index 00000000..81676a5f --- /dev/null +++ b/packages/dataparcels/src/parcelData/__test__/update-test.js @@ -0,0 +1,73 @@ +// @flow +import update from '../update'; + +const addThree = (parcelData) => ({ + ...parcelData, + value: parcelData.value + 3 +}); + +test('update should work', () => { + let parcelData = { + value: {a:1,b:2,c:3}, + child: { + a: {key:"a", meta: {abc: 123}}, + b: {key:"b"}, + c: {key:"c"} + } + }; + + let expectedParcelData = { + value: {a:15,b:2,c:3}, + child: { + a: {key:"a", meta: {abc: 123}}, + b: {key:"b"}, + c: {key:"c"} + } + }; + + let expectedExisting = { + value: 1, + meta: {abc: 123}, + key: "a" + }; + + let updated = update('a', (existing) => { + expect(existing).toEqual(expectedExisting); + return { + ...existing, + value: existing.value + 14 + }; + })(parcelData); + + expect(updated).toEqual(expectedParcelData); +}); + +test('update should work with unkeyed arrays', () => { + let parcelData = { + value: [1,2,3] + }; + + let expectedParcelData = { + value: [1,2,6], + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + let expectedExisting = { + value: 3, + key: "#c" + }; + + let updated = update('#c', (existing) => { + expect(existing).toEqual(expectedExisting); + return { + ...existing, + value: 6 + }; + })(parcelData); + + expect(updated).toEqual(expectedParcelData); +}); diff --git a/packages/dataparcels/src/parcelData/update.js b/packages/dataparcels/src/parcelData/update.js new file mode 100644 index 00000000..a81d731e --- /dev/null +++ b/packages/dataparcels/src/parcelData/update.js @@ -0,0 +1,67 @@ +// @flow +import type {Index} from '../types/Types'; +import type {Key} from '../types/Types'; +import type {Property} from '../types/Types'; +import type {ParcelData} from '../types/Types'; + +import get from './get'; +import isParentValue from './isParentValue'; +import prepareChildKeys from './prepareChildKeys'; +import keyOrIndexToProperty from './keyOrIndexToProperty'; +import updateChild from './updateChild'; +import updateChildKeys from './updateChildKeys'; + +import set from 'unmutable/lib/set'; +import update from 'unmutable/lib/update'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +export default (key: Key|Index, updater: Function) => (parcelData: ParcelData): ParcelData => { + let parcelDataWithChildKeys = prepareChildKeys()(parcelData); + let property: ?Property = keyOrIndexToProperty(key)(parcelDataWithChildKeys); + + if(typeof property === "undefined") { + return parcelDataWithChildKeys; + } + + let updatedData = pipeWith( + parcelDataWithChildKeys, + get(key), + updater + ); + + let { + value: updatedValue, + child: updatedChild, + ...updatedChildValues + } = updatedData; + + let value = pipeWith( + parcelDataWithChildKeys.value, + set(property, updatedValue) + ); + + let child = pipeWith( + parcelDataWithChildKeys.child, + update(property, (node) => ({ + ...node, + child: updatedChild, + ...updatedChildValues + })) + ); + + let result = { + ...parcelDataWithChildKeys, + value, + child + }; + + if(isParentValue(result.value)) { + return pipeWith( + result, + updateChild(), + updateChildKeys() + ); + } + + return result; +}; From 16a68f56ec6fa2db6b1aab539bc0b8a74ac30a96 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:10:13 +1100 Subject: [PATCH 016/120] refactor: delete unused file --- .../src/util/FindParcelsMatching.js | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 packages/dataparcels/src/util/FindParcelsMatching.js diff --git a/packages/dataparcels/src/util/FindParcelsMatching.js b/packages/dataparcels/src/util/FindParcelsMatching.js deleted file mode 100644 index b263ea5c..00000000 --- a/packages/dataparcels/src/util/FindParcelsMatching.js +++ /dev/null @@ -1,46 +0,0 @@ -// @flow -import type Parcel from '../parcel/Parcel'; -import {containsWildcard, split} from '../match/Matcher'; - -import flatMap from 'unmutable/lib/flatMap'; -import shallowEquals from 'unmutable/lib/shallowEquals'; -import take from 'unmutable/lib/take'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - -export default (startParcel: Parcel, match: string): Parcel[] => { - let matchParts = split(match); - let {path} = startParcel; - - let baseMatches = pipeWith( - matchParts, - take(path.length), - shallowEquals(path) - ); - - if(!baseMatches) { - return []; - } - - let get = (parcel: Parcel, matchParts: string[]): Parcel[] => { - let [matchPart, ...remainingMatchParts] = matchParts; - - if(!matchPart) { - return [parcel]; - } - if(!parcel.isParent()) { - return []; - } - if(containsWildcard(matchPart)) { - return pipeWith( - parcel.toArray(pp => get(pp, remainingMatchParts)), - flatMap(ii => ii) - ); - } - if(!parcel.has(matchPart)) { - return []; - } - return get(parcel.get(matchPart), remainingMatchParts); - }; - - return get(startParcel, matchParts.slice(path.length)); -}; From 025b9ec42d2cb2b8b04f81f9d42b5d97a5ead7bf Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:15:08 +1100 Subject: [PATCH 017/120] BREAK: rename Parcel.modifyValue to modifyValueDown --- .../src/docs/api/parcel/modifyValue.md | 3 -- .../src/docs/api/parcel/modifyValueDown.md | 3 ++ .../src/docs/api/parcel/pipe.md | 8 ++-- .../dataparcels-docs/src/pages/api/Parcel.jsx | 6 +-- packages/dataparcels/src/errors/Errors.js | 4 +- .../src/parcel/__test__/ModifyMethods-test.js | 40 +++++++++---------- .../src/parcel/__test__/ParcelGetters-test.js | 8 ++-- .../src/parcel/__test__/ParcelTypes-test.js | 2 +- .../src/parcel/methods/ModifyMethods.js | 12 +++--- .../src/__test__/ParcelHoc-test.js | 2 +- 10 files changed, 44 insertions(+), 44 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyValue.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyValue.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyValue.md deleted file mode 100644 index ad1086e3..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyValue.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyValue(updater: Function): void -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md new file mode 100644 index 00000000..7a7d7cfd --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md @@ -0,0 +1,3 @@ +```flow +modifyValueDown(updater: Function): void +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/pipe.md b/packages/dataparcels-docs/src/docs/api/parcel/pipe.md index f5842205..cdc62acb 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/pipe.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/pipe.md @@ -5,8 +5,8 @@ pipe(...updaters: Function[]): Parcel The `pipe` method allows for a parcel to be passed through one or more parcel modifying functions, while retaining the ability to chain. It allows for easier function composition. ```js -let valueToString = (parcel) => parcel.modifyValue(value => `${value}`); -let changeToNumber = (parcel) => parcel.modifyChangeValue(value => Number(value)); +let valueToString = (parcel) => parcel.modifyValueDown(value => `${value}`); +let changeToNumber = (parcel) => parcel.modifyValueUp(value => Number(value)); let parcel = new Parcel({value: 123}); parcel @@ -22,7 +22,7 @@ The above is equivalent to: ```js let parcel = new Parcel({value: 123}); parcel - .modifyValue(value => `${value}`) - .modifyChangeValue(value => Number(value)) + .modifyValueDown(value => `${value}`) + .modifyValueUp(value => Number(value)) .value // returns "123" ``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 5deff793..25e5288e 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -44,7 +44,7 @@ import Markdown_dispatch from 'docs/api/parcel/dispatch.md'; import Markdown_batch from 'docs/api/parcel/batch.md'; import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; import Markdown_ping from 'docs/api/parcel/ping.md'; -import Markdown_modifyValue from 'docs/api/parcel/modifyValue.md'; +import Markdown_modifyValueDown from 'docs/api/parcel/modifyValueDown.md'; import Markdown_modifyChangeBatch from 'docs/api/parcel/modifyChangeBatch.md'; import Markdown_modifyChangeValue from 'docs/api/parcel/modifyChangeValue.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; @@ -104,7 +104,7 @@ const md = { batch: Markdown_batch, batchAndReturn: Markdown_batchAndReturn, ping: Markdown_ping, - modifyValue: Markdown_modifyValue, + modifyValueDown: Markdown_modifyValueDown, modifyChangeBatch: Markdown_modifyChangeBatch, modifyChangeValue: Markdown_modifyChangeValue, initialMeta: Markdown_initialMeta, @@ -180,7 +180,7 @@ batchAndReturn() ping() # Modify methods -modifyValue() +modifyValueDown() modifyChangeBatch() modifyChangeValue() initialMeta() diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index c30d2889..bdcd22a9 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -3,6 +3,6 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); -export const ModifyValueChildReturnError = () => new Error(`.modifyValue()'s updater can not return a value that has children unless it is unchanged by the updater or is empty.`); -export const ModifyValueChangeChildReturnError = () => new Error(`When .modifyChangeValue()'s updater is passed a value that has children, it cannot return a value that has children unless it is unchanged by the updater`); +export const ModifyValueDownChildReturnError = () => new Error(`.modifyValueDown()'s updater can not return a value that has children unless it is unchanged by the updater or is empty.`); +export const ModifyValueUpChildReturnError = () => new Error(`When .modifyValueUp()'s updater is passed a value that has children, it cannot return a value that has children unless it is unchanged by the updater`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 81b59410..eca85fcd 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -2,14 +2,14 @@ import Parcel from '../Parcel'; import type ChangeRequest from '../../change/ChangeRequest'; -test('Parcel.modifyValue() should return a new parcel with updated parcelData', () => { +test('Parcel.modifyValueDown() should return a new parcel with updated parcelData', () => { expect.assertions(2); var data = { value: [123] }; var parcel = new Parcel(data).get(0); var updated = parcel - .modifyValue((value: *, parcelData: Parcel) => { + .modifyValueDown((value: *, parcelData: Parcel) => { expect(parcelData).toBe(parcel); return value + 1; }) @@ -24,72 +24,72 @@ test('Parcel.modifyValue() should return a new parcel with updated parcelData', expect(expectedData).toEqual(updated); }); -test('Parcel.modifyValue() should allow non-parent types to be returned', () => { +test('Parcel.modifyValueDown() should allow non-parent types to be returned', () => { let updatedValue = new Parcel({ value: 123 }) - .modifyValue(value => value + 1) + .modifyValueDown(value => value + 1) .value; expect(updatedValue).toEqual(124); }); -test('Parcel.modifyValue() should allow childless parent types to be returned', () => { +test('Parcel.modifyValueDown() should allow childless parent types to be returned', () => { let updatedValue = new Parcel({ value: 123 }) - .modifyValue(value => []) + .modifyValueDown(value => []) .value; expect(updatedValue).toEqual([]); }); -test('Parcel.modifyValue() should allow parent types to be returned if they dont change', () => { +test('Parcel.modifyValueDown() should allow parent types to be returned if they dont change', () => { let updatedValue = new Parcel({ value: [123] }) - .modifyValue(value => value) + .modifyValueDown(value => value) .value; expect(updatedValue).toEqual([123]); }); -test('Parcel.modifyValue() should throw error if changed parent types with children are returned', () => { +test('Parcel.modifyValueDown() should throw error if changed parent types with children are returned', () => { expect(() => { new Parcel({ value: [123] - }).modifyValue(value => [...value, 456]); + }).modifyValueDown(value => [...value, 456]); - }).toThrowError(`modifyValue()`); + }).toThrowError(`modifyValueDown()`); }); -test('Parcel.modifyValue() should throw error if childless is turned into parent types with children', () => { +test('Parcel.modifyValueDown() should throw error if childless is turned into parent types with children', () => { expect(() => { new Parcel({ value: 123 - }).modifyValue(value => [123, 456]); + }).modifyValueDown(value => [123, 456]); - }).toThrowError(`modifyValue()`); + }).toThrowError(`modifyValueDown()`); }); -test('Parcel.modifyValue() should recognise if value changes types, and set value if type changes', () => { +test('Parcel.modifyValueDown() should recognise if value changes types, and set value if type changes', () => { let handleChange = jest.fn(); let parcel = new Parcel({ value: 123, handleChange }) - .modifyValue(value => []) + .modifyValueDown(value => []) .push(123); expect(handleChange).toHaveBeenCalledTimes(1); expect(handleChange.mock.calls[0][0].value).toEqual([123]); }); -test('Parcel.modifyValue() should have id which is unique to updater', () => { +test('Parcel.modifyValueDown() should have id which is unique to updater', () => { let updater = value => []; - let parcel = new Parcel().modifyValue(updater); - let parcel2 = new Parcel().modifyValue(updater); - let parcel3 = new Parcel().modifyValue(a => 1 + 2); + let parcel = new Parcel().modifyValueDown(updater); + let parcel2 = new Parcel().modifyValueDown(updater); + let parcel3 = new Parcel().modifyValueDown(a => 1 + 2); expect(parcel.id).toBe("^.~mv-643198612"); expect(parcel2.id).toBe("^.~mv-643198612"); // same updater should produce the same hash diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js index 3bd4e412..ce85cb2d 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js @@ -75,7 +75,7 @@ test('Parcel.id should return the Parcels id', () => { }; expect("^").toBe(new Parcel(data).id); expect("^.a").toBe(new Parcel(data).get("a").id); - expect("^.~mv-364997092.a").toBe(new Parcel(data).modifyValue(ii => ii).get("a").id); + expect("^.~mv-364997092.a").toBe(new Parcel(data).modifyValueDown(ii => ii).get("a").id); expect("^.a.#a").toBe(new Parcel(data).getIn(["a",0]).id); expect("^.something%.%:%@").toBe(new Parcel(data).get("something.:@").id); expect("^.b").toBe(new Parcel(data).get("b").id); @@ -91,7 +91,7 @@ test('Parcel.path should return the Parcels path', () => { }; expect([]).toEqual(new Parcel(data).path); expect(["a"]).toEqual(new Parcel(data).get("a").path); - expect(["a"]).toEqual(new Parcel(data).modifyValue(ii => ii).get("a").path); + expect(["a"]).toEqual(new Parcel(data).modifyValueDown(ii => ii).get("a").path); expect(["a","#a"]).toEqual(new Parcel(data).getIn(["a",0]).path); expect(["something.:@"]).toEqual(new Parcel(data).get("something.:@").path); expect(["b"]).toEqual(new Parcel(data).get("b").path); @@ -106,9 +106,9 @@ test('Parcel._id.typedPathString() should return the Parcels typed path', () => } }; expect("^:ceiPT").toEqual(new Parcel(data)._id.typedPathString()); - expect("^:ceiPT").toEqual(new Parcel(data).modifyValue(ii => ii)._id.typedPathString()); + expect("^:ceiPT").toEqual(new Parcel(data).modifyValueDown(ii => ii)._id.typedPathString()); expect("^:ceiPT.a:CeIPt").toEqual(new Parcel(data).get("a")._id.typedPathString()); - expect("^:ceiPT.a:CeIPt").toEqual(new Parcel(data).modifyValue(ii => ii).get("a")._id.typedPathString()); + expect("^:ceiPT.a:CeIPt").toEqual(new Parcel(data).modifyValueDown(ii => ii).get("a")._id.typedPathString()); expect("^:ceiPT.a:CeIPt.#a:CEipt").toEqual(new Parcel(data).getIn(["a",0])._id.typedPathString()); expect("^:ceiPT.something%.%:%@:Ceipt").toEqual(new Parcel(data).get("something.:@")._id.typedPathString()); expect("^:ceiPT.b:Ceipt").toEqual(new Parcel(data).get("b")._id.typedPathString()); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js index 835a5c06..c42dd1c0 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js @@ -141,7 +141,7 @@ test('ParcelTypes should correctly identify top level values after modifiers', ( var data = { value: [1,2,3] }; - expect(new Parcel(data).modifyValue(ii => ii).isTopLevel()).toBe(true); + expect(new Parcel(data).modifyValueDown(ii => ii).isTopLevel()).toBe(true); }); // method creators diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index bb21b2af..603670cf 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -5,8 +5,8 @@ import type {ParcelMeta} from '../../types/Types'; import Types from '../../types/Types'; import ParcelTypes from '../ParcelTypes'; -import {ModifyValueChildReturnError} from '../../errors/Errors'; -import {ModifyValueChangeChildReturnError} from '../../errors/Errors'; +import {ModifyValueDownChildReturnError} from '../../errors/Errors'; +import {ModifyValueUpChildReturnError} from '../../errors/Errors'; import HashString from '../../util/HashString'; import equals from 'unmutable/lib/equals'; @@ -23,15 +23,15 @@ let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; export default (_this: Parcel): Object => ({ - modifyValue: (updater: Function): Parcel => { - Types(`modifyValue()`, `updater`, `function`)(updater); + modifyValueDown: (updater: Function): Parcel => { + Types(`modifyValueDown()`, `updater`, `function`)(updater); let {value} = _this._parcelData; let updatedValue = updater(value, _this); let updatedType = new ParcelTypes(updatedValue); if(updatedType.isParent() && !isEmpty()(updatedValue) && !equals(value)(updatedValue)) { - throw ModifyValueChildReturnError(); + throw ModifyValueDownChildReturnError(); } let updatedTypeChanged: boolean = updatedType.isParent() !== _this._parcelTypes.isParent() @@ -84,7 +84,7 @@ export default (_this: Parcel): Object => ({ if(type.isParent()) { if(!equals(value)(updatedValue)) { - throw ModifyValueChangeChildReturnError(); + throw ModifyValueUpChildReturnError(); } parcel.dispatch(changeRequest); return; diff --git a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js index 66cec234..74b06956 100644 --- a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js @@ -103,7 +103,7 @@ test('ParcelHoc config should accept a pipe function', () => { pipe: (props) => (parcel) => { expect(456).toBe(parcel.value); expect({}).toEqual(props); - return parcel.modifyValue(ii => ii + 1); + return parcel.modifyValueDown(ii => ii + 1); } }) ).props(); From ccc769a33ebe1d0b325c3127319173084bbcd0a4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:17:18 +1100 Subject: [PATCH 018/120] BREAK: rename Parcel.modifyChangeValue to modifyValueUp --- .../src/docs/api/parcel/modifyChangeValue.md | 4 ---- .../src/docs/api/parcel/modifyValueUp.md | 4 ++++ .../dataparcels-docs/src/pages/api/Parcel.jsx | 6 ++--- .../src/change/__test__/ChangeRequest-test.js | 1 - packages/dataparcels/src/parcel/Parcel.js | 4 ++-- .../src/parcel/__test__/ModifyMethods-test.js | 22 +++++++++---------- .../src/parcel/methods/ModifyMethods.js | 4 ++-- 7 files changed, 22 insertions(+), 23 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyChangeValue.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeValue.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeValue.md deleted file mode 100644 index 8d1dfb0e..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeValue.md +++ /dev/null @@ -1,4 +0,0 @@ -```flow -modifyChangeValue(updater: Function): void -``` - diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md new file mode 100644 index 00000000..40870bc9 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md @@ -0,0 +1,4 @@ +```flow +modifyValueUp(updater: Function): void +``` + diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 25e5288e..15b7c296 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -46,7 +46,7 @@ import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; import Markdown_ping from 'docs/api/parcel/ping.md'; import Markdown_modifyValueDown from 'docs/api/parcel/modifyValueDown.md'; import Markdown_modifyChangeBatch from 'docs/api/parcel/modifyChangeBatch.md'; -import Markdown_modifyChangeValue from 'docs/api/parcel/modifyChangeValue.md'; +import Markdown_modifyValueUp from 'docs/api/parcel/modifyValueUp.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; import Markdown_isChild from 'docs/api/parcel/isChild.md'; import Markdown_isElement from 'docs/api/parcel/isElement.md'; @@ -106,7 +106,7 @@ const md = { ping: Markdown_ping, modifyValueDown: Markdown_modifyValueDown, modifyChangeBatch: Markdown_modifyChangeBatch, - modifyChangeValue: Markdown_modifyChangeValue, + modifyValueUp: Markdown_modifyValueUp, initialMeta: Markdown_initialMeta, isChild: Markdown_isChild, isElement: Markdown_isElement, @@ -182,7 +182,7 @@ ping() # Modify methods modifyValueDown() modifyChangeBatch() -modifyChangeValue() +modifyValueUp() initialMeta() # Type methods diff --git a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js index 80907399..fd8e2b1d 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js @@ -196,7 +196,6 @@ test('ChangeRequest should keep originId and originPath', () => { new Parcel(data) .get('abc') .onChange(456); - //.modifyChangeValue(value => value + 1) }); diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 27e31f03..0c1077fa 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -345,9 +345,9 @@ export default class Parcel { unshift = (value: *) => this._methods.unshift(value); // Modify methods - modifyValue = (updater: Function): Parcel => this._methods.modifyValue(updater); modifyChangeBatch = (batcher: Function): Parcel => this._methods.modifyChangeBatch(batcher); - modifyChangeValue = (updater: Function): Parcel => this._methods.modifyChangeValue(updater); + modifyValueDown = (updater: Function): Parcel => this._methods.modifyValueDown(updater); + modifyValueUp = (updater: Function): Parcel => this._methods.modifyValueUp(updater); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index eca85fcd..3ddcc4c6 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -142,57 +142,57 @@ test('Parcel.modifyChangeBatch() should have id which is unique to updater', () expect(parcel3.id).not.toBe("^.~mcb-643198612"); // different updater should produce different hash }); -test('Parcel.modifyChangeValue() should allow you to change the payload of a changed parcel with an updater (and should allow non-parent types to be returned)', () => { +test('Parcel.modifyValueUp() should allow you to change the payload of a changed parcel with an updater (and should allow non-parent types to be returned)', () => { var handleChange = jest.fn(); new Parcel({ value: 123, handleChange }) - .modifyChangeValue(value => value + 1) + .modifyValueUp(value => value + 1) .onChange(456); expect(handleChange.mock.calls[0][0].value).toBe(457); }); -test('Parcel.modifyChangeValue() should allow parent types to be returned', () => { +test('Parcel.modifyValueUp() should allow parent types to be returned', () => { var handleChange = jest.fn(); new Parcel({ value: 123, handleChange }) - .modifyChangeValue(value => [123,456]) + .modifyValueUp(value => [123,456]) .onChange(456); expect(handleChange.mock.calls[0][0].value).toEqual([123,456]); }); -test('Parcel.modifyChangeValue() should allow parent types to be returned if they dont change', () => { +test('Parcel.modifyValueUp() should allow parent types to be returned if they dont change', () => { var handleChange = jest.fn(); new Parcel({ value: [123], handleChange }) - .modifyChangeValue(value => value) + .modifyValueUp(value => value) .onChange([456]); expect(handleChange.mock.calls[0][0].value).toEqual([456]); }); -test('Parcel.modifyChangeValue() should throw error if changed parent types with children are returned', () => { +test('Parcel.modifyValueUp() should throw error if changed parent types with children are returned', () => { expect(() => { var handleChange = jest.fn(); new Parcel({ value: [123], handleChange }) - .modifyChangeValue(value => [...value, 456]) + .modifyValueUp(value => [...value, 456]) .onChange([456]); - }).toThrowError(`modifyChangeValue()`); + }).toThrowError(`modifyValueUp()`); }); -test('Parcel.modifyChangeValue() should allow changes to meta through', () => { +test('Parcel.modifyValueUp() should allow changes to meta through', () => { expect.assertions(2); var data = { @@ -205,7 +205,7 @@ test('Parcel.modifyChangeValue() should allow changes to meta through', () => { }; new Parcel(data) - .modifyChangeValue(value => value + 1) + .modifyValueUp(value => value + 1) .batch(parcel => { parcel.onChange(456); parcel.setMeta({ diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 603670cf..f78252b3 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -73,8 +73,8 @@ export default (_this: Parcel): Object => ({ }); }, - modifyChangeValue: (updater: Function): Parcel => { - Types(`modifyChangeValue()`, `updater`, `function`)(updater); + modifyValueUp: (updater: Function): Parcel => { + Types(`modifyValueUp()`, `updater`, `function`)(updater); return _this.modifyChangeBatch((parcel: Parcel, changeRequest: ChangeRequest) => { let {value} = changeRequest.nextData; From 5af77d368ebb4bc7f4a2f3fd9adfe14e32322ba2 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:19:20 +1100 Subject: [PATCH 019/120] BREAK: rename Parcel.modifyChangeBatch to modifyChange --- .../src/docs/api/parcel/modifyChange.md | 3 +++ .../src/docs/api/parcel/modifyChangeBatch.md | 3 --- .../dataparcels-docs/src/pages/api/Parcel.jsx | 6 +++--- .../src/change/__test__/ChangeRequest-test.js | 8 ++++---- packages/dataparcels/src/parcel/Parcel.js | 2 +- .../src/parcel/__test__/ModifyMethods-test.js | 16 ++++++++-------- .../src/parcel/methods/ModifyMethods.js | 6 +++--- 7 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyChangeBatch.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md new file mode 100644 index 00000000..bdce6131 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md @@ -0,0 +1,3 @@ +```flow +modifyChange(batcher: Function): void +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeBatch.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeBatch.md deleted file mode 100644 index 9da5d2b0..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyChangeBatch.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyChangeBatch(batcher: Function): void -``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 15b7c296..187c5763 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -45,8 +45,8 @@ import Markdown_batch from 'docs/api/parcel/batch.md'; import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; import Markdown_ping from 'docs/api/parcel/ping.md'; import Markdown_modifyValueDown from 'docs/api/parcel/modifyValueDown.md'; -import Markdown_modifyChangeBatch from 'docs/api/parcel/modifyChangeBatch.md'; import Markdown_modifyValueUp from 'docs/api/parcel/modifyValueUp.md'; +import Markdown_modifyChange from 'docs/api/parcel/modifyChange.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; import Markdown_isChild from 'docs/api/parcel/isChild.md'; import Markdown_isElement from 'docs/api/parcel/isElement.md'; @@ -105,8 +105,8 @@ const md = { batchAndReturn: Markdown_batchAndReturn, ping: Markdown_ping, modifyValueDown: Markdown_modifyValueDown, - modifyChangeBatch: Markdown_modifyChangeBatch, modifyValueUp: Markdown_modifyValueUp, + modifyChange: Markdown_modifyChange, initialMeta: Markdown_initialMeta, isChild: Markdown_isChild, isElement: Markdown_isElement, @@ -181,8 +181,8 @@ ping() # Modify methods modifyValueDown() -modifyChangeBatch() modifyValueUp() +modifyChange() initialMeta() # Type methods diff --git a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js index fd8e2b1d..70a7b97c 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js @@ -214,7 +214,7 @@ test('ChangeRequest should keep originId and originPath even when going through }; new Parcel(data) - .modifyChangeBatch((parcel, changeRequest) => { + .modifyChange((parcel, changeRequest) => { parcel.set('def', 789); parcel.dispatch(changeRequest); }) @@ -320,19 +320,19 @@ test('ChangeRequest data chache should be invalidated correctly', () => { parcel .get('a') - .modifyChangeBatch((parcel, changeRequest) => { + .modifyChange((parcel, changeRequest) => { expect(changeRequest.nextData).toEqual({key: 'a', meta: {abc: 123}, value: {b: 456}, child: {b:{key: "b"}}}); expect(changeRequest.nextData).toEqual({key: 'a', meta: {abc: 123}, value: {b: 456}, child: {b:{key: "b"}}}); // get cached parcel.dispatch(changeRequest); }) - .modifyChangeBatch((parcel, changeRequest) => { + .modifyChange((parcel, changeRequest) => { expect(changeRequest.nextData).toEqual({key: 'a', meta: {}, value: {b: 456}, child: {b:{key: "b"}}}); expect(changeRequest.nextData).toEqual({key: 'a', meta: {}, value: {b: 456}, child: {b:{key: "b"}}}); // get cached parcel.dispatch(changeRequest); parcel.setMeta({abc: 123}); }) .get('b') - .modifyChangeBatch((parcel, changeRequest) => { + .modifyChange((parcel, changeRequest) => { expect(changeRequest.nextData).toEqual({key: 'b', meta: {}, value: 456}); expect(changeRequest.nextData).toEqual({key: 'b', meta: {}, value: 456}); // get cached parcel.dispatch(changeRequest); diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 0c1077fa..01459118 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -345,7 +345,7 @@ export default class Parcel { unshift = (value: *) => this._methods.unshift(value); // Modify methods - modifyChangeBatch = (batcher: Function): Parcel => this._methods.modifyChangeBatch(batcher); + modifyChange = (batcher: Function): Parcel => this._methods.modifyChange(batcher); modifyValueDown = (updater: Function): Parcel => this._methods.modifyValueDown(updater); modifyValueUp = (updater: Function): Parcel => this._methods.modifyValueUp(updater); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 3ddcc4c6..bf8de79f 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -96,7 +96,7 @@ test('Parcel.modifyValueDown() should have id which is unique to updater', () => expect(parcel3.id).not.toBe("^.~mv-643198612"); // different updater should produce different hash }); -test('Parcel.modifyChangeBatch() should allow you to change the payload of a changed parcel', () => { +test('Parcel.modifyChange() should allow you to change the payload of a changed parcel', () => { expect.assertions(1); var data = { @@ -108,13 +108,13 @@ test('Parcel.modifyChangeBatch() should allow you to change the payload of a cha }; new Parcel(data) - .modifyChangeBatch((parcel: Parcel, changeRequest: ChangeRequest) => { + .modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { parcel.set(changeRequest.nextData.value + 1); }) .onChange(456); }); -test('Parcel.modifyChangeBatch() should allow you to stop a change by not calling dispatch', () => { +test('Parcel.modifyChange() should allow you to stop a change by not calling dispatch', () => { var handleChange = jest.fn(); var data = { @@ -123,7 +123,7 @@ test('Parcel.modifyChangeBatch() should allow you to stop a change by not callin }; new Parcel(data) - .modifyChangeBatch((parcel: Parcel, changeRequest: ChangeRequest) => { + .modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { // nothing here }) .onChange(456); @@ -131,11 +131,11 @@ test('Parcel.modifyChangeBatch() should allow you to stop a change by not callin expect(handleChange).toHaveBeenCalledTimes(0); }); -test('Parcel.modifyChangeBatch() should have id which is unique to updater', () => { +test('Parcel.modifyChange() should have id which is unique to updater', () => { let updater = value => []; - let parcel = new Parcel().modifyChangeBatch(updater); - let parcel2 = new Parcel().modifyChangeBatch(updater); - let parcel3 = new Parcel().modifyChangeBatch(a => "woop"); + let parcel = new Parcel().modifyChange(updater); + let parcel2 = new Parcel().modifyChange(updater); + let parcel3 = new Parcel().modifyChange(a => "woop"); expect(parcel.id).toBe("^.~mcb-643198612"); expect(parcel2.id).toBe("^.~mcb-643198612"); // same updater should produce the same hash diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index f78252b3..1d23823b 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -60,8 +60,8 @@ export default (_this: Parcel): Object => ({ }); }, - modifyChangeBatch: (batcher: Function): Parcel => { - Types(`modifyChangeBatch()`, `batcher`, `function`)(batcher); + modifyChange: (batcher: Function): Parcel => { + Types(`modifyChange()`, `batcher`, `function`)(batcher); return _this._create({ id: _this._id.pushModifier(`mcb-${HashFunction(batcher)}`), onDispatch: (changeRequest: ChangeRequest) => { @@ -75,7 +75,7 @@ export default (_this: Parcel): Object => ({ modifyValueUp: (updater: Function): Parcel => { Types(`modifyValueUp()`, `updater`, `function`)(updater); - return _this.modifyChangeBatch((parcel: Parcel, changeRequest: ChangeRequest) => { + return _this.modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { let {value} = changeRequest.nextData; let type = new ParcelTypes(value); From abb17b07c214bc6e09dc437450759d5d6e53cfc6 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 29 Nov 2018 00:20:10 +1100 Subject: [PATCH 020/120] refactor: delete unused file --- .../util/__test__/FindParcelsMatching-test.js | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 packages/dataparcels/src/util/__test__/FindParcelsMatching-test.js diff --git a/packages/dataparcels/src/util/__test__/FindParcelsMatching-test.js b/packages/dataparcels/src/util/__test__/FindParcelsMatching-test.js deleted file mode 100644 index 7053731b..00000000 --- a/packages/dataparcels/src/util/__test__/FindParcelsMatching-test.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow -import Parcel from 'dataparcels'; -import FindParcelsMatching from '../FindParcelsMatching'; - -test(`FindParcelsMatching() should return all parcels matching the match string at or below the start parcel's depth`, () => { - - let p = new Parcel({ - value: { - abc: { - def: 123, - ghi: 456 - }, - jkl: { - mno: 789 - } - } - }); - - expect(["abc"]).toEqual(FindParcelsMatching(p, "abc").map(ii => ii.path.join("."))); - expect(["abc.def"]).toEqual(FindParcelsMatching(p, "abc.def").map(ii => ii.path.join("."))); - expect([]).toEqual(FindParcelsMatching(p, "abc.def.toofar").map(ii => ii.path.join("."))); - expect([]).toEqual(FindParcelsMatching(p, "abc.woo").map(ii => ii.path.join("."))); - expect([]).toEqual( - FindParcelsMatching(p, "asdf%.kasd.asdasd.asd").map(ii => ii.path.join(".")) - ); - expect(["abc.def", "abc.ghi"]).toEqual(FindParcelsMatching(p, "abc.*").map(ii => ii.path.join("."))); - expect(["abc.def"]).toEqual( - FindParcelsMatching(p.get('abc'), "abc.def").map(ii => ii.path.join(".")) - ); - expect([]).toEqual( - FindParcelsMatching(p.get('mno'), "abc.def").map(ii => ii.path.join(".")) - ); - expect(["abc.def","abc.ghi","jkl.mno"]).toEqual(FindParcelsMatching(p, "*.*").map(ii => ii.path.join("."))); -}); From ac8613222245df4d8a8474cea2311d9ff38cdd50 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 2 Dec 2018 13:08:55 +1100 Subject: [PATCH 021/120] feat: draft modifyUp and modifyDown --- packages/dataparcels/src/parcel/Parcel.js | 4 +- .../src/parcel/methods/ModifyMethods.js | 50 ++++++++++++++----- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 01459118..475c9e9b 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -345,9 +345,11 @@ export default class Parcel { unshift = (value: *) => this._methods.unshift(value); // Modify methods - modifyChange = (batcher: Function): Parcel => this._methods.modifyChange(batcher); + modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); + modifyUp = (updater: Function): Parcel => this._methods.modifyUp(updater); modifyValueDown = (updater: Function): Parcel => this._methods.modifyValueDown(updater); modifyValueUp = (updater: Function): Parcel => this._methods.modifyValueUp(updater); + modifyChange = (batcher: ParcelBatcher): Parcel => this._methods.modifyChange(batcher); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 1d23823b..fbb27470 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -23,6 +23,30 @@ let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; export default (_this: Parcel): Object => ({ + modifyDown: (updater: Function): Parcel => { + Types(`modifyDown()`, `updater`, `function`)(updater); + let parcelData = updater(_this._parcelData); + + return _this._create({ + id: _this._id.pushModifier(`md-${HashFunction(updater)}`), + parcelData, + onDispatch: (changeRequest: ChangeRequest) => { + _this.dispatch(changeRequest._addPre(updater)); + } + }); + }, + + modifyUp: (updater: Function): Parcel => { + Types(`modifyUp()`, `updater`, `function`)(updater); + + return _this._create({ + id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), + onDispatch: (changeRequest: ChangeRequest) => { + _this.dispatch(changeRequest._addPost(updater)); + } + }); + }, + modifyValueDown: (updater: Function): Parcel => { Types(`modifyValueDown()`, `updater`, `function`)(updater); @@ -60,19 +84,6 @@ export default (_this: Parcel): Object => ({ }); }, - modifyChange: (batcher: Function): Parcel => { - Types(`modifyChange()`, `batcher`, `function`)(batcher); - return _this._create({ - id: _this._id.pushModifier(`mcb-${HashFunction(batcher)}`), - onDispatch: (changeRequest: ChangeRequest) => { - _this.batch( - (parcel: Parcel) => batcher(parcel, changeRequest._setBaseParcel(parcel)), - changeRequest - ); - } - }); - }, - modifyValueUp: (updater: Function): Parcel => { Types(`modifyValueUp()`, `updater`, `function`)(updater); return _this.modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { @@ -98,6 +109,19 @@ export default (_this: Parcel): Object => ({ }); }, + modifyChange: (batcher: Function): Parcel => { + Types(`modifyChange()`, `batcher`, `function`)(batcher); + return _this._create({ + id: _this._id.pushModifier(`mcb-${HashFunction(batcher)}`), + onDispatch: (changeRequest: ChangeRequest) => { + _this.batch( + (parcel: Parcel) => batcher(parcel, changeRequest._setBaseParcel(parcel)), + changeRequest + ); + } + }); + }, + initialMeta: (initialMeta: ParcelMeta = {}): Parcel => { Types(`initialMeta()`, `initialMeta`, `object`)(initialMeta); let {meta} = _this._parcelData; From 96fe36eca2f85a62b91e60282b0b3de0b9a7d66a Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 09:17:44 +1100 Subject: [PATCH 022/120] feat: add parceldata getIn --- .../src/parcelData/__test__/getIn-test.js | 221 ++++++++++++++++++ packages/dataparcels/src/parcelData/getIn.js | 22 ++ 2 files changed, 243 insertions(+) create mode 100644 packages/dataparcels/src/parcelData/__test__/getIn-test.js create mode 100644 packages/dataparcels/src/parcelData/getIn.js diff --git a/packages/dataparcels/src/parcelData/__test__/getIn-test.js b/packages/dataparcels/src/parcelData/__test__/getIn-test.js new file mode 100644 index 00000000..14677525 --- /dev/null +++ b/packages/dataparcels/src/parcelData/__test__/getIn-test.js @@ -0,0 +1,221 @@ +// @flow +import getIn from '../getIn'; + +test('getIn should work with objects', () => { + let parcelData = { + value: { + a: { + b: 1 + } + } + }; + let expectedParcelData = { + value: { + b: 1 + }, + key: "a" + }; + + expect(expectedParcelData).toEqual(getIn(['a'])(parcelData)); +}); + +test('getIn should work with objects with child data', () => { + let parcelData = { + value: { + a: { + b: 1 + } + }, + meta: { + abc: 123 + }, + child: { + a: { + key: "a", + meta: { + def: 456 + }, + child: { + b: { + key: "b", + meta: { + ghi: 789 + } + } + } + } + } + }; + + let expectedParcelData = { + value: { + b: 1 + }, + meta: { + def: 456 + }, + key: "a", + child: { + b: { + key: "b", + meta: { + ghi: 789 + } + } + } + }; + + expect(expectedParcelData).toEqual(getIn(['a'])(parcelData)); +}); + +test('getIn should work with objects with hashkey - just to make sure that hashkeys are only converted to properties when used on an indexed parcel', () => { + let parcelData = { + value: { + ["#a"]: { + b: 1 + } + } + }; + let expectedParcelData = { + value: { + b: 1 + }, + key: "#a" + }; + + expect(expectedParcelData).toEqual(getIn(['#a'])(parcelData)); +}); + + +test('getIn should not clone value', () => { + let parcelData = { + value: { + a: { + b: 1 + } + } + }; + expect(parcelData.value.a).toBe(getIn(['a'])(parcelData).value); +}); + +test('getIn should work with arrays that dont have keys yet', () => { + let parcelData = { + value: ['abc'] + }; + + let expectedParcelData = { + value: 'abc', + key: "#a" + }; + + expect(getIn([0])(parcelData)).toEqual(expectedParcelData); +}); + +test('getIn should work with arrays that dont have keys yet with hashkey', () => { + let parcelData = { + value: ['abc', 'def'] + }; + + let expectedParcelData = { + value: 'def', + key: "#b" + }; + + expect(getIn(["#b"])(parcelData)).toEqual(expectedParcelData); +}); + +test('getIn should work with objects that already have children, and not recreate children, even if incorrect', () => { + let parcelData = { + value: { + a: { + b: 1 + } + }, + child: { + a: { + key: 'AsdasdsdDS' + } + } + }; + let expectedParcelData = { + value: { + b: 1 + }, + key: 'AsdasdsdDS' + }; + + expect(expectedParcelData).toEqual(getIn(['a'])(parcelData)); +}); + +test('getIn should work with non existent keys', () => { + let parcelData = { + value: { + a: { + b: 1 + } + } + }; + let expectedParcelData = { + value: undefined, + key: "z" + }; + + expect(expectedParcelData).toEqual(getIn(['z'])(parcelData)); + + let expectedParcelData2 = { + value: "!!!", + key: "z" + }; + + expect(expectedParcelData2).toEqual(getIn(['z'], "!!!")(parcelData)); +}); + +// +// deep tests +// + +test('getIn should work deeply', () => { + let parcelData = { + value: { + a: { + b: 1 + } + } + }; + let expectedParcelData = { + value: 1, + key: "b" + }; + + expect(getIn(['a', 'b'])(parcelData)).toEqual(expectedParcelData); +}); + +test('getIn should return undefined if asking through a non-parent', () => { + let parcelData = { + value: { + a: 123 + } + }; + let expectedParcelData = { + value: undefined, + key: "b" + }; + + expect(getIn(['a', 'b'])(parcelData)).toEqual(expectedParcelData); +}); + +test('getIn should return undefined if asking for a non-existent key', () => { + let parcelData = { + value: { + a: { + b: 123 + } + } + }; + let expectedParcelData = { + value: undefined, + key: "c" + }; + + expect(getIn(['a', 'c'])(parcelData)).toEqual(expectedParcelData); +}); diff --git a/packages/dataparcels/src/parcelData/getIn.js b/packages/dataparcels/src/parcelData/getIn.js new file mode 100644 index 00000000..a56d051e --- /dev/null +++ b/packages/dataparcels/src/parcelData/getIn.js @@ -0,0 +1,22 @@ +// @flow +import type {Key} from '../types/Types'; +import type {Index} from '../types/Types'; +import type {ParcelData} from '../types/Types'; + +import get from './get'; +import has from './has'; +import keyOrIndexToKey from './keyOrIndexToKey'; +import isParentValue from './isParentValue'; + +export default (keyPath: Array, notFoundValue: ?*) => (parcelData: ParcelData): ParcelData => { + for(let key of keyPath) { + if(!isParentValue(parcelData.value) || !has(key)(parcelData)) { + return { + value: notFoundValue, + key: keyOrIndexToKey(key)(parcelData) + }; + } + parcelData = get(key, notFoundValue)(parcelData); + } + return parcelData; +}; From 4fb356b424fb2da4fd463d12c370a1f0c394adbe Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 09:18:14 +1100 Subject: [PATCH 023/120] feat: add staticparcel to runtime type checker --- packages/dataparcels/src/types/Types.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index fb7185b9..968ba335 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -5,6 +5,7 @@ import type Treeshare from '../treeshare/Treeshare'; import Parcel from '../parcel/Parcel'; import Action from '../change/Action'; import ChangeRequest from '../change/ChangeRequest'; +import StaticParcel from '../staticParcel/StaticParcel'; import isPlainObject from 'unmutable/lib/util/isPlainObject'; export type ParcelData = { @@ -116,6 +117,10 @@ const RUNTIME_TYPES = { name: "an object containing parcel data {value: *, meta?: {}, key?: *}", check: ii => isPlainObject(ii) && ii.hasOwnProperty('value') }, + ['staticParcel']: { + name: "a StaticParcel", + check: ii => ii instanceof StaticParcel + }, ['string']: { name: "a string", check: ii => typeof ii === "string" From 63e4327ee3cca23857e462e36c8520697bf6b7fe Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 10:39:10 +1100 Subject: [PATCH 024/120] fix: make Parcel.toObject() make object out of array value --- .../parcel/__test__/ParentGetMethods-test.js | 17 +++++++++++++++++ .../src/parcel/methods/ParentGetMethods.js | 15 ++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js index 8454123c..9267c672 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js @@ -278,6 +278,23 @@ test('ParentParcel.toObject() should make an object', () => { }); +test('ParentParcel.toObject() should make an object from an array', () => { + var data = { + value: [1,2,3], + meta: { + a: {a:4,b:5,c:6} + } + }; + + var expectedObject = {"0":1,"1":2,"2":3}; + var parcel = new Parcel(data); + var obj = map(ii => ii.value)(parcel.toObject()); + + expect(obj).toEqual(expectedObject); + +}); + + test('ParentParcel.toObject() should make an object with a mapper', () => { var data = { value: {a:1,b:2,c:3}, diff --git a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js index 47df6ad6..19596385 100644 --- a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js @@ -10,9 +10,11 @@ import parcelGet from '../../parcelData/get'; import parcelHas from '../../parcelData/has'; import prepareChildKeys from '../../parcelData/prepareChildKeys'; +import keyArray from 'unmutable/lib/keyArray'; import map from 'unmutable/lib/map'; import size from 'unmutable/lib/size'; import toArray from 'unmutable/lib/toArray'; +import toObject from 'unmutable/lib/toObject'; import pipeWith from 'unmutable/lib/util/pipeWith'; export default (_this: Parcel) => ({ @@ -73,16 +75,19 @@ export default (_this: Parcel) => ({ return pipeWith( _this._parcelData.value, - map((ii: *, key: string|number): * => { - let item = _this.get(key); - return mapper(item, key, _this); - }) + map((value, key) => mapper(_this.get(key), key, _this)), + toObject() ); }, toArray: (mapper: ParcelMapper): Array<*> => { Types(`toArray()`, `mapper`, `function`)(mapper); - return toArray()(_this.toObject(mapper)); + + return pipeWith( + _this._parcelData.value, + map((value, key) => mapper(_this.get(key), key, _this)), + toArray() + ); }, size: (): number => size()(_this.value) From cb25af939a7d66d4a3b5b5ecea29001c05cacef3 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 11:00:24 +1100 Subject: [PATCH 025/120] BREAK: remove Parcel.updateMeta --- .../src/docs/api/parcel/updateMeta.md | 3 - .../dataparcels-docs/src/pages/api/Parcel.jsx | 3 - packages/dataparcels/src/parcel/Parcel.js | 1 - .../__test__/ParcelChangeMethods-test.js | 55 ------------------- .../src/parcel/methods/ParcelChangeMethods.js | 11 ---- 5 files changed, 73 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateMeta.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateMeta.md b/packages/dataparcels-docs/src/docs/api/parcel/updateMeta.md deleted file mode 100644 index 364f9ab4..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateMeta.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -updateMeta(updater: Function): void -``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 187c5763..9340131b 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -38,7 +38,6 @@ import Markdown_swapNext from 'docs/api/parcel/swapNext.md'; import Markdown_swapPrev from 'docs/api/parcel/swapPrev.md'; import Markdown_unshift from 'docs/api/parcel/unshift.md'; import Markdown_setMeta from 'docs/api/parcel/setMeta.md'; -import Markdown_updateMeta from 'docs/api/parcel/updateMeta.md'; import Markdown_setChangeRequestMeta from 'docs/api/parcel/setChangeRequestMeta.md'; import Markdown_dispatch from 'docs/api/parcel/dispatch.md'; import Markdown_batch from 'docs/api/parcel/batch.md'; @@ -98,7 +97,6 @@ const md = { swapPrev: Markdown_swapPrev, unshift: Markdown_unshift, setMeta: Markdown_setMeta, - updateMeta: Markdown_updateMeta, setChangeRequestMeta: Markdown_setChangeRequestMeta, dispatch: Markdown_dispatch, batch: Markdown_batch, @@ -172,7 +170,6 @@ unshift() # Advanced change methods setMeta() -updateMeta() setChangeRequestMeta() dispatch() batch() diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 475c9e9b..524ca7f9 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -311,7 +311,6 @@ export default class Parcel { // Advanced change methods setMeta = (partialMeta: ParcelMeta) => this._methods.setMeta(partialMeta); - updateMeta = (updater: ParcelMetaUpdater) => this._methods.updateMeta(updater); setChangeRequestMeta = (partialMeta: ParcelMeta) => this._methods.setChangeRequestMeta(partialMeta); dispatch = (dispatchable: Action|Action[]|ChangeRequest) => this._methods.dispatch(dispatchable); batch = (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => this._methods.batch(batcher, changeRequest); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index cf50d4f3..d626417f 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -219,61 +219,6 @@ test('Parcel.setMeta() should call the Parcels handleChange function with the ne }); }); -test('Parcel.updateMeta() should call the Parcels handleChange function with the new meta merged in', () => { - expect.assertions(5); - - var data = { - value: 123 - }; - - var expectedMeta = { - abc: 123 - }; - - var expectedMeta2 = { - abc: 123, - def: 456 - }; - - var expectedAction = { - type: "setMeta", - keyPath: [], - payload: { - meta: { - abc: 123 - } - } - }; - - var changes = 0; - - new Parcel({ - ...data, - handleChange: (parcel, changeRequest) => { - changes++; - - if(changes === 1) { - expect(expectedMeta).toEqual(parcel.meta); - expect(expectedAction).toEqual(GetAction(changeRequest)); - parcel.updateMeta(meta => { - expect({abc: 123}).toEqual(meta) - return { - def: 456 - }; - }); - - } else if(changes === 2) { - expect(expectedMeta2).toEqual(parcel.meta); - } - } - }).updateMeta(meta => { - expect({}).toEqual(meta) - return { - abc: 123 - }; - }); -}); - test('Parcel.setChangeRequestMeta() should set change request meta', () => { var data = { value: 123, diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index da4dad1f..567f4f18 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -35,17 +35,6 @@ export default (_this: Parcel, dispatch: Function) => ({ dispatch(ActionCreators.setMeta(partialMeta)); }, - updateMeta: (updater: ParcelMetaUpdater) => { - Types(`updateMeta()`, `updater`, `function`)(updater); - let {meta} = _this._parcelData; - pipeWith( - meta, - updater, - Types(`updateMeta()`, `the result of updater()`, `object`), - _this.setMeta - ); - }, - setChangeRequestMeta: (partialMeta: ParcelMeta) => { Types(`setChangeRequestMeta()`, `partialMeta`, `object`)(partialMeta); dispatch(new ChangeRequest().setChangeRequestMeta(partialMeta)); From a3dced446c23030ac76d6d753745e6b0d1015033 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 11:06:18 +1100 Subject: [PATCH 026/120] BREAK: remove type ParcelMetaUpdater --- packages/dataparcels/src/index.js | 1 - packages/dataparcels/src/parcel/Parcel.js | 1 - .../dataparcels/src/parcel/methods/ParcelChangeMethods.js | 3 --- packages/dataparcels/src/types/Types.js | 4 ++-- packages/react-dataparcels/src/index.js | 1 - 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index 5e192d21..2c4c8558 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -10,7 +10,6 @@ export type {ParcelData} from './types/Types'; export type {ParcelConfig} from './types/Types'; export type {ParcelConfigInternal} from './types/Types'; export type {ParcelMeta} from './types/Types'; -export type {ParcelMetaUpdater} from './types/Types'; export type {ParcelBatcher} from './types/Types'; export type {ParcelMapper} from './types/Types'; diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 524ca7f9..68cc5f4d 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -10,7 +10,6 @@ import type {ParcelConfigInternal} from '../types/Types'; import type {ParcelConfig} from '../types/Types'; import type {ParcelData} from '../types/Types'; import type {ParcelMapper} from '../types/Types'; -import type {ParcelMetaUpdater} from '../types/Types'; import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 567f4f18..b0a14814 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -1,15 +1,12 @@ // @flow import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; -import type {ParcelMetaUpdater} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; import ActionCreators from '../../change/ActionCreators'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - export default (_this: Parcel, dispatch: Function) => ({ setSelf: (value: *) => { diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index 968ba335..b97fe3d2 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -44,13 +44,13 @@ export type CreateParcelConfigType = { }; export type ParcelMeta = {[key: string]: *}; -export type ParcelMetaUpdater = (meta: ParcelMeta) => ParcelMeta; - export type ParcelBatcher = (item: Parcel) => void; export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) => *; export type ParcelUpdater = (item: Parcel) => Parcel; export type ParcelValueUpdater = (value: *) => *; +export type StaticParcelMapper = (item: StaticParcel, index: string|number, _this: StaticParcel) => *; + export type MatchPipe = { match: string, depth: number, diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index 11eb276b..711b1e59 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -10,7 +10,6 @@ export type {ParcelData} from 'dataparcels'; export type {ParcelConfig} from 'dataparcels'; export type {ParcelConfigInternal} from 'dataparcels'; export type {ParcelMeta} from 'dataparcels'; -export type {ParcelMetaUpdater} from 'dataparcels'; export type {ParcelBatcher} from 'dataparcels'; export type {ParcelMapper} from 'dataparcels'; From ad74093b93ebe303baa8a34b3b7450a4022501f4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 11:06:31 +1100 Subject: [PATCH 027/120] amend: fix lint --- packages/dataparcels/src/parcel/methods/ParentGetMethods.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js index 19596385..8563cb15 100644 --- a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js @@ -10,7 +10,6 @@ import parcelGet from '../../parcelData/get'; import parcelHas from '../../parcelData/has'; import prepareChildKeys from '../../parcelData/prepareChildKeys'; -import keyArray from 'unmutable/lib/keyArray'; import map from 'unmutable/lib/map'; import size from 'unmutable/lib/size'; import toArray from 'unmutable/lib/toArray'; From e1a66a1b4603fb0a979591edd4b7a7a12afe8c81 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 5 Dec 2018 11:14:29 +1100 Subject: [PATCH 028/120] BREAK: remove Parcel.matchPipe --- .../src/docs/api/parcel/matchPipe.md | 3 - .../dataparcels-docs/src/pages/api/Parcel.jsx | 3 - packages/dataparcels/src/match/Matcher.js | 127 ------ .../src/match/__test__/Matcher-test.js | 426 ------------------ packages/dataparcels/src/parcel/Parcel.js | 16 +- .../parcel/__test__/ParcelGetMethods-test.js | 68 --- .../src/parcel/methods/ParcelGetMethods.js | 41 -- packages/dataparcels/src/types/Types.js | 8 - 8 files changed, 1 insertion(+), 691 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/matchPipe.md delete mode 100644 packages/dataparcels/src/match/Matcher.js delete mode 100644 packages/dataparcels/src/match/__test__/Matcher-test.js diff --git a/packages/dataparcels-docs/src/docs/api/parcel/matchPipe.md b/packages/dataparcels-docs/src/docs/api/parcel/matchPipe.md deleted file mode 100644 index 671697c8..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/matchPipe.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -matchPipe(match: string, ...updaters: Function[]): Parcel -``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 9340131b..8063a18f 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -57,7 +57,6 @@ import Markdown_log from 'docs/api/parcel/log.md'; import Markdown_spy from 'docs/api/parcel/spy.md'; import Markdown_spyChange from 'docs/api/parcel/spyChange.md'; import Markdown_pipe from 'docs/api/parcel/pipe.md'; -import Markdown_matchPipe from 'docs/api/parcel/matchPipe.md'; import Markdown_toConsole from 'docs/api/parcel/toConsole.md'; const md = { @@ -116,7 +115,6 @@ const md = { spy: Markdown_spy, spyChange: Markdown_spyChange, pipe: Markdown_pipe, - matchPipe: Markdown_matchPipe, toConsole: Markdown_toConsole } @@ -198,7 +196,6 @@ spyChange() # Composition methods pipe() -matchPipe() # Debug methods log() diff --git a/packages/dataparcels/src/match/Matcher.js b/packages/dataparcels/src/match/Matcher.js deleted file mode 100644 index f0dd5614..00000000 --- a/packages/dataparcels/src/match/Matcher.js +++ /dev/null @@ -1,127 +0,0 @@ -// @flow -import escapeStringRegexp from 'escape-string-regexp'; - -import join from 'unmutable/lib/join'; -import keyArray from 'unmutable/lib/keyArray'; -import map from 'unmutable/lib/map'; -import skip from 'unmutable/lib/skip'; -import pipe from 'unmutable/lib/util/pipe'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - -export const split = (match: string): string[] => pipeWith( - match, - escapeSpecialChars, - ii => ii.split("."), - map(unescapeSpecialChars) -); - -export const containsWildcard = (match: string): boolean => pipeWith( - match, - escapeSpecialChars, - ii => ii.replace(/\*\*/g, "").indexOf("*") !== -1 -); - -export const containsGlobstar = (match: string): boolean => pipeWith( - match, - escapeSpecialChars, - ii => ii.indexOf("**") !== -1 -); - -const TYPE_SELECTORS = { - ["Child"]: "C", - ["!Child"]: "c", - ["Element"]: "E", - ["!Element"]: "e", - ["Indexed"]: "I", - ["!Indexed"]: "i", - ["Parent"]: "P", - ["!Parent"]: "p", - ["TopLevel"]: "T", - ["!TopLevel"]: "t" -}; - -const SPECIAL_CHARS = [".", ":", "|", "*"]; -const REGEX_SPECIAL_CHARS = SPECIAL_CHARS.map(escapeStringRegexp); -const MATCH_ANY_IN_PART = "[^.]*?"; - -const escapeSpecialChars = pipe( - ...pipeWith( - REGEX_SPECIAL_CHARS, - map((chr: string, index: number): Function => { - return str => str.replace(new RegExp(`%${chr}`, "g"), `%${index}`); - }) - ) -); - -const unescapeSpecialChars = pipe( - ...pipeWith( - SPECIAL_CHARS, - map((chr: string, index: number): Function => { - return str => str.replace(new RegExp(`%${index}`, "g"), `%${chr}`); - }) - ) -); - -const regexifyGlobstars = str => str.replace(/\\\*\\\*/g, ".*?"); -const regexifyWildcards = str => str.replace(/\\\*/g, MATCH_ANY_IN_PART); - -const regexifyPart = (part: string): string => { - let [name, type] = part.split(":"); - - if(name === "") { - name = MATCH_ANY_IN_PART; - } - - // if no type, match any type selector - if(!type) { - return `${name}:${MATCH_ANY_IN_PART}`; - } - - // replace type with type selectors - let typeSelector = TYPE_SELECTORS[type]; - if(!typeSelector) { - let choices = pipeWith( - TYPE_SELECTORS, - keyArray(), - join(", ") - ); - throw new Error(`"${type}" is not a valid type selector. Choose one of ${choices}`); - } - - return `${name}:${MATCH_ANY_IN_PART}[${typeSelector}]${MATCH_ANY_IN_PART}`; -}; - -export default (typedPathString: string, match: string, depth: number = 0): boolean => { - let test = escapeSpecialChars(typedPathString); - if(depth > 0) { - test = pipeWith( - test, - ii => ii.split("."), - skip(depth), - join(".") - ); - } - - return escapeSpecialChars(match) - .split("|") - .some((escapedMatch: string): boolean => { - if(escapedMatch[0] === ".") { - if(escapedMatch.length === 1 || escapedMatch[1] === ":") { - escapedMatch = escapedMatch.slice(1); - } - escapedMatch = `*${escapedMatch}`; - } - - return pipeWith( - escapedMatch, - escapeStringRegexp, - ii => ii.split("\\."), - map(regexifyPart), - join("\\."), - regexifyGlobstars, - regexifyWildcards, - regex => `^${regex}$`, - (regex) => new RegExp(regex, "g").test(test) - ); - }); -}; diff --git a/packages/dataparcels/src/match/__test__/Matcher-test.js b/packages/dataparcels/src/match/__test__/Matcher-test.js deleted file mode 100644 index f8774e71..00000000 --- a/packages/dataparcels/src/match/__test__/Matcher-test.js +++ /dev/null @@ -1,426 +0,0 @@ -// @flow -import Matcher, { split, containsWildcard, containsGlobstar } from '../Matcher'; - -import filter from 'unmutable/lib/filter'; -import identity from 'unmutable/lib/identity'; -import keyArray from 'unmutable/lib/keyArray'; -import map from 'unmutable/lib/map'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - -// -// match -// - -let typedPathStrings = { - top: "^:ceiPT", - childValue: "^:ceiPT.abc:Ceipt", - childObject: "^:ceiPT.def:CeiPt", - grandchildValue: "^:ceiPT.def:CeiPt.defkid:Ceipt", - grandchildWithDot: "^:ceiPT.def:CeiPt.dot%.dot:Ceipt", - greatGrandchild: "^:ceiPT.def:CeiPt.more:CeiPt.abc:Ceipt", - childArray: "^:ceiPT.ghi:CeIPt", - grandchildElement: "^:ceiPT.ghi:CeIPt.#a:CEipt", - escapeChars: "^:ceiPT.jkl%.%:%|%#%,:Ceipt" -}; - -let matchTests = [ - { - name: "match self", - match: ".", - shouldMatch: ["top"] - }, - { - name: "match self with depth = 1", - match: ".", - shouldMatch: [ - "childValue", - "childObject", - "childArray", - "escapeChars" - ], - depth: 1 - }, - { - name: "match self with depth = 2", - match: ".", - shouldMatch: [ - "grandchildValue", - "grandchildWithDot", - "grandchildElement" - ], - depth: 2 - }, - { - name: "match self with depth = 3", - match: ".", - shouldMatch: [ - "greatGrandchild" - ], - depth: 3 - }, - { - name: "match by full name", - match: "^", - shouldMatch: ["top"] - }, - { - name: "match child by full name", - match: ".abc", - shouldMatch: ["childValue"] - }, - { - name: "match child with escape chars", - match: ".jkl%.%:%|%#%,", - shouldMatch: ["escapeChars"] - }, - { - name: "match child that doesnt exist / dont match grandchild", - match: ".defkid", - shouldMatch: [] - }, - { - name: "match grandchild", - match: ".def.defkid", - shouldMatch: ["grandchildValue"] - }, - { - name: "match grandchild element", - match: ".ghi.#a", - shouldMatch: ["grandchildElement"] - }, - { - name: "match multiple", - match: ".abc|.ghi.#a", - shouldMatch: ["childValue", "grandchildElement"] - }, - { - name: "match wildcard", - match: ".*", - shouldMatch: ["childValue", "childObject", "childArray", "escapeChars"] - }, - { - name: "match wildcard start", - match: ".*f", - shouldMatch: ["childObject"] - }, - { - name: "match wildcard middle", - match: ".*e*", - shouldMatch: ["childObject"] - }, - { - name: "match wildcard end", - match: ".d*", - shouldMatch: ["childObject"] - }, - { - name: "match wildcard in array", - match: ".ghi.*", - shouldMatch: ["grandchildElement"] - }, - { - name: "match wildcards in keypath", - match: ".def.*.abc", - shouldMatch: ["greatGrandchild"] - }, - { - name: "match wildcards in keypath", - match: ".*.*.*", - shouldMatch: ["greatGrandchild"] // and NOT grandchildWithDot - }, - { - name: "match globstar", - match: "**", - shouldMatch: [ - "top", - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "childArray", - "grandchildElement", - "escapeChars" - ] - }, - { - name: "match globstar start", - match: "**abc", - shouldMatch: ["childValue", "greatGrandchild"] - }, - { - name: "match globstar start (negative test)", - match: "**def", - shouldMatch: ["childObject"] - }, - { - name: "match globstar middle", - match: "**def**", - shouldMatch: [ - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild" - ] - }, - { - name: "match globstar end", - match: ".ghi.**", - shouldMatch: ["grandchildElement"] - }, - { - name: "match globstar children", - match: ".**", - shouldMatch: [ - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "childArray", - "grandchildElement", - "escapeChars" - ] - }, - { - name: "match self with type", - match: ".:Parent", - shouldMatch: ["top"] - }, - { - name: "match self with type", - match: ".:Indexed", - shouldMatch: [] - }, - { - name: "match child by full name with type", - match: ".abc:Child", - shouldMatch: ["childValue"] - }, - { - name: "match child by full name with type", - match: ".abc:Parent", - shouldMatch: [] - }, - { - name: "match child with escape chars with type", - match: ".jkl%.%:%|%#%,:Child", - shouldMatch: ["escapeChars"] - }, - { - name: "match child with escape chars with type", - match: ".jkl%.%:%|%#%,:Parent", - shouldMatch: [] - }, - { - name: "match wildcard children with type", - match: ".*:Child", - shouldMatch: ["childValue", "childObject", "childArray", "escapeChars"] - }, - { - name: "match wildcard children with type", - match: ".*:Parent", - shouldMatch: ["childObject", "childArray"] - }, - { - name: "match wildcard children with type", - match: ".*:Indexed", - shouldMatch: ["childArray"] - }, - { - name: "match wildcard children with type", - match: ".*:Element", - shouldMatch: [] - }, - { - name: "match wildcard children with type", - match: ".*:TopLevel", - shouldMatch: [] - }, - { - name: "match wildcard children with negative type", - match: ".*:!Child", - shouldMatch: [] - }, - { - name: "match wildcard children with negative type", - match: ".*:!Parent", - shouldMatch: ["childValue", "escapeChars"] - }, - { - name: "match wildcard children with negative type", - match: ".*:!Indexed", - shouldMatch: ["childValue", "childObject", "escapeChars"] - }, - { - name: "match wildcard children with negative type", - match: ".*:!Element", - shouldMatch: ["childValue", "childObject", "childArray", "escapeChars"] - }, - { - name: "match wildcard children with negative type", - match: ".*:!TopLevel", - shouldMatch: ["childValue", "childObject", "childArray", "escapeChars"] - }, - { - name: "match globstar with type", - match: "**:Parent", - shouldMatch: [ - "top", - "childObject", - "childArray" - ] - }, - { - name: "match globstar with wildcard", - match: "**.*", - shouldMatch: [ - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "childArray", - "grandchildElement", - "escapeChars" - ] - }, - { - name: "match globstar with two wildcards", - match: "**.*.*", - shouldMatch: [ - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "grandchildElement" - ] - }, - { - name: "match globstar and wildcard with type", - match: "**.*:Parent", - shouldMatch: [ - "childObject", - "childArray" - ] - }, - { - name: "match globstar with type", - match: "**:Indexed", - shouldMatch: ["childArray"] - }, - { - name: "match globstar with type", - match: "**:Element", - shouldMatch: ["grandchildElement"] - }, - { - name: "match globstar with type", - match: "**:TopLevel", - shouldMatch: ["top"] - }, - { - name: "match globstar with negative type", - match: "**:!Child", - shouldMatch: ["top"] - }, - { - name: "match globstar with negative type", - match: "**:!Parent", - shouldMatch: [ - "childValue", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "grandchildElement", - "escapeChars" - ] - }, - { - name: "match globstar with negative type", - match: "**:!Indexed", - shouldMatch: [ - "top", - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "grandchildElement", - "escapeChars" - ] - }, - { - name: "match globstar with negative type", - match: "**:!Element", - shouldMatch: [ - "top", - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "childArray", - "escapeChars" - ] - }, - { - name: "match globstar with negative type", - match: "**:!TopLevel", - shouldMatch: [ - "childValue", - "childObject", - "grandchildValue", - "grandchildWithDot", - "greatGrandchild", - "childArray", - "grandchildElement", - "escapeChars" - ] - } -]; - -pipeWith( - matchTests, - map(({name, match, matchParsed, shouldMatch, depth = 0}) => { - test(`${name}`, () => { - let matched: string[] = pipeWith( - typedPathStrings, - map((typedPathString, name) => Matcher(typedPathString, match, depth)), - filter(identity()), - keyArray() - ); - expect(matched).toEqual(shouldMatch); - }); - }) -); - -test(`split() should split`, () => { - expect(['abc']).toEqual(split(`abc`)); - expect(['abc', 'def']).toEqual(split(`abc.def`)); - expect(['abc', 'de%.f']).toEqual(split(`abc.de%.f`)); -}); - -test(`containsWildcard() should identify when a match string contains a wildcard`, () => { - expect(containsWildcard(`abc`)).toBe(false); - expect(containsWildcard(`abc*`)).toBe(true); - expect(containsWildcard(`abc.*`)).toBe(true); - expect(containsWildcard(`abc%*`)).toBe(false); - expect(containsWildcard(`abc%*.*`)).toBe(true); - expect(containsWildcard(`**`)).toBe(false); - expect(containsWildcard(`abc.**`)).toBe(false); - expect(containsWildcard(`abc.*.**`)).toBe(true); - expect(containsWildcard(`abc%**`)).toBe(true); -}); - -test(`containsGlobstar() should identify when a match string contains a globstar`, () => { - expect(containsGlobstar(`abc`)).toBe(false); - expect(containsGlobstar(`abc*`)).toBe(false); - expect(containsGlobstar(`abc.*`)).toBe(false); - expect(containsGlobstar(`abc%*`)).toBe(false); - expect(containsGlobstar(`abc%*.*`)).toBe(false); - expect(containsGlobstar(`**`)).toBe(true); - expect(containsGlobstar(`abc.**`)).toBe(true); - expect(containsGlobstar(`abc.*.**`)).toBe(true); - expect(containsGlobstar(`abc%**`)).toBe(false); -}); - diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 68cc5f4d..0e5b1cb9 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -4,7 +4,6 @@ import type ChangeRequest from '../change/ChangeRequest'; import type {CreateParcelConfigType} from '../types/Types'; import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; -import type {MatchPipe} from '../types/Types'; import type {ParcelBatcher} from '../types/Types'; import type {ParcelConfigInternal} from '../types/Types'; import type {ParcelConfig} from '../types/Types'; @@ -42,7 +41,6 @@ const DEFAULT_CONFIG_INTERNAL = () => ({ child: undefined, meta: {}, id: new ParcelId(), - matchPipes: [], parent: undefined, treeshare: undefined }); @@ -65,7 +63,6 @@ export default class Parcel { child, meta, id, - matchPipes, parent, treeshare } = _configInternal || DEFAULT_CONFIG_INTERNAL(); @@ -86,9 +83,6 @@ export default class Parcel { this._parent = parent; } - // match pipes - this._matchPipes = matchPipes || []; - // types this._parcelTypes = new ParcelTypes( value, @@ -154,14 +148,12 @@ export default class Parcel { _dispatchBuffer: ?Function; // used by batch() _log: boolean = false; // used by log() _logName: string = ""; // used by log() - _matchPipes: MatchPipe[]; // used by matchPipe() and passed to all subsequent parcels _create = (createParcelConfig: CreateParcelConfigType): Parcel => { let { id = this._id, onDispatch = this.dispatch, handleChange, - matchPipes = this._matchPipes, parent, parcelData = this._parcelData, treeshare = this._treeshare @@ -173,7 +165,7 @@ export default class Parcel { meta = {} } = parcelData; - let parcel: Parcel = new Parcel( + return new Parcel( { value, handleChange @@ -182,16 +174,11 @@ export default class Parcel { child, meta, id, - matchPipes, onDispatch, parent, treeshare } ); - - return parent - ? parcel._methods._applyMatchPipes() - : parcel; }; // @@ -360,7 +347,6 @@ export default class Parcel { // Composition methods pipe = (...updaters: ParcelUpdater[]): Parcel => this._methods.pipe(...updaters); - matchPipe = (match: string, ...updaters: ParcelUpdater[]): Parcel => this._methods.matchPipe(match, ...updaters); // Advanced methods getInternalLocationShareData = (): * => this._methods.getInternalLocationShareData(); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js index 008c8e60..6b9e994d 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js @@ -176,71 +176,3 @@ test('Parcel.pipe() should pass itself in and return what pipe() returns', () => expect(updater2.mock.calls[0][0]).toBe(parcel1); expect(result).toBe(parcel2); }); - -test('Parcel.matchPipe() should match self', () => { - let updater = jest.fn(_ => _); - - let parcel = new Parcel({value: 123}).matchPipe(".", updater); - - expect(updater.mock.calls.length).toBe(1); - expect(updater.mock.calls[0][0].id).toBe("^.~mp"); -}); - -test('Parcel.matchPipe() should match child', () => { - let updater = jest.fn(_ => _); - - let parcel = new Parcel({value: [123]}).matchPipe(".#a", updater).get(0); - - expect(updater.mock.calls.length).toBe(1); - expect(updater.mock.calls[0][0].id).toBe("^.~mp.#a"); -}); - -test('Parcel.matchPipe() should match child with a deep origin', () => { - let updater = jest.fn(_ => _); - - let parcel = new Parcel({ - value: { - abc: { - def: 123 - } - } - }) - .get("abc") - .matchPipe(".def", updater) - .get("def"); - - expect(updater.mock.calls.length).toBe(1); - expect(updater.mock.calls[0][0].id).toBe("^.abc.~mp.def"); -}); - -test('Parcel.matchPipe() can match child', () => { - let updater = jest.fn(_ => _); - - let parcel = new Parcel({ - value: { - abc: 123, - def: 456 - } - }).matchPipe(".abc", updater); - - parcel.get("abc"); - parcel.get("def"); - - expect(updater.mock.calls.length).toBe(1); - expect(updater.mock.calls[0][0].id).toBe("^.~mp.abc"); -}); - - -test('When matching only self, Parcel.matchPipe() should pass a cloned version of itself in and return what matchPipe() returns', () => { - var parcel1 = new Parcel(); - var parcel2 = new Parcel(); - - let updater1 = jest.fn(_ => _); - let updater2 = jest.fn(_ => parcel2); - - var result = parcel1.matchPipe(".", updater1, updater2); - - expect(updater1.mock.calls[0][0].value).toBe(parcel1.value); // parcel will be a cloned version of itself - expect(updater2.mock.calls[0][0]).toBe(updater1.mock.calls[0][0]); // second updater should receive same parcel as first - expect(result).toBe(parcel2); -}); diff --git a/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js b/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js index fd2b117b..d5775ddb 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js @@ -2,10 +2,8 @@ import type ChangeRequest from '../../change/ChangeRequest'; import type Parcel from '../../parcel/Parcel'; import type {ParcelUpdater} from '../../types/Types'; -import type {MatchPipe} from '../../types/Types'; import Types from '../../types/Types'; -import Matcher from '../../match/Matcher'; import DeletedParcelMarker from '../../parcelData/DeletedParcelMarker'; import map from 'unmutable/lib/map'; @@ -49,45 +47,6 @@ export default (_this: Parcel) => ({ ); }, - matchPipe: (match: string, ...updaters: ParcelUpdater[]): Parcel => { - Types(`matchPipe()`, `first param`, `string`)(match); - updaters.forEach(Types(`matchPipe()`, `all updaters`, `function`)); - - let parcel = _this._create({ - id: _this._id.pushModifier('mp'), - matchPipes: [ - ..._this._matchPipes, - { - depth: _this.path.length, - match, - updater: pipe( - ...pipeWith( - updaters, - map(updater => pipe( - updater, - Types(`matchPipe() `, `the result of all functions`, `parcel`) - )) - ) - ) - } - ] - }); - return parcel._methods._applyMatchPipes(); - }, - - _applyMatchPipes: (): Parcel => { - let typedPathString = _this._id.typedPathString(); - return pipeWith( - _this, - ..._this._matchPipes - .filter(({match, depth}: MatchPipe): boolean => { - let matched = Matcher(typedPathString, match, depth); - return matched; - }) - .map(({updater}: MatchPipe) => updater) - ); - }, - // Status methods hasDispatched: (): boolean => { diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index b97fe3d2..d29edfeb 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -28,7 +28,6 @@ export type ParcelConfigInternal = { child: *, meta: ParcelMeta, id: ParcelId, - matchPipes?: MatchPipe[], parent?: ?Parcel, treeshare: Treeshare }; @@ -36,7 +35,6 @@ export type ParcelConfigInternal = { export type CreateParcelConfigType = { onDispatch?: Function, id?: ParcelId, - matchPipes?: MatchPipe[], parcelData?: ParcelData, parent?: ?Parcel, handleChange?: Function, @@ -51,12 +49,6 @@ export type ParcelValueUpdater = (value: *) => *; export type StaticParcelMapper = (item: StaticParcel, index: string|number, _this: StaticParcel) => *; -export type MatchPipe = { - match: string, - depth: number, - updater: ParcelUpdater -}; - export type Key = string; export type Index = number; export type Property = number|string; From cad57fb5dd60a20d2a713d504ba822accec5977d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 6 Dec 2018 09:53:30 +1100 Subject: [PATCH 029/120] refactor: remove typedPathString and typeCode logic --- packages/dataparcels/src/parcel/Parcel.js | 4 +--- packages/dataparcels/src/parcel/ParcelTypes.js | 9 --------- .../src/parcel/__test__/ParcelGetters-test.js | 17 ----------------- .../src/parcel/__test__/ParcelTypes-test.js | 10 ---------- packages/dataparcels/src/parcelId/ParcelId.js | 17 ++--------------- packages/dataparcels/src/types/Types.js | 10 +--------- 6 files changed, 4 insertions(+), 63 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 0e5b1cb9..cbeee4da 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -90,10 +90,8 @@ export default class Parcel { !!(id && id.path().length === 0) ); + // id this._id = id; - if(!_configInternal || parent) { - this._id.setTypeCode(this._parcelTypes.toTypeCode()); - } // treeshare this._treeshare = treeshare || new Treeshare({debugRender}); diff --git a/packages/dataparcels/src/parcel/ParcelTypes.js b/packages/dataparcels/src/parcel/ParcelTypes.js index 3068bd34..55747a93 100644 --- a/packages/dataparcels/src/parcel/ParcelTypes.js +++ b/packages/dataparcels/src/parcel/ParcelTypes.js @@ -23,13 +23,4 @@ export default class ParcelTypes { isIndexed: Function = (): boolean => this._isIndexed; isParent: Function = (): boolean => this._isParent; isTopLevel: Function = (): boolean => this._isTopLevel; - - toTypeCode: Function = (): string => { - let c: string = this._isChild ? "C" : "c"; - let e: string = this._isElement ? "E" : "e"; - let i: string = this._isIndexed ? "I" : "i"; - let p: string = this._isParent ? "P" : "p"; - let t: string = this._isTopLevel ? "T" : "t"; - return `${c}${e}${i}${p}${t}`; - }; } diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js index ce85cb2d..4491949b 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js @@ -97,20 +97,3 @@ test('Parcel.path should return the Parcels path', () => { expect(["b"]).toEqual(new Parcel(data).get("b").path); // t.is("#a", new Parcel(data).getIn(["a",?????]).path); TODO }); - -test('Parcel._id.typedPathString() should return the Parcels typed path', () => { - var data = { - value: { - a: [1,2,3], - ['something.:@']: 123 - } - }; - expect("^:ceiPT").toEqual(new Parcel(data)._id.typedPathString()); - expect("^:ceiPT").toEqual(new Parcel(data).modifyValueDown(ii => ii)._id.typedPathString()); - expect("^:ceiPT.a:CeIPt").toEqual(new Parcel(data).get("a")._id.typedPathString()); - expect("^:ceiPT.a:CeIPt").toEqual(new Parcel(data).modifyValueDown(ii => ii).get("a")._id.typedPathString()); - expect("^:ceiPT.a:CeIPt.#a:CEipt").toEqual(new Parcel(data).getIn(["a",0])._id.typedPathString()); - expect("^:ceiPT.something%.%:%@:Ceipt").toEqual(new Parcel(data).get("something.:@")._id.typedPathString()); - expect("^:ceiPT.b:Ceipt").toEqual(new Parcel(data).get("b")._id.typedPathString()); - // t.is("#a", new Parcel(data).getIn(["a",?????])._id.typedPathString()); TODO -}); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js index c42dd1c0..f07605a5 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js @@ -11,7 +11,6 @@ test('ParcelTypes should correctly identify primitive values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceipT"); }); test('ParcelTypes should correctly identify date', () => { @@ -23,7 +22,6 @@ test('ParcelTypes should correctly identify date', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceipT"); }); test('ParcelTypes should correctly identify object values', () => { @@ -37,7 +35,6 @@ test('ParcelTypes should correctly identify object values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceiPT"); }); test('ParcelTypes should correctly identify class instance values', () => { @@ -52,7 +49,6 @@ test('ParcelTypes should correctly identify class instance values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceipT"); }); test('ParcelTypes should correctly identify unmutable compatible class instance values', () => { @@ -68,7 +64,6 @@ test('ParcelTypes should correctly identify unmutable compatible class instance expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceiPT"); }); @@ -83,7 +78,6 @@ test('ParcelTypes should correctly identify Immutable.js Map values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceiPT"); }); @@ -96,7 +90,6 @@ test('ParcelTypes should correctly identify array values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceIPT"); }); test('ParcelTypes should correctly identify Immutable.js List values', () => { @@ -108,7 +101,6 @@ test('ParcelTypes should correctly identify Immutable.js List values', () => { expect(new Parcel(data).isChild()).toBe(false); expect(new Parcel(data).isElement()).toBe(false); expect(new Parcel(data).isTopLevel()).toBe(true); - expect(new Parcel(data)._parcelTypes.toTypeCode()).toBe("ceIPT"); }); test('ParcelTypes should correctly identify child values', () => { @@ -122,7 +114,6 @@ test('ParcelTypes should correctly identify child values', () => { expect(new Parcel(data).get("a").isChild()).toBe(true); expect(new Parcel(data).get("a").isElement()).toBe(false); expect(new Parcel(data).get("a").isTopLevel()).toBe(false); - expect(new Parcel(data).get("a")._parcelTypes.toTypeCode()).toBe("Ceipt"); }); test('ParcelTypes should correctly identify element values', () => { @@ -134,7 +125,6 @@ test('ParcelTypes should correctly identify element values', () => { expect(new Parcel(data).get(0).isChild()).toBe(true); expect(new Parcel(data).get(0).isElement()).toBe(true); expect(new Parcel(data).get(0).isTopLevel()).toBe(false); - expect(new Parcel(data).get(0)._parcelTypes.toTypeCode()).toBe("CEipt"); }); test('ParcelTypes should correctly identify top level values after modifiers', () => { diff --git a/packages/dataparcels/src/parcelId/ParcelId.js b/packages/dataparcels/src/parcelId/ParcelId.js index 3d2dbe69..89fe2998 100644 --- a/packages/dataparcels/src/parcelId/ParcelId.js +++ b/packages/dataparcels/src/parcelId/ParcelId.js @@ -13,19 +13,16 @@ export const stringifyPath = (path: string[]): string => path.map(escapeKey).joi const DEFAULT_PARCELID_DATA = { id: ["^"], - path: ["^"], - typedPath: ["^"] + path: ["^"] }; export default class ParcelId { _id: string[]; _path: string[]; - _typedPath: string[]; constructor(parcelIdData: ParcelIdData = DEFAULT_PARCELID_DATA) { this._id = parcelIdData.id; this._path = parcelIdData.path; - this._typedPath = parcelIdData.typedPath; } _create: Function = (data: Object): ParcelId => { @@ -44,10 +41,6 @@ export default class ParcelId { return rest()(this._path); }; - typedPathString: Function = (): string => { - return this._typedPath.join("."); - }; - push: Function = (key: Key, isElement: boolean): ParcelId => { let escapedKey = escapeKey(key); let escapeAndPush: Function = isElement @@ -58,7 +51,6 @@ export default class ParcelId { this.toJS(), update('id', escapeAndPush), update('path', push(key)), - update('typedPath', escapeAndPush), this._create ); }; @@ -73,11 +65,6 @@ export default class ParcelId { toJS: Function = (): Object => ({ id: this._id, - path: this._path, - typedPath: this._typedPath + path: this._path }); - - setTypeCode: Function = (typeCode: string) => { - this._typedPath = update(-1, ii =>`${ii}:${typeCode}`)(this._typedPath); - }; } diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index d29edfeb..bc6a3910 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -5,7 +5,6 @@ import type Treeshare from '../treeshare/Treeshare'; import Parcel from '../parcel/Parcel'; import Action from '../change/Action'; import ChangeRequest from '../change/ChangeRequest'; -import StaticParcel from '../staticParcel/StaticParcel'; import isPlainObject from 'unmutable/lib/util/isPlainObject'; export type ParcelData = { @@ -47,16 +46,13 @@ export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) = export type ParcelUpdater = (item: Parcel) => Parcel; export type ParcelValueUpdater = (value: *) => *; -export type StaticParcelMapper = (item: StaticParcel, index: string|number, _this: StaticParcel) => *; - export type Key = string; export type Index = number; export type Property = number|string; export type ParcelIdData = { id: string[], - path: string[], - typedPath: string[] + path: string[] }; const RUNTIME_TYPES = { @@ -109,10 +105,6 @@ const RUNTIME_TYPES = { name: "an object containing parcel data {value: *, meta?: {}, key?: *}", check: ii => isPlainObject(ii) && ii.hasOwnProperty('value') }, - ['staticParcel']: { - name: "a StaticParcel", - check: ii => ii instanceof StaticParcel - }, ['string']: { name: "a string", check: ii => typeof ii === "string" From 3aaef4c6356dcc5127469205fc80e41a690d278d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 6 Dec 2018 10:00:02 +1100 Subject: [PATCH 030/120] refactor: remove ping and shouldBeSynchronous --- .../src/docs/api/action/isValueAction.md | 2 +- .../docs/api/action/shouldBeSynchronous.md | 5 --- .../src/docs/api/parcel/ping.md | 3 -- .../dataparcels-docs/src/pages/api/Action.jsx | 3 -- .../src/pages/api/ChangeRequest.jsx | 1 - .../dataparcels-docs/src/pages/api/Parcel.jsx | 3 -- packages/dataparcels/src/change/Action.js | 6 +--- .../dataparcels/src/change/ActionCreators.js | 7 ---- .../dataparcels/src/change/ChangeRequest.js | 6 ---- .../src/change/ChangeRequestReducer.js | 1 - .../src/change/__test__/Action-test.js | 10 +----- .../__test__/ChangeRequestReducerPing-test.js | 33 ------------------- packages/dataparcels/src/parcel/Parcel.js | 1 - .../__test__/ParcelChangeMethods-test.js | 22 ------------- .../src/parcel/methods/ParcelChangeMethods.js | 4 --- .../react-dataparcels/src/ParcelBoundary.jsx | 4 +-- .../src/__test__/ParcelBoundary-test.js | 23 ------------- 17 files changed, 4 insertions(+), 130 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/action/shouldBeSynchronous.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/ping.md delete mode 100644 packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js diff --git a/packages/dataparcels-docs/src/docs/api/action/isValueAction.md b/packages/dataparcels-docs/src/docs/api/action/isValueAction.md index 3d9b29a7..aad95f5f 100644 --- a/packages/dataparcels-docs/src/docs/api/action/isValueAction.md +++ b/packages/dataparcels-docs/src/docs/api/action/isValueAction.md @@ -4,4 +4,4 @@ isValueAction(): boolean Returns true if the action affects the original parcel's value. -Actions such as `setMeta` and `ping` do not affect the original parcel's value and are not value actions. +Actions such as `setMeta` do not affect the original parcel's value and are not value actions. diff --git a/packages/dataparcels-docs/src/docs/api/action/shouldBeSynchronous.md b/packages/dataparcels-docs/src/docs/api/action/shouldBeSynchronous.md deleted file mode 100644 index 9a75aa7a..00000000 --- a/packages/dataparcels-docs/src/docs/api/action/shouldBeSynchronous.md +++ /dev/null @@ -1,5 +0,0 @@ -```flow -shouldBeSynchronous(): boolean -``` - -Some types of actions (such as `ping`) are "synchronous", meaning that they will ignore debouncing and buffering, propagating immediately to the top level parcel when included in a ChangeRequest. This method returns true if the action is synchronous. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/ping.md b/packages/dataparcels-docs/src/docs/api/parcel/ping.md deleted file mode 100644 index dd69f228..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/ping.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -ping(): void -``` diff --git a/packages/dataparcels-docs/src/pages/api/Action.jsx b/packages/dataparcels-docs/src/pages/api/Action.jsx index edfefe3a..77ec4b7c 100644 --- a/packages/dataparcels-docs/src/pages/api/Action.jsx +++ b/packages/dataparcels-docs/src/pages/api/Action.jsx @@ -3,14 +3,12 @@ import type {Node} from 'react'; import React from 'react'; import ApiPage from 'component/ApiPage'; import Markdown_Action from 'docs/api/action/Action.md'; -import Markdown_shouldBeSynchronous from 'docs/api/action/shouldBeSynchronous.md'; import Markdown_isValueAction from 'docs/api/action/isValueAction.md'; import Markdown_isMetaAction from 'docs/api/action/isMetaAction.md'; import Markdown_toJS from 'docs/api/action/toJS.md'; const md = { _desc: Markdown_Action, - shouldBeSynchronous: Markdown_shouldBeSynchronous, isValueAction: Markdown_isValueAction, isMetaAction: Markdown_isMetaAction, toJS: Markdown_toJS @@ -18,7 +16,6 @@ const md = { const api = ` # Methods -shouldBeSynchronous() isValueAction() isMetaAction() toJS() diff --git a/packages/dataparcels-docs/src/pages/api/ChangeRequest.jsx b/packages/dataparcels-docs/src/pages/api/ChangeRequest.jsx index 8ac92e56..ce622c7a 100644 --- a/packages/dataparcels-docs/src/pages/api/ChangeRequest.jsx +++ b/packages/dataparcels-docs/src/pages/api/ChangeRequest.jsx @@ -23,7 +23,6 @@ updateActions() merge() getDataIn() hasValueChanged() -shouldBeSynchronous() toJS() toConsole() `; diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 8063a18f..2ab6c694 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -42,7 +42,6 @@ import Markdown_setChangeRequestMeta from 'docs/api/parcel/setChangeRequestMeta. import Markdown_dispatch from 'docs/api/parcel/dispatch.md'; import Markdown_batch from 'docs/api/parcel/batch.md'; import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; -import Markdown_ping from 'docs/api/parcel/ping.md'; import Markdown_modifyValueDown from 'docs/api/parcel/modifyValueDown.md'; import Markdown_modifyValueUp from 'docs/api/parcel/modifyValueUp.md'; import Markdown_modifyChange from 'docs/api/parcel/modifyChange.md'; @@ -100,7 +99,6 @@ const md = { dispatch: Markdown_dispatch, batch: Markdown_batch, batchAndReturn: Markdown_batchAndReturn, - ping: Markdown_ping, modifyValueDown: Markdown_modifyValueDown, modifyValueUp: Markdown_modifyValueUp, modifyChange: Markdown_modifyChange, @@ -172,7 +170,6 @@ setChangeRequestMeta() dispatch() batch() batchAndReturn() -ping() # Modify methods modifyValueDown() diff --git a/packages/dataparcels/src/change/Action.js b/packages/dataparcels/src/change/Action.js index afc2bc3b..663b6ab7 100644 --- a/packages/dataparcels/src/change/Action.js +++ b/packages/dataparcels/src/change/Action.js @@ -74,12 +74,8 @@ export default class Action { return this._add(_ => _._addPost(post)); }; - shouldBeSynchronous = (): boolean => { - return this.type === "ping"; - }; - isValueAction = (): boolean => { - return this.type !== "ping" && this.type !== "setMeta"; + return this.type !== "setMeta"; }; isMetaAction = (): boolean => { diff --git a/packages/dataparcels/src/change/ActionCreators.js b/packages/dataparcels/src/change/ActionCreators.js index b0d4cb41..47fa52a5 100644 --- a/packages/dataparcels/src/change/ActionCreators.js +++ b/packages/dataparcels/src/change/ActionCreators.js @@ -48,12 +48,6 @@ const insertBeforeSelf: Function = (value: *): Action => { }); }; -const ping: Function = (): Action => { - return new Action({ - type: "ping" - }); -}; - const push: Function = (value: *): Action => { return new Action({ type: "push", @@ -153,7 +147,6 @@ export default { insertAfterSelf, insertBefore, insertBeforeSelf, - ping, push, pop, setMeta, diff --git a/packages/dataparcels/src/change/ChangeRequest.js b/packages/dataparcels/src/change/ChangeRequest.js index c83cc4fc..cd0f3045 100644 --- a/packages/dataparcels/src/change/ChangeRequest.js +++ b/packages/dataparcels/src/change/ChangeRequest.js @@ -172,12 +172,6 @@ export default class ChangeRequest { return next.value !== prev.value; }; - shouldBeSynchronous = (): boolean => { - return this - ._actions - .some(action => action.shouldBeSynchronous()); - }; - toJS = (): Object => { return { actions: this._actions.map(action => action.toJS()), diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 57b4e61a..d9c4c8c9 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -31,7 +31,6 @@ const actionMap = { delete: ({lastKey}) => del(lastKey), insertAfter: ({lastKey, value}) => insertAfter(lastKey, value), insertBefore: ({lastKey, value}) => insertBefore(lastKey, value), - ping: () => identity(), pop: () => pop(), push: ({value}) => push(value), setMeta: ({meta}) => setMeta(meta), diff --git a/packages/dataparcels/src/change/__test__/Action-test.js b/packages/dataparcels/src/change/__test__/Action-test.js index 7fed22b1..de5cd8c0 100644 --- a/packages/dataparcels/src/change/__test__/Action-test.js +++ b/packages/dataparcels/src/change/__test__/Action-test.js @@ -32,12 +32,6 @@ test('Action should build an action with a default keyPath', () => { expect(new Action({type: "???"}).keyPath).toEqual([]); }); -test('Action should be synchronous if it has a type of ping, else not', () => { - expect(new Action({type: "ping"}).shouldBeSynchronous()).toBe(true); - expect(new Action({type: "set"}).shouldBeSynchronous()).toBe(false); - expect(new Action({type: "???"}).shouldBeSynchronous()).toBe(false); -}); - test('Action _unget should unshift key to front of empty keyPath', () => { let action = { type: "woo", @@ -229,14 +223,12 @@ test('Action _addPost twice should put post functions in same keyPathModifiers', {key: 'a', post: [post, post2], pre: []} ]); }); -test('Action should be value action if it isnt ping or setMeta', () => { - expect(new Action({type: "ping"}).isValueAction()).toBe(false); +test('Action should be value action if it isnt setMeta', () => { expect(new Action({type: "set"}).isValueAction()).toBe(true); expect(new Action({type: "setMeta"}).isValueAction()).toBe(false); }); test('Action should be meta action if it is setMeta', () => { - expect(new Action({type: "ping"}).isMetaAction()).toBe(false); expect(new Action({type: "set"}).isMetaAction()).toBe(false); expect(new Action({type: "setMeta"}).isMetaAction()).toBe(true); }); diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js deleted file mode 100644 index 7dea799a..00000000 --- a/packages/dataparcels/src/change/__test__/ChangeRequestReducerPing-test.js +++ /dev/null @@ -1,33 +0,0 @@ -// @flow -import ChangeRequest from '../ChangeRequest'; -import ChangeRequestReducer from '../ChangeRequestReducer'; -import Action from '../Action'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - -const makeReducer = (action) => pipeWith( - new ChangeRequest(action), - ChangeRequestReducer -); - -test('ChangeRequestReducer should ping', () => { - var data = { - value: [ - 0, - 1, - 2 - ], - key: "^", - child: undefined - }; - var action = new Action({ - type: "ping" - }); - - var expectedValue = [ - 0, - 1, - 2 - ]; - expect(makeReducer(action)(data).value).toEqual(expectedValue); -}); - diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index cbeee4da..3df9bfc0 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -299,7 +299,6 @@ export default class Parcel { dispatch = (dispatchable: Action|Action[]|ChangeRequest) => this._methods.dispatch(dispatchable); batch = (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => this._methods.batch(batcher, changeRequest); batchAndReturn = (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => this._methods.batchAndReturn(batcher, changeRequest); - ping = () => this._methods.ping(); // Indexed methods insertAfter = overload({ diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index d626417f..6e04a545 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -234,25 +234,3 @@ test('Parcel.setChangeRequestMeta() should set change request meta', () => { parcel.setChangeRequestMeta({a: 3}); }); }); - -test('Parcel.ping() should call the Parcels handleChange function with no change', () => { - expect.assertions(1); - - var data = { - value: 123 - }; - - var expectedData = { - child: undefined, - meta: {}, - value: 123, - key: '^' - }; - - new Parcel({ - ...data, - handleChange: (parcel, changeRequest) => { - expect(expectedData).toEqual(parcel.data); - } - }).ping(456); -}); diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index b0a14814..12db7666 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -35,9 +35,5 @@ export default (_this: Parcel, dispatch: Function) => ({ setChangeRequestMeta: (partialMeta: ParcelMeta) => { Types(`setChangeRequestMeta()`, `partialMeta`, `object`)(partialMeta); dispatch(new ChangeRequest().setChangeRequestMeta(partialMeta)); - }, - - ping: () => { - dispatch(ActionCreators.ping()); } }); diff --git a/packages/react-dataparcels/src/ParcelBoundary.jsx b/packages/react-dataparcels/src/ParcelBoundary.jsx index 173140d2..98b1a4d9 100644 --- a/packages/react-dataparcels/src/ParcelBoundary.jsx +++ b/packages/react-dataparcels/src/ParcelBoundary.jsx @@ -212,13 +212,11 @@ export default class ParcelBoundary extends React.Component { /* e newParcel.toConsole(); } - let shouldBeSynchronous = () => changeRequest.shouldBeSynchronous(); - let updateParcel = set('parcel', newParcel); let addToBuffer = this.addToBuffer(changeRequest); let releaseBuffer = this.releaseBuffer(); - if((!debounce && !hold) || shouldBeSynchronous()) { + if(!debounce && !hold) { this.setState(pipe( updateParcel, addToBuffer, diff --git a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js index d91b516f..d468505a 100644 --- a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js @@ -282,29 +282,6 @@ test('ParcelBoundary should cancel unreleased changes when receiving a new parce expect(handleChange).toHaveBeenCalledTimes(0); }); -test('ParcelBoundary should ignore debounce when sending a ping', () => { - let childRenderer = jest.fn(); - let handleChange = jest.fn(); - - let parcel = new Parcel({ - value: 123, - handleChange - }); - - let wrapper = shallow( - {childRenderer} - ); - - let childParcel = childRenderer.mock.calls[0][0]; - childParcel.ping(); - - // even with debounce applied, handleChange should have been called immediately - expect(handleChange).toHaveBeenCalledTimes(1); - - // handleChange should have the same value as before - expect(handleChange.mock.calls[0][0].value).toBe(123); -}); - test('ParcelBoundary should use an internal boundary split to stop parcel boundaries using the same parcel from sharing their parcel registries', () => { let parcel = new Parcel({ value: { From b900d06a09a160b8670b3ce648f3596edd74e2d8 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 6 Dec 2018 10:29:25 +1100 Subject: [PATCH 031/120] docs: turn parcelboundary render into pure example without debugRender option --- .../src/content/ExamplesParcelBoundary.md | 2 +- .../src/docs/api/parcelBoundary/parcel.md | 2 +- .../src/examples/ParcelBoundaryExample.jsx | 43 ---------- .../src/examples/ParcelBoundaryPure.jsx | 67 ++++++++++++++++ .../pages/examples/parcelboundary-example.md | 53 ------------ ...dary-example.js => parcelboundary-pure.js} | 4 +- .../src/pages/examples/parcelboundary-pure.md | 80 +++++++++++++++++++ 7 files changed, 151 insertions(+), 100 deletions(-) delete mode 100644 packages/dataparcels-docs/src/examples/ParcelBoundaryExample.jsx create mode 100644 packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx delete mode 100644 packages/dataparcels-docs/src/pages/examples/parcelboundary-example.md rename packages/dataparcels-docs/src/pages/examples/{parcelboundary-example.js => parcelboundary-pure.js} (53%) create mode 100644 packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md diff --git a/packages/dataparcels-docs/src/content/ExamplesParcelBoundary.md b/packages/dataparcels-docs/src/content/ExamplesParcelBoundary.md index fc99ccf9..4751a623 100644 --- a/packages/dataparcels-docs/src/content/ExamplesParcelBoundary.md +++ b/packages/dataparcels-docs/src/content/ExamplesParcelBoundary.md @@ -1,6 +1,6 @@ import Link from 'gatsby-link'; -* ParcelBoundary example +* ParcelBoundary pure rendering example * Using debounce * Using forceUpdate * Using hold diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundary/parcel.md b/packages/dataparcels-docs/src/docs/api/parcelBoundary/parcel.md index 9080e12c..b7b516af 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundary/parcel.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundary/parcel.md @@ -18,4 +18,4 @@ The `parcel` can be accessed from inside the ParcelBoundary via the first argume ``` -Example +Example diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryExample.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryExample.jsx deleted file mode 100644 index cb231bcd..00000000 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryExample.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; -import ExampleHoc from 'component/ExampleHoc'; - -const PersonParcelHoc = ParcelHoc({ - name: "personParcel", - valueFromProps: (/* props */) => ({ - name: { - first: "Robert", - last: "Clamps" - }, - age: "33" - }), - debugRender: true -}); - -const PersonEditor = (props) => { - let {personParcel} = props; - return
- - - {(name) =>
- - - {(first) => } - - - - - {(last) => } - -
- } -
- - - - {(age) => } - -
; -}; - -export default PersonParcelHoc(ExampleHoc(PersonEditor)); diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx new file mode 100644 index 00000000..2303954b --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + name: { + first: "Robert", + last: "Clamps" + }, + age: "33", + height: "160" + }) +}); + +const DebugRender = ({children}) => { + // each render, have a new, random background colour + let rand = () => Math.floor((Math.random() * 0.75 + 0.25) * 256); + let style = { + backgroundColor: `rgb(${rand()},${rand()},${rand()})`, + padding: "1rem", + marginBottom: "1rem" + }; + return
{children}
; +}; + +const PersonEditor = (props) => { + let {personParcel} = props; + return
+ + + {(name) => + + + {(first) => + + } + + + + + {(last) => + + } + + + } + + + + + {(age) => + + } + + + + + {(height) => + + } + +
; +}; + +export default PersonParcelHoc(ExampleHoc(PersonEditor)); diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-example.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-example.md deleted file mode 100644 index 57617d23..00000000 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-example.md +++ /dev/null @@ -1,53 +0,0 @@ -import Link from 'gatsby-link'; -import ParcelBoundaryExample from 'examples/ParcelBoundaryExample'; - -This example demonstrates nested ParcelBoundaries and their pure rendering feature. ParcelBoundaries appear as coloured boxes. As you type in an input, the colours will change to indicate which ParcelBoundaries have re-rendered. - -API reference for ParcelBoundary - - - -```js -import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; - -const PersonParcelHoc = ParcelHoc({ - name: "personParcel", - valueFromProps: (/* props */) => ({ - name: { - first: "Robert", - last: "Clamps" - }, - age: "33" - }), - debugRender: true -}); - -const PersonEditor = (props) => { - let {personParcel} = props; - return
- - - {(name) =>
- - - {(first) => } - - - - - {(last) => } - -
- } -
- - - - {(age) => } - -
; -}; - -export default PersonParcelHoc(PersonEditor); -``` diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-example.js b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.js similarity index 53% rename from packages/dataparcels-docs/src/pages/examples/parcelboundary-example.js rename to packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.js index c76b6c56..58bf7ed2 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-example.js +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.js @@ -1,9 +1,9 @@ // @flow import React from 'react'; -import Markdown from 'pages/examples/parcelboundary-example.md'; +import Markdown from 'pages/examples/parcelboundary-pure.md'; import Example from 'component/Example'; export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md new file mode 100644 index 00000000..74211f7f --- /dev/null +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md @@ -0,0 +1,80 @@ +import Link from 'gatsby-link'; +import ParcelBoundaryPure from 'examples/ParcelBoundaryPure'; + +This example demonstrates nested ParcelBoundaries and their pure rendering feature. In this example, ParcelBoundaries render as coloured boxes. As you type in an input, the colours will change to indicate which ParcelBoundaries have re-rendered. + +Note how the `height` field has a prop of `pure={false}`, and therefore updates every time there is a change. + +API reference for ParcelBoundary + + + +```js +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + name: { + first: "Robert", + last: "Clamps" + }, + age: "33", + height: "160" + }) +}); + +const DebugRender = ({children}) => { + // each render, have a new, random background colour + let rand = () => Math.floor((Math.random() * 0.75 + 0.25) * 256); + let style = { + backgroundColor: `rgb(${rand()},${rand()},${rand()})`, + padding: "1rem", + marginBottom: "1rem" + }; + return
{children}
; +}; + +const PersonEditor = (props) => { + let {personParcel} = props; + return
+ + + {(name) => + + + {(first) => + + } + + + + + {(last) => + + } + + + } + + + + + {(age) => + + } + + + + + {(height) => + + } + +
; +}; + +export default PersonParcelHoc(PersonEditor); + +``` From 9255e46e19d6a393861a2637e47ff5fca36fd2b0 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 6 Dec 2018 10:43:19 +1100 Subject: [PATCH 032/120] BREAK: remove debugRender --- .../src/docs/api/parcel/Parcel.md | 6 +----- .../src/docs/api/parcelHoc/ParcelHoc.md | 1 - .../src/docs/api/parcelHoc/debugRender.md | 7 ------- .../src/pages/api/ParcelHoc.jsx | 3 --- packages/dataparcels/src/parcel/Parcel.js | 6 ++---- .../src/parcel/__test__/Parcel-test.js | 5 ----- .../dataparcels/src/treeshare/Treeshare.js | 13 ++++--------- packages/dataparcels/src/types/Types.js | 3 +-- .../react-dataparcels/src/ParcelBoundary.jsx | 18 ++---------------- packages/react-dataparcels/src/ParcelHoc.jsx | 10 +++------- .../src/__test__/ParcelBoundary-test.js | 17 ----------------- .../src/__test__/ParcelHoc-test.js | 13 ------------- 12 files changed, 13 insertions(+), 89 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcelHoc/debugRender.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md b/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md index 6059ab2c..501a88e3 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md @@ -20,9 +20,7 @@ import Parcel from 'react-dataparcels'; ```flow new Parcel({ value?: any, - handleChange?: Function, - // debugging options - debugRender?: boolean + handleChange?: Function }); ``` @@ -32,8 +30,6 @@ new Parcel({ The `handleChange` function will be called whenever the Parcel's value has been triggered to change. It is passed `newParcel`, a replacement Parcel containing the changes; and `changeRequest`, a ChangeRequest that contains details about the change itself. In `handleChange` you would typically implement logic to replace your current parcel with `newParcel`, but if you're using React you should read getting started to save you the trouble of implementing this yourself. -* - For debugging purposes. When set to `true` this causes all downstream ParcelBoundarys to display when they are being rendered and re-rendered. ```js // creates a Parcel that contains a value of 123 diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md index 28229343..28f4cfa7 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md @@ -28,7 +28,6 @@ ParcelHoc({ pipe?: Function // debugging options debugParcel?: boolean - debugRender?: boolean }); ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/debugRender.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/debugRender.md deleted file mode 100644 index 5db58cc1..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/debugRender.md +++ /dev/null @@ -1,7 +0,0 @@ -import Link from 'component/Link'; - -```flow -debugRender?: boolean = false // optional -``` - -For debugging purposes. When set to `true` this causes all downstream ParcelBoundarys to display when they are being rendered and re-rendered. diff --git a/packages/dataparcels-docs/src/pages/api/ParcelHoc.jsx b/packages/dataparcels-docs/src/pages/api/ParcelHoc.jsx index 615f6c39..51b8d297 100644 --- a/packages/dataparcels-docs/src/pages/api/ParcelHoc.jsx +++ b/packages/dataparcels-docs/src/pages/api/ParcelHoc.jsx @@ -11,7 +11,6 @@ import Markdown_onChange from 'docs/api/parcelHoc/onChange.md'; import Markdown_delayUntil from 'docs/api/parcelHoc/delayUntil.md'; import Markdown_pipe from 'docs/api/parcelHoc/pipe.md'; import Markdown_debugParcel from 'docs/api/parcelHoc/debugParcel.md'; -import Markdown_debugRender from 'docs/api/parcelHoc/debugRender.md'; import Markdown_childName from 'docs/api/parcelHoc/childName.md'; const md = { @@ -24,7 +23,6 @@ const md = { delayUntil: Markdown_delayUntil, pipe: Markdown_pipe, debugParcel: Markdown_debugParcel, - debugRender: Markdown_debugRender, ['${name}']: Markdown_childName } @@ -37,7 +35,6 @@ onChange delayUntil pipe debugParcel -debugRender # Child props $\{name\} diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 3df9bfc0..c8d27a0f 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -51,12 +51,10 @@ export default class Parcel { let { handleChange, - value, - debugRender = false + value } = config; handleChange && Types(`Parcel()`, `config.handleChange`, `function`)(handleChange); - Types(`Parcel()`, `config.debugRender`, `boolean`)(debugRender); let { onDispatch, @@ -94,7 +92,7 @@ export default class Parcel { this._id = id; // treeshare - this._treeshare = treeshare || new Treeshare({debugRender}); + this._treeshare = treeshare || new Treeshare(); this._treeshare.registry.set(id.id(), this); let dispatch = (dispatchable: Action|Action[]|ChangeRequest) => this._methods.dispatch(dispatchable); diff --git a/packages/dataparcels/src/parcel/__test__/Parcel-test.js b/packages/dataparcels/src/parcel/__test__/Parcel-test.js index cf83e7a3..67e14c04 100644 --- a/packages/dataparcels/src/parcel/__test__/Parcel-test.js +++ b/packages/dataparcels/src/parcel/__test__/Parcel-test.js @@ -24,8 +24,3 @@ test('Parcels should be able to accept just handleChange in config', () => { expect(undefined).toEqual(parcel.value); parcel.onChange(456); }); - -test('Parcel should store debugRender in treeshare', () => { - expect(new Parcel()._treeshare.debugRender).toBe(false); - expect(new Parcel({debugRender: true})._treeshare.debugRender).toBe(true); -}); diff --git a/packages/dataparcels/src/treeshare/Treeshare.js b/packages/dataparcels/src/treeshare/Treeshare.js index 28426511..943baa2f 100644 --- a/packages/dataparcels/src/treeshare/Treeshare.js +++ b/packages/dataparcels/src/treeshare/Treeshare.js @@ -42,36 +42,31 @@ class LocationShareRegistry { type Config = { registry?: ParcelRegistry, dispatch?: DispatchRegistry, - locationShare?: LocationShareRegistry, - debugRender: boolean + locationShare?: LocationShareRegistry }; export default class Treeshare { - debugRender: boolean; registry: ParcelRegistry; dispatch: DispatchRegistry; locationShare: LocationShareRegistry; - constructor(config: Config) { + constructor(config: Config = {}) { let { registry, dispatch, - locationShare, - debugRender + locationShare } = config; this.registry = registry || new ParcelRegistry(); this.dispatch = dispatch || new DispatchRegistry(); this.locationShare = locationShare || new LocationShareRegistry(); - this.debugRender = debugRender || false; } boundarySplit: Function = (): Treeshare => { return new Treeshare({ // do not pass in registry dispatch: this.dispatch, - locationShare: this.locationShare, - debugRender: this.debugRender + locationShare: this.locationShare }); } } diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index bc6a3910..1ced63b5 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -18,8 +18,7 @@ export type ParcelDataEvaluator = (parcelData: ParcelData) => ParcelData; export type ParcelConfig = { handleChange?: Function, - value?: *, - debugRender?: boolean + value?: * }; export type ParcelConfigInternal = { diff --git a/packages/react-dataparcels/src/ParcelBoundary.jsx b/packages/react-dataparcels/src/ParcelBoundary.jsx index 98b1a4d9..4b2ac8a3 100644 --- a/packages/react-dataparcels/src/ParcelBoundary.jsx +++ b/packages/react-dataparcels/src/ParcelBoundary.jsx @@ -113,15 +113,6 @@ export default class ParcelBoundary extends React.Component { /* e return null; } - debugRenderStyle: Function = (): Object => { - let rand = () => Math.floor((Math.random() * 0.75 + 0.25) * 256); - return { - backgroundColor: `rgb(${rand()},${rand()},${rand()})`, - padding: "1rem", - marginBottom: "1rem" - }; - }; - addToBuffer: Function = (changeRequest: ChangeRequest) => (state: State): State => { let {debugBuffer} = this.props; let { @@ -260,13 +251,8 @@ export default class ParcelBoundary extends React.Component { /* e cancel: () => this.setState(this.cancelBuffer()), release: () => this.setState(this.releaseBuffer()) }; - let buffered = changeCount > 0; - - let element = children(parcel, actions, buffered); - if(parcel._treeshare.debugRender) { - return
{element}
; - } - return element; + let buffered = changeCount > 0; + return children(parcel, actions, buffered); } } diff --git a/packages/react-dataparcels/src/ParcelHoc.jsx b/packages/react-dataparcels/src/ParcelHoc.jsx index e4f2a866..efe4c8a2 100644 --- a/packages/react-dataparcels/src/ParcelHoc.jsx +++ b/packages/react-dataparcels/src/ParcelHoc.jsx @@ -34,8 +34,7 @@ type ParcelHocConfig = { onChange?: (props: AnyProps) => OnChange, delayUntil?: (props: AnyProps) => boolean, pipe?: (props: *) => (parcel: Parcel) => Parcel, - debugParcel?: boolean, - debugRender?: boolean + debugParcel?: boolean }; const PARCEL_HOC_NAME = `ParcelHoc()`; @@ -51,8 +50,7 @@ export default (config: ParcelHocConfig): Function => { delayUntil = (props) => true, /* eslint-disable-line no-unused-vars */ pipe = props => ii => ii, /* eslint-disable-line no-unused-vars */ // debug options - debugParcel = false, - debugRender = false + debugParcel = false } = config; Types(PARCEL_HOC_NAME, "config.name", "string")(name); @@ -63,7 +61,6 @@ export default (config: ParcelHocConfig): Function => { Types(PARCEL_HOC_NAME, "config.delayUntil", "function")(delayUntil); Types(PARCEL_HOC_NAME, "config.pipe", "function")(pipe); Types(PARCEL_HOC_NAME, "config.debugParcel", "boolean")(debugParcel); - Types(PARCEL_HOC_NAME, "config.debugRender", "boolean")(debugRender); return (Component: ComponentType) => class ParcelHoc extends React.Component { constructor(props: Props) { @@ -71,8 +68,7 @@ export default (config: ParcelHocConfig): Function => { let initialize = (value: *) => new Parcel({ value, - handleChange: this.handleChange, - debugRender + handleChange: this.handleChange }); this.state = { diff --git a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js index d468505a..44e71076 100644 --- a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js @@ -315,20 +315,3 @@ test('ParcelBoundary should use an internal boundary split to stop parcel bounda expect(childParcelA2.value).toEqual({abc: 456, def: 123}); expect(childParcelB2.value).toEqual({abc: 123, def: 456}); }); - -test('ParcelBoundary should render colours when debugRender is true', () => { - let hasChanged = false; - let parcel = new Parcel({ - value: 123, - debugRender: true - }); - - expect( - shallow({(pp) => "???"}) - .render() - .get(0) - .attribs - .style - .indexOf('background-color') !== -1 - ).toBe(true); -}); diff --git a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js index 5b317d24..ffe93313 100644 --- a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js @@ -107,19 +107,6 @@ test('ParcelHoc config should accept a pipe function', () => { expect(457).toBe(childProps.proppy.value); }); -test('ParcelHoc config should accept a debugRender boolean', () => { - let childProps = shallowRenderHoc( - {}, - ParcelHoc({ - valueFromProps: () => 456, - name: "proppy", - debugRender: true - }) - ).props(); - - expect(childProps.proppy._treeshare.debugRender).toBe(true); -}); - test('ParcelHoc config should accept a debugParcel boolean', () => { let {log} = console; // $FlowFixMe From 284c13d16ae5484580d259208c59f97ad1214c8e Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Fri, 11 Jan 2019 14:25:41 +1100 Subject: [PATCH 033/120] docs: remove unused gh-pages --- packages/dataparcels-docs/gatsby-node.js | 63 ------------------------ packages/dataparcels-docs/package.json | 2 - 2 files changed, 65 deletions(-) diff --git a/packages/dataparcels-docs/gatsby-node.js b/packages/dataparcels-docs/gatsby-node.js index 9a6fa9f7..e8e64120 100644 --- a/packages/dataparcels-docs/gatsby-node.js +++ b/packages/dataparcels-docs/gatsby-node.js @@ -1,68 +1,5 @@ const {createFilePath} = require('gatsby-source-filesystem'); const path = require('path'); -const fs = require('fs'); - -exports.createPages = ({graphql, boundActionCreators}) => { - const {createPage} = boundActionCreators; - - // function createExamples() { - // return graphql(` - // { - // allFile(filter: {sourceInstanceName: {eq: "example-pages"}}, sort: {fields: relativePath, order: ASC}) { - // edges { - // next { - // name - // relativePath - // } - // node { - // name - // relativePath - // } - // previous { - // name - // relativePath - // } - // } - // } - // } - // `) - // .then(result => { - // if (result.errors) { - // return Promise.reject(result.errors); - // } - - // let getPath = (node) => `/examples/${node.name.split("-")[1]}`; - // result.data.allFile.edges.forEach(({next, node, previous}, index) => { - // let component = path.resolve(`src/examples/${node.relativePath}`); - - // createPage({ - // path: getPath(node), - // component, - // context: { - // next: next ? getPath(next) : null, - // previous: previous ? getPath(previous) : null, - // file: node.relativePath - // } - // }); - // }); - // }); - // } - - return Promise.resolve() - //.then(createExamples) - ; -}; - -const circleYml = ` -general: - branches: - ignore: - - gh-pages -`; - -exports.onPostBuild = () => { - fs.writeFileSync(`${__dirname}/public/circle.yml`, circleYml); -} exports.modifyWebpackConfig = ({ config, stage }) => { diff --git a/packages/dataparcels-docs/package.json b/packages/dataparcels-docs/package.json index 36bf998a..aba2a175 100644 --- a/packages/dataparcels-docs/package.json +++ b/packages/dataparcels-docs/package.json @@ -8,7 +8,6 @@ "scripts": { "build-all": "yarn build-docs", "build-docs": "gatsby build", - "deploy": "gatsby build --prefix-paths && gh-pages -d public", "watch": "gatsby develop", "test": "echo \"Error: no test specified\" && exit 1" }, @@ -24,7 +23,6 @@ "gatsby-remark-prismjs": "^1.2.21", "gatsby-source-filesystem": "^1.5.26", "gatsby-transformer-remark": "^1.7.34", - "gh-pages": "^1.1.0", "immutable": "^3.8.2", "mdx-loader": "1.0.0-beta.3", "mdxc": "^1.1.1", From ce88393e69189476323c4e0a6395b23cee4d6a81 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Fri, 11 Jan 2019 14:26:50 +1100 Subject: [PATCH 034/120] add: setData action --- packages/dataparcels/src/change/ActionCreators.js | 9 +++++++++ packages/dataparcels/src/change/ChangeRequestReducer.js | 1 + 2 files changed, 10 insertions(+) diff --git a/packages/dataparcels/src/change/ActionCreators.js b/packages/dataparcels/src/change/ActionCreators.js index 47fa52a5..0aada7ab 100644 --- a/packages/dataparcels/src/change/ActionCreators.js +++ b/packages/dataparcels/src/change/ActionCreators.js @@ -1,6 +1,7 @@ // @flow import type {Key} from '../types/Types'; import type {Index} from '../types/Types'; +import type {ParcelData} from '../types/Types'; import Action from './Action'; @@ -63,6 +64,13 @@ const pop: Function = (): Action => { }); }; +const setData: Function = (parcelData: ParcelData): Action => { + return new Action({ + type: "setData", + payload: parcelData + }); +}; + const setMeta: Function = (meta: *): Action => { return new Action({ type: "setMeta", @@ -149,6 +157,7 @@ export default { insertBeforeSelf, push, pop, + setData, setMeta, setSelf, shift, diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index d9c4c8c9..0c22f0ec 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -33,6 +33,7 @@ const actionMap = { insertBefore: ({lastKey, value}) => insertBefore(lastKey, value), pop: () => pop(), push: ({value}) => push(value), + setData: parcelData => () => parcelData, setMeta: ({meta}) => setMeta(meta), set: ({value}) => setSelf(value), shift: () => shift(), From 2f9061d1b9b240689a63cc58607700f903d99db4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Fri, 11 Jan 2019 14:28:37 +1100 Subject: [PATCH 035/120] BREAK: redo parcel.modify methods and update methods --- .../src/docs/api/parcel/modifyDown.md | 3 + .../src/docs/api/parcel/modifyUp.md | 4 + .../src/docs/api/parcel/modifyValueDown.md | 3 - .../src/docs/api/parcel/modifyValueUp.md | 4 - .../src/docs/api/parcel/updateDeep.md | 4 + .../src/docs/api/parcel/updateInDeep.md | 3 + .../dataparcels-docs/src/pages/api/Parcel.jsx | 22 ++- packages/dataparcels/src/errors/Errors.js | 4 +- packages/dataparcels/src/parcel/Parcel.js | 10 +- .../src/parcel/__test__/ModifyMethods-test.js | 148 ++++++++++++++---- .../__test__/ParcelChangeMethods-test.js | 47 +++--- .../src/parcel/__test__/ParcelGetters-test.js | 4 +- .../src/parcel/__test__/ParcelTypes-test.js | 2 +- .../__test__/ParentChangeMethods-test.js | 59 +++++-- .../src/parcel/methods/ModifyMethods.js | 60 +++---- .../src/parcel/methods/ParcelChangeMethods.js | 11 +- .../src/parcel/methods/ParentChangeMethods.js | 16 +- 17 files changed, 282 insertions(+), 122 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md new file mode 100644 index 00000000..28dbb598 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md @@ -0,0 +1,3 @@ +```flow +modifyDown(updater: Function): Parcel +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md new file mode 100644 index 00000000..c4a128b5 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md @@ -0,0 +1,4 @@ +```flow +modifyUp(updater: Function): Parcel +``` + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md deleted file mode 100644 index 7a7d7cfd..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueDown.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyValueDown(updater: Function): void -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md deleted file mode 100644 index 40870bc9..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyValueUp.md +++ /dev/null @@ -1,4 +0,0 @@ -```flow -modifyValueUp(updater: Function): void -``` - diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md b/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md new file mode 100644 index 00000000..d5e06ae4 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md @@ -0,0 +1,4 @@ +```flow +updateDeep(updater: Function): void +updateDeep(key: string|number, updater: Function): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md b/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md new file mode 100644 index 00000000..b7a986df --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md @@ -0,0 +1,3 @@ +```flow +updateInDeep(keyPath: Array, updater: Function): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 2ab6c694..791569d7 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -25,7 +25,9 @@ import Markdown_onChangeDOM from 'docs/api/parcel/onChangeDOM.md'; import Markdown_set from 'docs/api/parcel/set.md'; import Markdown_setIn from 'docs/api/parcel/setIn.md'; import Markdown_update from 'docs/api/parcel/update.md'; +import Markdown_updateDeep from 'docs/api/parcel/updateDeep.md'; import Markdown_updateIn from 'docs/api/parcel/updateIn.md'; +import Markdown_updateInDeep from 'docs/api/parcel/updateInDeep.md'; import Markdown_delete from 'docs/api/parcel/delete.md'; import Markdown_deleteIn from 'docs/api/parcel/deleteIn.md'; import Markdown_insertAfter from 'docs/api/parcel/insertAfter.md'; @@ -42,8 +44,8 @@ import Markdown_setChangeRequestMeta from 'docs/api/parcel/setChangeRequestMeta. import Markdown_dispatch from 'docs/api/parcel/dispatch.md'; import Markdown_batch from 'docs/api/parcel/batch.md'; import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; -import Markdown_modifyValueDown from 'docs/api/parcel/modifyValueDown.md'; -import Markdown_modifyValueUp from 'docs/api/parcel/modifyValueUp.md'; +import Markdown_modifyDown from 'docs/api/parcel/modifyDown.md'; +import Markdown_modifyUp from 'docs/api/parcel/modifyUp.md'; import Markdown_modifyChange from 'docs/api/parcel/modifyChange.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; import Markdown_isChild from 'docs/api/parcel/isChild.md'; @@ -82,7 +84,9 @@ const md = { set: Markdown_set, setIn: Markdown_setIn, update: Markdown_update, + updateDeep: Markdown_updateDeep, updateIn: Markdown_updateIn, + updateInDeep: Markdown_updateInDeep, delete: Markdown_delete, deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, @@ -99,8 +103,8 @@ const md = { dispatch: Markdown_dispatch, batch: Markdown_batch, batchAndReturn: Markdown_batchAndReturn, - modifyValueDown: Markdown_modifyValueDown, - modifyValueUp: Markdown_modifyValueUp, + modifyDown: Markdown_modifyDown, + modifyUp: Markdown_modifyUp, modifyChange: Markdown_modifyChange, initialMeta: Markdown_initialMeta, isChild: Markdown_isChild, @@ -148,10 +152,12 @@ onChange() onChangeDOM() set() setIn() -update() -updateIn() delete() deleteIn() +update() +updateDeep() +updateIn() +updateInDeep() # Indexed & element change methods insertAfter() @@ -172,8 +178,8 @@ batch() batchAndReturn() # Modify methods -modifyValueDown() -modifyValueUp() +modifyDown() +modifyUp() modifyChange() initialMeta() diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index bdcd22a9..2c5ce366 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -3,6 +3,6 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); -export const ModifyValueDownChildReturnError = () => new Error(`.modifyValueDown()'s updater can not return a value that has children unless it is unchanged by the updater or is empty.`); -export const ModifyValueUpChildReturnError = () => new Error(`When .modifyValueUp()'s updater is passed a value that has children, it cannot return a value that has children unless it is unchanged by the updater`); +export const ModifyValueDownChildReturnError = () => new Error(`.modifyDown()'s updater can not return a value that has children unless it is unchanged by the updater or is empty.`); +export const ModifyValueUpChildReturnError = () => new Error(`When .modifyUp()'s updater is passed a value that has children, it cannot return a value that has children unless it is unchanged by the updater`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index c8d27a0f..2dc93878 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -12,6 +12,7 @@ import type {ParcelMapper} from '../types/Types'; import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; +import type {StaticParcelUpdater} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -283,8 +284,13 @@ export default class Parcel { ["1"]: (updater: ParcelValueUpdater) => this._methods.updateSelf(updater), ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); + updateDeep = overload({ + ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfDeep(updater), + ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateDeep(key, updater) + }); setIn = (keyPath: Array, value: *) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); + updateInDeep = (keyPath: Array, updater: StaticParcelUpdater) => this._methods.updateInDeep(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) @@ -327,8 +333,8 @@ export default class Parcel { // Modify methods modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); modifyUp = (updater: Function): Parcel => this._methods.modifyUp(updater); - modifyValueDown = (updater: Function): Parcel => this._methods.modifyValueDown(updater); - modifyValueUp = (updater: Function): Parcel => this._methods.modifyValueUp(updater); + modifyDownDeep = (updater: Function): Parcel => this._methods.modifyDownDeep(updater); + modifyUpDeep = (updater: Function): Parcel => this._methods.modifyUpDeep(updater); modifyChange = (batcher: ParcelBatcher): Parcel => this._methods.modifyChange(batcher); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index bf8de79f..a87db498 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -1,15 +1,17 @@ // @flow -import Parcel from '../Parcel'; import type ChangeRequest from '../../change/ChangeRequest'; -test('Parcel.modifyValueDown() should return a new parcel with updated parcelData', () => { +import Parcel from '../Parcel'; +import StaticParcel from '../../staticParcel/StaticParcel'; + +test('Parcel.modifyDown() should return a new parcel with updated parcelData', () => { expect.assertions(2); var data = { value: [123] }; var parcel = new Parcel(data).get(0); var updated = parcel - .modifyValueDown((value: *, parcelData: Parcel) => { + .modifyDown((value: *, parcelData: Parcel) => { expect(parcelData).toBe(parcel); return value + 1; }) @@ -24,72 +26,72 @@ test('Parcel.modifyValueDown() should return a new parcel with updated parcelDat expect(expectedData).toEqual(updated); }); -test('Parcel.modifyValueDown() should allow non-parent types to be returned', () => { +test('Parcel.modifyDown() should allow non-parent types to be returned', () => { let updatedValue = new Parcel({ value: 123 }) - .modifyValueDown(value => value + 1) + .modifyDown(value => value + 1) .value; expect(updatedValue).toEqual(124); }); -test('Parcel.modifyValueDown() should allow childless parent types to be returned', () => { +test('Parcel.modifyDown() should allow childless parent types to be returned', () => { let updatedValue = new Parcel({ value: 123 }) - .modifyValueDown(value => []) + .modifyDown(value => []) .value; expect(updatedValue).toEqual([]); }); -test('Parcel.modifyValueDown() should allow parent types to be returned if they dont change', () => { +test('Parcel.modifyDown() should allow parent types to be returned if they dont change', () => { let updatedValue = new Parcel({ value: [123] }) - .modifyValueDown(value => value) + .modifyDown(value => value) .value; expect(updatedValue).toEqual([123]); }); -test('Parcel.modifyValueDown() should throw error if changed parent types with children are returned', () => { +test('Parcel.modifyDown() should throw error if changed parent types with children are returned', () => { expect(() => { new Parcel({ value: [123] - }).modifyValueDown(value => [...value, 456]); + }).modifyDown(value => [...value, 456]); - }).toThrowError(`modifyValueDown()`); + }).toThrowError(`modifyDown()`); }); -test('Parcel.modifyValueDown() should throw error if childless is turned into parent types with children', () => { +test('Parcel.modifyDown() should throw error if childless is turned into parent types with children', () => { expect(() => { new Parcel({ value: 123 - }).modifyValueDown(value => [123, 456]); + }).modifyDown(value => [123, 456]); - }).toThrowError(`modifyValueDown()`); + }).toThrowError(`modifyDown()`); }); -test('Parcel.modifyValueDown() should recognise if value changes types, and set value if type changes', () => { +test('Parcel.modifyDown() should recognise if value changes types, and set value if type changes', () => { let handleChange = jest.fn(); let parcel = new Parcel({ value: 123, handleChange }) - .modifyValueDown(value => []) + .modifyDown(value => []) .push(123); expect(handleChange).toHaveBeenCalledTimes(1); expect(handleChange.mock.calls[0][0].value).toEqual([123]); }); -test('Parcel.modifyValueDown() should have id which is unique to updater', () => { +test('Parcel.modifyDown() should have id which is unique to updater', () => { let updater = value => []; - let parcel = new Parcel().modifyValueDown(updater); - let parcel2 = new Parcel().modifyValueDown(updater); - let parcel3 = new Parcel().modifyValueDown(a => 1 + 2); + let parcel = new Parcel().modifyDown(updater); + let parcel2 = new Parcel().modifyDown(updater); + let parcel3 = new Parcel().modifyDown(a => 1 + 2); expect(parcel.id).toBe("^.~mv-643198612"); expect(parcel2.id).toBe("^.~mv-643198612"); // same updater should produce the same hash @@ -142,57 +144,57 @@ test('Parcel.modifyChange() should have id which is unique to updater', () => { expect(parcel3.id).not.toBe("^.~mcb-643198612"); // different updater should produce different hash }); -test('Parcel.modifyValueUp() should allow you to change the payload of a changed parcel with an updater (and should allow non-parent types to be returned)', () => { +test('Parcel.modifyUp() should allow you to change the payload of a changed parcel with an updater (and should allow non-parent types to be returned)', () => { var handleChange = jest.fn(); new Parcel({ value: 123, handleChange }) - .modifyValueUp(value => value + 1) + .modifyUp(value => value + 1) .onChange(456); expect(handleChange.mock.calls[0][0].value).toBe(457); }); -test('Parcel.modifyValueUp() should allow parent types to be returned', () => { +test('Parcel.modifyUp() should allow parent types to be returned', () => { var handleChange = jest.fn(); new Parcel({ value: 123, handleChange }) - .modifyValueUp(value => [123,456]) + .modifyUp(value => [123,456]) .onChange(456); expect(handleChange.mock.calls[0][0].value).toEqual([123,456]); }); -test('Parcel.modifyValueUp() should allow parent types to be returned if they dont change', () => { +test('Parcel.modifyUp() should allow parent types to be returned if they dont change', () => { var handleChange = jest.fn(); new Parcel({ value: [123], handleChange }) - .modifyValueUp(value => value) + .modifyUp(value => value) .onChange([456]); expect(handleChange.mock.calls[0][0].value).toEqual([456]); }); -test('Parcel.modifyValueUp() should throw error if changed parent types with children are returned', () => { +test('Parcel.modifyUp() should throw error if changed parent types with children are returned', () => { expect(() => { var handleChange = jest.fn(); new Parcel({ value: [123], handleChange }) - .modifyValueUp(value => [...value, 456]) + .modifyUp(value => [...value, 456]) .onChange([456]); - }).toThrowError(`modifyValueUp()`); + }).toThrowError(`modifyUp()`); }); -test('Parcel.modifyValueUp() should allow changes to meta through', () => { +test('Parcel.modifyUp() should allow changes to meta through', () => { expect.assertions(2); var data = { @@ -205,7 +207,7 @@ test('Parcel.modifyValueUp() should allow changes to meta through', () => { }; new Parcel(data) - .modifyValueUp(value => value + 1) + .modifyUp(value => value + 1) .batch(parcel => { parcel.onChange(456); parcel.setMeta({ @@ -214,6 +216,88 @@ test('Parcel.modifyValueUp() should allow changes to meta through', () => { }); }); +test('Parcel.modifyDownDeep() should be called with static parcel and return with no change', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(staticParcel => staticParcel); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let {value} = parcel + .modifyDownDeep(updater) + .data; + + let expectedValue = [1,2,3]; + + expect(value).toEqual(expectedValue); + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0].data.value).toEqual(expectedValue); +}); + +test('Parcel.modifyDownDeep() should modify value', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(staticParcel => staticParcel.push(4)); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyDownDeep(updater); + let {value} = parcelWithModifier.data; + parcelWithModifier.push(5); + + expect(value).toEqual([1,2,3,4]); + expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); +}); + +test('Parcel.modifyUpDeep() should be called with static parcel and return with no change', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(staticParcel => staticParcel); + + let parcel = new Parcel({ + handleChange, + value: 123 + }); + + let parcelWithModifier = parcel.modifyUpDeep(updater); + let {value} = parcelWithModifier.data; + + expect(value).toEqual(123); + expect(updater).not.toHaveBeenCalled(); + + parcelWithModifier.set(456); + + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0].data.value).toEqual(456); +}); + +test('Parcel.modifyUpDeep() should modify value', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(staticParcel => staticParcel.push(5)); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyUpDeep(updater); + let {value} = parcelWithModifier.data; + + expect(value).toEqual([1,2,3]); + expect(updater).not.toHaveBeenCalled(); + + parcelWithModifier.push(4); + + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); +}); test('Parcel.initialMeta() should work', () => { expect.assertions(3); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 6e04a545..f551fadc 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -1,6 +1,7 @@ // @flow import Parcel from '../Parcel'; import GetAction from '../../util/__test__/GetAction-testUtil'; +import StaticParcel from '../../staticParcel/StaticParcel'; test('Parcel.set() should call the Parcels handleChange function with the new parcelData', () => { expect.assertions(3); @@ -69,39 +70,31 @@ test('Parcel.set() should remove and replace child data when setting a deep data }); test('Parcel.update() should call the Parcels handleChange function with the new parcelData', () => { - expect.assertions(3); - var data = { - value: 123 - }; + let handleChange = jest.fn(); + let updater = jest.fn(ii => ii + 1); - var expectedArg = 123; + new Parcel({ + value: 123, + handleChange + }).update(updater); - var expectedData = { - child: undefined, - meta: {}, - value: 456, - key: '^' - }; + expect(updater.mock.calls[0][0]).toBe(123); + expect(handleChange.mock.calls[0][0].data.value).toBe(124); +}); - var expectedAction = { - type: "set", - keyPath: [], - payload: { - value: 456 - } - }; +test('Parcel.updateDeep() should call the Parcels handleChange function with the new parcelData', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(staticParcel => staticParcel.push(4)); new Parcel({ - ...data, - handleChange: (parcel, changeRequest) => { - expect(expectedData).toEqual(parcel.data); - expect(expectedAction).toEqual(GetAction(changeRequest)); - } - }).update((ii) => { - expect(expectedArg).toEqual(ii); - return 456; - }); + value: [1,2,3], + handleChange + }).updateDeep(updater); + + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); test('Parcel.onChange() should work like set that only accepts a single argument', () => { diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js index 4491949b..f40ca157 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js @@ -75,7 +75,7 @@ test('Parcel.id should return the Parcels id', () => { }; expect("^").toBe(new Parcel(data).id); expect("^.a").toBe(new Parcel(data).get("a").id); - expect("^.~mv-364997092.a").toBe(new Parcel(data).modifyValueDown(ii => ii).get("a").id); + expect("^.~mv-364997092.a").toBe(new Parcel(data).modifyDown(ii => ii).get("a").id); expect("^.a.#a").toBe(new Parcel(data).getIn(["a",0]).id); expect("^.something%.%:%@").toBe(new Parcel(data).get("something.:@").id); expect("^.b").toBe(new Parcel(data).get("b").id); @@ -91,7 +91,7 @@ test('Parcel.path should return the Parcels path', () => { }; expect([]).toEqual(new Parcel(data).path); expect(["a"]).toEqual(new Parcel(data).get("a").path); - expect(["a"]).toEqual(new Parcel(data).modifyValueDown(ii => ii).get("a").path); + expect(["a"]).toEqual(new Parcel(data).modifyDown(ii => ii).get("a").path); expect(["a","#a"]).toEqual(new Parcel(data).getIn(["a",0]).path); expect(["something.:@"]).toEqual(new Parcel(data).get("something.:@").path); expect(["b"]).toEqual(new Parcel(data).get("b").path); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js index f07605a5..411532d5 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelTypes-test.js @@ -131,7 +131,7 @@ test('ParcelTypes should correctly identify top level values after modifiers', ( var data = { value: [1,2,3] }; - expect(new Parcel(data).modifyValueDown(ii => ii).isTopLevel()).toBe(true); + expect(new Parcel(data).modifyDown(ii => ii).isTopLevel()).toBe(true); }); // method creators diff --git a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js index 890da415..e2df00e6 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js @@ -1,6 +1,7 @@ // @flow import Parcel from '../Parcel'; import map from 'unmutable/lib/map'; +import StaticParcel from '../../staticParcel/StaticParcel'; test('ParentParcel.set(key) should call the Parcels handleChange function with the new parcelData', () => { expect.assertions(1); @@ -19,21 +20,36 @@ test('ParentParcel.set(key) should call the Parcels handleChange function with t }); test('ParentParcel.update(key) should call the Parcels handleChange function with the new parcelData', () => { - expect.assertions(2); + let updater = jest.fn(ii => ii + 1); + let handleChange = jest.fn(); - var data = { + new Parcel({ value: { - a: "!!!" + abc: 123 }, - handleChange: (parcel) => { - let {value} = parcel.data; - expect({a: "???"}).toEqual(value); - } - }; + handleChange + }).update("abc", updater); - new Parcel(data).update("a", ii => { - expect("!!!").toBe(ii); - return "???"; + expect(updater.mock.calls[0][0]).toBe(123); + expect(handleChange.mock.calls[0][0].data.value).toEqual({ + abc: 124 + }); +}); + +test('ParentParcel.updateDeep(key) should call the Parcels handleChange function with the new parcelData', () => { + let updater = jest.fn(staticParcel => staticParcel.push(4)); + let handleChange = jest.fn(); + + new Parcel({ + value: { + abc: [1,2,3] + }, + handleChange + }).updateDeep("abc", updater); + + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(handleChange.mock.calls[0][0].data.value).toEqual({ + abc: [1,2,3,4] }); }); @@ -94,6 +110,27 @@ test('ParentParcel.updateIn(keyPath) should call the Parcels handleChange functi }); }); +test('ParentParcel.updateInDeep(keyPath) should call the Parcels handleChange function with the new parcelData', () => { + let updater = jest.fn(staticParcel => staticParcel.push(4)); + let handleChange = jest.fn(); + + new Parcel({ + value: { + abc: { + def: [1,2,3] + } + }, + handleChange + }).updateInDeep(["abc", "def"], updater); + + expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(handleChange.mock.calls[0][0].data.value).toEqual({ + abc: { + def: [1,2,3,4] + } + }); +}); + test('ParentParcel.deleteIn(keyPath) should delete deeply', () => { var data = { value: { diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index fbb27470..a317c6b4 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -2,7 +2,10 @@ import type ChangeRequest from '../../change/ChangeRequest'; import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; +import type {ParcelValueUpdater} from '../../types/Types'; + import Types from '../../types/Types'; +import StaticParcel from '../../staticParcel/StaticParcel'; import ParcelTypes from '../ParcelTypes'; import {ModifyValueDownChildReturnError} from '../../errors/Errors'; @@ -23,32 +26,8 @@ let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; export default (_this: Parcel): Object => ({ - modifyDown: (updater: Function): Parcel => { + modifyDown: (updater: ParcelValueUpdater): Parcel => { Types(`modifyDown()`, `updater`, `function`)(updater); - let parcelData = updater(_this._parcelData); - - return _this._create({ - id: _this._id.pushModifier(`md-${HashFunction(updater)}`), - parcelData, - onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPre(updater)); - } - }); - }, - - modifyUp: (updater: Function): Parcel => { - Types(`modifyUp()`, `updater`, `function`)(updater); - - return _this._create({ - id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), - onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPost(updater)); - } - }); - }, - - modifyValueDown: (updater: Function): Parcel => { - Types(`modifyValueDown()`, `updater`, `function`)(updater); let {value} = _this._parcelData; let updatedValue = updater(value, _this); @@ -84,8 +63,8 @@ export default (_this: Parcel): Object => ({ }); }, - modifyValueUp: (updater: Function): Parcel => { - Types(`modifyValueUp()`, `updater`, `function`)(updater); + modifyUp: (updater: ParcelValueUpdater): Parcel => { + Types(`modifyUp()`, `updater`, `function`)(updater); return _this.modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { let {value} = changeRequest.nextData; @@ -109,6 +88,33 @@ export default (_this: Parcel): Object => ({ }); }, + modifyDownDeep: (updater: Function): Parcel => { + Types(`modifyDownDeep()`, `updater`, `function`)(updater); + + let staticUpdater = StaticParcel._updateFromData(updater); + + return _this._create({ + id: _this._id.pushModifier(`md-${HashFunction(updater)}`), + parcelData: staticUpdater(_this._parcelData), + onDispatch: (changeRequest: ChangeRequest) => { + _this.dispatch(changeRequest._addPre(staticUpdater)); + } + }); + }, + + modifyUpDeep: (updater: Function): Parcel => { + Types(`modifyUpDeep()`, `updater`, `function`)(updater); + + let staticUpdater = StaticParcel._updateFromData(updater); + + return _this._create({ + id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), + onDispatch: (changeRequest: ChangeRequest) => { + _this.dispatch(changeRequest._addPost(staticUpdater)); + } + }); + }, + modifyChange: (batcher: Function): Parcel => { Types(`modifyChange()`, `batcher`, `function`)(batcher); return _this._create({ diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 12db7666..891e856b 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -2,10 +2,12 @@ import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; +import type {StaticParcelUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; import ActionCreators from '../../change/ActionCreators'; +import StaticParcel from '../../staticParcel/StaticParcel'; export default (_this: Parcel, dispatch: Function) => ({ @@ -18,10 +20,15 @@ export default (_this: Parcel, dispatch: Function) => ({ _this.set(updater(_this.value)); }, - onChange: (value: *) => { - _this.set(value); + updateSelfDeep: (updater: StaticParcelUpdater) => { + Types(`updateSelfDeep()`, `updater`, `function`)(updater); + let staticParcelUpdater = StaticParcel._updateFromData(updater); + let updated = staticParcelUpdater(_this._parcelData); + dispatch(ActionCreators.setData(updated)); }, + onChange: _this.set, + onChangeDOM: (event: Object) => { Types(`onChangeDOM()`, `event`, `event`)(event); _this.onChange(event.currentTarget.value); diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index e729fd8c..97f47934 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -3,6 +3,8 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelValueUpdater} from '../../types/Types'; +import type {StaticParcelUpdater} from '../../types/Types'; + import Types from '../../types/Types'; export default (_this: Parcel /*, dispatch: Function*/): Object => ({ @@ -17,6 +19,12 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).update(updater); }, + updateDeep: (key: Key|Index, updater: StaticParcelUpdater) => { + Types(`update()`, `key`, `keyIndex`)(key); + Types(`update()`, `updater`, `function`)(updater); + _this.get(key).updateDeep(updater); + }, + delete: (key: Key|Index) => { Types(`delete()`, `key`, `keyIndex`)(key); _this.get(key).delete(); @@ -29,10 +37,16 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ updateIn: (keyPath: Array, updater: ParcelValueUpdater) => { Types(`updateIn()`, `keyPath`, `keyIndexPath`)(keyPath); - Types(`update()`, `updater`, `function`)(updater); + Types(`updateIn()`, `updater`, `function`)(updater); _this.getIn(keyPath).update(updater); }, + updateInDeep: (keyPath: Array, updater: StaticParcelUpdater) => { + Types(`updateInDeep()`, `keyPath`, `keyIndexPath`)(keyPath); + Types(`updateInDeep()`, `updater`, `function`)(updater); + _this.getIn(keyPath).updateDeep(updater); + }, + deleteIn: (keyPath: Array) => { Types(`deleteIn()`, `keyPath`, `keyIndexPath`)(keyPath); _this.getIn(keyPath).delete(); From 7233ea90758005be6a511a39c42ae79a41957c6b Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:30:16 +1100 Subject: [PATCH 036/120] build: fix view-coverage command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1693a169..62998601 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "test": "yarn jest --maxWorkers=4", "test-all": "yarn lint && yarn flow && yarn test --maxWorkers=4 && yarn flow-coverage", "deploy-docs": "yarn lerna --scope dataparcels-docs run deploy", - "view-coverage": "yarn run coverage; open ./coverage/lcov-report/index.html", + "view-coverage": "open ./coverage/lcov-report/index.html", "watch": "lerna run watch --parallel --" }, "workspaces": { From 516c98a9d53b3f7fa2ae447e006dde8da0da41be Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:31:41 +1100 Subject: [PATCH 037/120] add: Parcel.children() --- .../src/docs/api/parcel/children.md | 3 ++ .../src/docs/api/parcel/toArray.md | 2 +- .../src/docs/api/parcel/toObject.md | 2 +- .../dataparcels-docs/src/pages/api/Parcel.jsx | 3 ++ packages/dataparcels/src/parcel/Parcel.js | 46 ++++++++++--------- .../parcel/__test__/ParentGetMethods-test.js | 34 +++++++++++++- .../src/parcel/methods/ParentGetMethods.js | 24 +++++----- 7 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/children.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/children.md b/packages/dataparcels-docs/src/docs/api/parcel/children.md new file mode 100644 index 00000000..16e558bc --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/children.md @@ -0,0 +1,3 @@ +```flow +children(mapper?: Function): Parent // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/toArray.md b/packages/dataparcels-docs/src/docs/api/parcel/toArray.md index ed5fe168..e7b262b0 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/toArray.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/toArray.md @@ -1,3 +1,3 @@ ```flow -toArray(mapper?: Function): Parcel[] // only on ParentParcels +toArray(mapper?: Function): Array // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/toObject.md b/packages/dataparcels-docs/src/docs/api/parcel/toObject.md index 3b0ac152..00bab19b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/toObject.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/toObject.md @@ -1,3 +1,3 @@ ```flow -toObject(mapper?: Function): Object // only on ParentParcels +toObject(mapper?: Function): {[key: string]: Parcel} // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 791569d7..78507ae1 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -14,6 +14,7 @@ import Markdown_spread from 'docs/api/parcel/spread.md'; import Markdown_spreadDOM from 'docs/api/parcel/spreadDOM.md'; import Markdown_get from 'docs/api/parcel/get.md'; import Markdown_getIn from 'docs/api/parcel/getIn.md'; +import Markdown_children from 'docs/api/parcel/children.md'; import Markdown_toObject from 'docs/api/parcel/toObject.md'; import Markdown_toArray from 'docs/api/parcel/toArray.md'; import Markdown_has from 'docs/api/parcel/has.md'; @@ -73,6 +74,7 @@ const md = { spreadDOM: Markdown_spreadDOM, get: Markdown_get, getIn: Markdown_getIn, + children: Markdown_children, toObject: Markdown_toObject, toArray: Markdown_toArray, has: Markdown_has, @@ -136,6 +138,7 @@ spreadDOM() # Branch methods get() getIn() +children() toObject() toArray() diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 2dc93878..9b9869f8 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -12,6 +12,7 @@ import type {ParcelMapper} from '../types/Types'; import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; +import type {ParentType} from '../types/Types'; import type {StaticParcelUpdater} from '../types/Types'; import Types from '../types/Types'; @@ -188,7 +189,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set data(value: *) { + set data(value: any) { throw ReadOnlyError(); } @@ -198,7 +199,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set value(value: *) { + set value(value: any) { throw ReadOnlyError(); } @@ -209,7 +210,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set meta(value: *) { + set meta(value: any) { throw ReadOnlyError(); } @@ -219,7 +220,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set key(value: *) { + set key(value: any) { throw ReadOnlyError(); } @@ -229,7 +230,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set id(value: *) { + set id(value: any) { throw ReadOnlyError(); } @@ -239,7 +240,7 @@ export default class Parcel { } // $FlowFixMe - this doesn't have side effects - set path(value: *) { + set path(value: any) { throw ReadOnlyError(); } @@ -248,14 +249,15 @@ export default class Parcel { // // Spread methods - spread = (notFoundValue: ?* = undefined): * => this._methods.spread(notFoundValue); - spreadDOM = (notFoundValue: ?* = undefined): * => this._methods.spreadDOM(notFoundValue); + spread = (notFoundValue: any = undefined): * => this._methods.spread(notFoundValue); + spreadDOM = (notFoundValue: any = undefined): * => this._methods.spreadDOM(notFoundValue); // Branch methods - get = (key: Key|Index, notFoundValue: ?* = undefined): Parcel => this._methods.get(key, notFoundValue); - getIn = (keyPath: Array, notFoundValue: ?* = undefined): Parcel => this._methods.getIn(keyPath, notFoundValue); - toObject = (mapper: ParcelMapper = _ => _): { [key: string]: * } => this._methods.toObject(mapper); - toArray = (mapper: ParcelMapper = _ => _): Array<*> => this._methods.toArray(mapper); + get = (key: Key|Index, notFoundValue: any = undefined): Parcel => this._methods.get(key, notFoundValue); + getIn = (keyPath: Array, notFoundValue: any = undefined): Parcel => this._methods.getIn(keyPath, notFoundValue); + children = (mapper: ParcelMapper = _ => _): ParentType => this._methods.children(mapper); + toObject = (mapper: ParcelMapper = _ => _): { [key: string]: Parcel } => this._methods.toObject(mapper); + toArray = (mapper: ParcelMapper = _ => _): Array => this._methods.toArray(mapper); // Parent methods has = (key: Key|Index): boolean => this._methods.has(key); @@ -274,11 +276,11 @@ export default class Parcel { spyChange = (sideEffect: Function): Parcel => this._methods.spyChange(sideEffect); // Change methods - onChange = (value: *) => this._methods.onChange(value); + onChange = (value: any) => this._methods.onChange(value); onChangeDOM = (event: *) => this._methods.onChangeDOM(event); set = overload({ - ["1"]: (value: *) => this._methods.setSelf(value), - ["2"]: (key: Key|Index, value: *) => this._methods.set(key, value) + ["1"]: (value: any) => this._methods.setSelf(value), + ["2"]: (key: Key|Index, value: any) => this._methods.set(key, value) }); update = overload({ ["1"]: (updater: ParcelValueUpdater) => this._methods.updateSelf(updater), @@ -288,7 +290,7 @@ export default class Parcel { ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfDeep(updater), ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateDeep(key, updater) }); - setIn = (keyPath: Array, value: *) => this._methods.setIn(keyPath, value); + setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); updateInDeep = (keyPath: Array, updater: StaticParcelUpdater) => this._methods.updateInDeep(keyPath, updater); delete = overload({ @@ -306,14 +308,14 @@ export default class Parcel { // Indexed methods insertAfter = overload({ - ["1"]: (value: *) => this._methods.insertAfterSelf(value), - ["2"]: (key: Key|Index, value: *) => this._methods.insertAfter(key, value) + ["1"]: (value: any) => this._methods.insertAfterSelf(value), + ["2"]: (key: Key|Index, value: any) => this._methods.insertAfter(key, value) }); insertBefore = overload({ - ["1"]: (value: *) => this._methods.insertBeforeSelf(value), - ["2"]: (key: Key|Index, value: *) => this._methods.insertBefore(key, value) + ["1"]: (value: any) => this._methods.insertBeforeSelf(value), + ["2"]: (key: Key|Index, value: any) => this._methods.insertBefore(key, value) }); - push = (value: *) => this._methods.push(value); + push = (value: any) => this._methods.push(value); pop = () => this._methods.pop(); shift = () => this._methods.shift(); swap = overload({ @@ -328,7 +330,7 @@ export default class Parcel { ["0"]: () => this._methods.swapPrevSelf(), ["1"]: (key: Key|Index) => this._methods.swapPrev(key) }); - unshift = (value: *) => this._methods.unshift(value); + unshift = (value: any) => this._methods.unshift(value); // Modify methods modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); diff --git a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js index 9267c672..6df48db9 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentGetMethods-test.js @@ -2,6 +2,8 @@ import Parcel from '../Parcel'; import TestTimeExecution from '../../util/__test__/TestTimeExecution-testUtil'; import GetAction from '../../util/__test__/GetAction-testUtil'; + +import every from 'unmutable/lib/every'; import map from 'unmutable/lib/map'; import range from 'unmutable/lib/util/range'; @@ -262,6 +264,37 @@ test('ParentParcel.getIn(keyPath) should cope with non existent keypaths', () => expect(descendantParcel2.value).toEqual("!!!"); }); +test('ParentParcel.children() should get child parcels in original collection', () => { + let children = new Parcel({ + value: {a:1,b:2,c:3} + }).children(); + + // test if child parcels are made + expect(every(parcel => parcel instanceof Parcel)(children)).toBe(true); + + // test if child parcel contents are good + expect(map(parcel => parcel.value)(children)).toEqual({ + a: 1, + b: 2, + c: 3 + }); +}); + +test('ParentParcel.children() should get child parcels in original collection with a mapper', () => { + let mapper = jest.fn(parcel => parcel.value); + let children = new Parcel({ + value: {a:1,b:2,c:3} + }).children(mapper); + + // test if child parcel contents are good + expect(children).toEqual({ + a: 1, + b: 2, + c: 3 + }); +}); + + test('ParentParcel.toObject() should make an object', () => { var data = { value: {a:1,b:2,c:3}, @@ -275,7 +308,6 @@ test('ParentParcel.toObject() should make an object', () => { var obj = map(ii => ii.value)(parcel.toObject()); expect(expectedObject).toEqual(obj); - }); test('ParentParcel.toObject() should make an object from an array', () => { diff --git a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js index 8563cb15..682c562a 100644 --- a/packages/dataparcels/src/parcel/methods/ParentGetMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentGetMethods.js @@ -4,12 +4,14 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelMapper} from '../../types/Types'; +import type {ParentType} from '../../types/Types'; import Types from '../../types/Types'; import parcelGet from '../../parcelData/get'; import parcelHas from '../../parcelData/has'; import prepareChildKeys from '../../parcelData/prepareChildKeys'; +import clone from 'unmutable/lib/clone'; import map from 'unmutable/lib/map'; import size from 'unmutable/lib/size'; import toArray from 'unmutable/lib/toArray'; @@ -69,24 +71,24 @@ export default (_this: Parcel) => ({ return parcel; }, - toObject: (mapper: ParcelMapper): { [key: string]: * } => { - Types(`toObject()`, `mapper`, `function`)(mapper); + children: (mapper: ParcelMapper): ParentType => { + Types(`children()`, `mapper`, `function`)(mapper); return pipeWith( _this._parcelData.value, - map((value, key) => mapper(_this.get(key), key, _this)), - toObject() + clone(), + map((value, key) => mapper(_this.get(key), key, _this)) ); }, - toArray: (mapper: ParcelMapper): Array<*> => { - Types(`toArray()`, `mapper`, `function`)(mapper); + toObject: (mapper: ParcelMapper): { [key: string]: Parcel } => { + Types(`toObject()`, `mapper`, `function`)(mapper); + return toObject()(_this.children(mapper)); + }, - return pipeWith( - _this._parcelData.value, - map((value, key) => mapper(_this.get(key), key, _this)), - toArray() - ); + toArray: (mapper: ParcelMapper): Array => { + Types(`toArray()`, `mapper`, `function`)(mapper); + return toArray()(_this.children(mapper)); }, size: (): number => size()(_this.value) From f1cf293af5f9da62b53afbd795f1d28cbc15a8ab Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:35:45 +1100 Subject: [PATCH 038/120] BREAK: add value updater validation to updaters --- packages/dataparcels/src/errors/Errors.js | 3 +-- .../src/parcel/__test__/ParcelChangeMethods-test.js | 8 ++++++++ .../src/parcel/methods/ParcelChangeMethods.js | 6 +++++- .../dataparcels/src/util/ValidateValueUpdater.js | 13 +++++++++++++ .../__test__/TestValidateValueUpdater-testUtil.js | 9 +++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 packages/dataparcels/src/util/ValidateValueUpdater.js create mode 100644 packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index 2c5ce366..825aa921 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -3,6 +3,5 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); -export const ModifyValueDownChildReturnError = () => new Error(`.modifyDown()'s updater can not return a value that has children unless it is unchanged by the updater or is empty.`); -export const ModifyValueUpChildReturnError = () => new Error(`When .modifyUp()'s updater is passed a value that has children, it cannot return a value that has children unless it is unchanged by the updater`); +export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index f551fadc..6b907af7 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -2,6 +2,7 @@ import Parcel from '../Parcel'; import GetAction from '../../util/__test__/GetAction-testUtil'; import StaticParcel from '../../staticParcel/StaticParcel'; +import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; test('Parcel.set() should call the Parcels handleChange function with the new parcelData', () => { expect.assertions(3); @@ -83,6 +84,13 @@ test('Parcel.update() should call the Parcels handleChange function with the new expect(handleChange.mock.calls[0][0].data.value).toBe(124); }); +test('Parcel.update() should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new Parcel({value}).update(updater) + ); +}); + test('Parcel.updateDeep() should call the Parcels handleChange function with the new parcelData', () => { let handleChange = jest.fn(); diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 891e856b..2e68b858 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -8,6 +8,7 @@ import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; import ActionCreators from '../../change/ActionCreators'; import StaticParcel from '../../staticParcel/StaticParcel'; +import ValidateValueUpdater from '../../util/ValidateValueUpdater'; export default (_this: Parcel, dispatch: Function) => ({ @@ -17,7 +18,10 @@ export default (_this: Parcel, dispatch: Function) => ({ updateSelf: (updater: ParcelValueUpdater) => { Types(`updateSelf()`, `updater`, `function`)(updater); - _this.set(updater(_this.value)); + let {value} = _this; + let updatedValue = updater(value, _this); + ValidateValueUpdater(value, updatedValue); + _this.set(updatedValue); }, updateSelfDeep: (updater: StaticParcelUpdater) => { diff --git a/packages/dataparcels/src/util/ValidateValueUpdater.js b/packages/dataparcels/src/util/ValidateValueUpdater.js new file mode 100644 index 00000000..b3604974 --- /dev/null +++ b/packages/dataparcels/src/util/ValidateValueUpdater.js @@ -0,0 +1,13 @@ +// @flow +import ParcelTypes from '../parcel/ParcelTypes'; +import {UnsafeValueUpdaterError} from '../errors/Errors'; + +import equals from 'unmutable/lib/equals'; + +export default (value: any, updatedValue: any) => { + let type = new ParcelTypes(value); + let updatedType = new ParcelTypes(updatedValue); + if(type.isParent() && updatedType.isParent() && !equals(value)(updatedValue)) { + throw UnsafeValueUpdaterError(); + } +}; diff --git a/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js b/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js new file mode 100644 index 00000000..4e193d8a --- /dev/null +++ b/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js @@ -0,0 +1,9 @@ +// @flow + +export default (expect: Function, test: Function) => { + expect(() => test(123, _ => _)).not.toThrowError(); + expect(() => test(123, () => [])).not.toThrowError(); + expect(() => test([], () => 123)).not.toThrowError(); + expect(() => test([1], _ => _)).not.toThrowError(); + expect(() => test([1], () => [2])).toThrowError('Value updaters'); +}; From 14175a40fff5e340c57ada86e61f8444889e2e65 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:35:59 +1100 Subject: [PATCH 039/120] refactor: sort methods --- .../src/parcel/methods/ParentChangeMethods.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index 97f47934..eb055bca 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -13,6 +13,21 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).set(value); }, + setIn: (keyPath: Array, value: *) => { + Types(`setIn()`, `keyPath`, `keyIndexPath`)(keyPath); + _this.getIn(keyPath).set(value); + }, + + delete: (key: Key|Index) => { + Types(`delete()`, `key`, `keyIndex`)(key); + _this.get(key).delete(); + }, + + deleteIn: (keyPath: Array) => { + Types(`deleteIn()`, `keyPath`, `keyIndexPath`)(keyPath); + _this.getIn(keyPath).delete(); + }, + update: (key: Key|Index, updater: ParcelValueUpdater) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); @@ -25,16 +40,6 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).updateDeep(updater); }, - delete: (key: Key|Index) => { - Types(`delete()`, `key`, `keyIndex`)(key); - _this.get(key).delete(); - }, - - setIn: (keyPath: Array, value: *) => { - Types(`setIn()`, `keyPath`, `keyIndexPath`)(keyPath); - _this.getIn(keyPath).set(value); - }, - updateIn: (keyPath: Array, updater: ParcelValueUpdater) => { Types(`updateIn()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateIn()`, `updater`, `function`)(updater); @@ -45,10 +50,5 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ Types(`updateInDeep()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateInDeep()`, `updater`, `function`)(updater); _this.getIn(keyPath).updateDeep(updater); - }, - - deleteIn: (keyPath: Array) => { - Types(`deleteIn()`, `keyPath`, `keyIndexPath`)(keyPath); - _this.getIn(keyPath).delete(); } }); From 2fbc19126b6403cfa9a75b396a62ba99f60893e3 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:36:31 +1100 Subject: [PATCH 040/120] refactor: redo updateIn to reduce code --- .../dataparcels/src/parcelData/updateIn.js | 71 +++---------------- 1 file changed, 8 insertions(+), 63 deletions(-) diff --git a/packages/dataparcels/src/parcelData/updateIn.js b/packages/dataparcels/src/parcelData/updateIn.js index 542f5229..ecbee149 100644 --- a/packages/dataparcels/src/parcelData/updateIn.js +++ b/packages/dataparcels/src/parcelData/updateIn.js @@ -1,73 +1,18 @@ // @flow import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; -import type {Property} from '../types/Types'; import type {ParcelData} from '../types/Types'; +import type {ParcelDataEvaluator} from '../types/Types'; -import get from './get'; -import isParentValue from './isParentValue'; -import prepareChildKeys from './prepareChildKeys'; -import keyOrIndexToProperty from './keyOrIndexToProperty'; -import updateChild from './updateChild'; -import updateChildKeys from './updateChildKeys'; +import update from './update'; +import composeWith from 'unmutable/lib/composeWith'; -import set from 'unmutable/lib/set'; -import update from 'unmutable/lib/update'; -import pipeWith from 'unmutable/lib/util/pipeWith'; - -let updateIn = (keyPath: Array, updater: Function) => (parcelData: ParcelData): ParcelData => { +export default (keyPath: Array, updater: Function): ParcelDataEvaluator => { if(keyPath.length === 0) { - return updater(parcelData); - } - - let [key, ...rest] = keyPath; - let parcelDataWithChildKeys = prepareChildKeys()(parcelData); - let property: ?Property = keyOrIndexToProperty(key)(parcelDataWithChildKeys); - - if(typeof property === "undefined") { - return parcelDataWithChildKeys; + return updater; } - - let before = pipeWith( - parcelDataWithChildKeys, - get(key) - ); - - let { - value: updatedValue, - child: updatedChild, - ...updatedChildValues - } = updateIn(rest, updater)(before); - - let value = pipeWith( - parcelDataWithChildKeys.value, - set(property, updatedValue) + return composeWith( + ...keyPath.map((key: Key|Index) => (next) => update(key, next)), + updater ); - - let child = pipeWith( - parcelDataWithChildKeys.child, - update(property, (node) => ({ - ...node, - child: updatedChild, - ...updatedChildValues - })) - ); - - let result = { - ...parcelDataWithChildKeys, - value, - child - }; - - if(isParentValue(result.value)) { - return pipeWith( - result, - updateChild(), - updateChildKeys() - ); - } - - return result; }; - -export default updateIn; From 094c1e7b9b23bf5bd18dc3a6f8f0e3a767887763 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 12 Jan 2019 12:36:48 +1100 Subject: [PATCH 041/120] amend: fix flow problem --- packages/dataparcels/src/util/FilterMethods.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/dataparcels/src/util/FilterMethods.js b/packages/dataparcels/src/util/FilterMethods.js index 5fe0bd91..e518b200 100644 --- a/packages/dataparcels/src/util/FilterMethods.js +++ b/packages/dataparcels/src/util/FilterMethods.js @@ -1,10 +1,11 @@ // @flow import type Parcel from '../parcel/Parcel'; +import type StaticParcel from '../staticParcel/StaticParcel'; import map from 'unmutable/lib/map'; import pipeWith from 'unmutable/lib/util/pipeWith'; -export default (parcelType: string, methodCreator: Function) => (parcel: Parcel, ...args: Array<*>): { [key: string]: Function } => { +export default (parcelType: string, methodCreator: Function) => (parcel: Parcel|StaticParcel, ...args: Array<*>): { [key: string]: Function } => { let methods: { [key: string]: Function } = methodCreator(parcel, ...args); // $FlowFixMe - I want to do this @@ -15,7 +16,8 @@ export default (parcelType: string, methodCreator: Function) => (parcel: Parcel, return pipeWith( methods, map((value, key) => (...args: Array<*>) => { - let suffix = `(keyPath: [${parcel.path.join(', ')}]).`; + // $FlowFixMe - why do you pay attention to your types more than preceding conditional logic? + let suffix = Array.isArray(parcel.path) ? `(keyPath: [${parcel.path.join(', ')}]).` : ``; if(key.slice(-4) === "Self") { throw new Error(`.${key.slice(0, -4)}() cannot be called with ${args.length} argument${args.length === 1 ? "" : "s"} on a value of "${parcel.value}". ${suffix}`); From 996ce7a42b48e5e34a98e2c7ed46512b6d1d16ec Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 13 Jan 2019 21:07:29 +1100 Subject: [PATCH 042/120] add: add new type exports --- packages/dataparcels/src/index.js | 12 ++++++++++++ packages/dataparcels/src/parcel/Parcel.js | 4 ++-- packages/dataparcels/src/types/Types.js | 19 +++++++++++++++++-- packages/react-dataparcels/src/index.js | 20 ++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index 2c4c8558..17f1145d 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -4,11 +4,17 @@ export default Parcel; export {default as Action} from './change/Action'; export {default as ChangeRequest} from './change/ChangeRequest'; +export {default as StaticParcel} from './staticParcel/StaticParcel'; export {default as DeletedParcelMarker} from './parcelData/DeletedParcelMarker'; +// +// types +// + export type {ParcelData} from './types/Types'; export type {ParcelConfig} from './types/Types'; export type {ParcelConfigInternal} from './types/Types'; +export type {ParcelCreateConfigType} from './types/Types'; export type {ParcelMeta} from './types/Types'; export type {ParcelBatcher} from './types/Types'; @@ -16,6 +22,12 @@ export type {ParcelMapper} from './types/Types'; export type {ParcelUpdater} from './types/Types'; export type {ParcelValueUpdater} from './types/Types'; +export type {StaticParcelSetMeta} from './types/Types'; +export type {StaticParcelUpdater} from './types/Types'; +export type {StaticParcelValueUpdater} from './types/Types'; +export type {StaticParcelConfigInternal} from './types/Types'; + export type {Key} from './types/Types'; export type {Index} from './types/Types'; export type {Property} from './types/Types'; +export type {ParentType} from './types/Types'; diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 9b9869f8..ea9fb195 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -1,7 +1,7 @@ // @flow import type Action from '../change/Action'; import type ChangeRequest from '../change/ChangeRequest'; -import type {CreateParcelConfigType} from '../types/Types'; +import type {ParcelCreateConfigType} from '../types/Types'; import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; import type {ParcelBatcher} from '../types/Types'; @@ -147,7 +147,7 @@ export default class Parcel { _log: boolean = false; // used by log() _logName: string = ""; // used by log() - _create = (createParcelConfig: CreateParcelConfigType): Parcel => { + _create = (createParcelConfig: ParcelCreateConfigType): Parcel => { let { id = this._id, onDispatch = this.dispatch, diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index 1ced63b5..deacce04 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -5,6 +5,7 @@ import type Treeshare from '../treeshare/Treeshare'; import Parcel from '../parcel/Parcel'; import Action from '../change/Action'; import ChangeRequest from '../change/ChangeRequest'; +import StaticParcel from '../staticParcel/StaticParcel'; import isPlainObject from 'unmutable/lib/util/isPlainObject'; export type ParcelData = { @@ -30,7 +31,7 @@ export type ParcelConfigInternal = { treeshare: Treeshare }; -export type CreateParcelConfigType = { +export type ParcelCreateConfigType = { onDispatch?: Function, id?: ParcelId, parcelData?: ParcelData, @@ -43,12 +44,22 @@ export type ParcelMeta = {[key: string]: *}; export type ParcelBatcher = (item: Parcel) => void; export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) => *; export type ParcelUpdater = (item: Parcel) => Parcel; -export type ParcelValueUpdater = (value: *) => *; +export type ParcelValueUpdater = (value: *, parcel: Parcel) => *; + +export type StaticParcelSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; +export type StaticParcelUpdater = (item: StaticParcel) => StaticParcel; +export type StaticParcelValueUpdater = (value: *, parcel: StaticParcel) => *; + +export type StaticParcelConfigInternal = { + parent?: ?StaticParcel +}; export type Key = string; export type Index = number; export type Property = number|string; +export type ParentType = any; // should be any parent data type + export type ParcelIdData = { id: string[], path: string[] @@ -104,6 +115,10 @@ const RUNTIME_TYPES = { name: "an object containing parcel data {value: *, meta?: {}, key?: *}", check: ii => isPlainObject(ii) && ii.hasOwnProperty('value') }, + ['staticParcel']: { + name: "a StaticParcel", + check: ii => ii instanceof StaticParcel + }, ['string']: { name: "a string", check: ii => typeof ii === "string" diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index 711b1e59..3d153f6f 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -1,14 +1,25 @@ // @flow + +// +// dataparcels +// + import dataparcels from 'dataparcels'; export default dataparcels; export {Action} from 'dataparcels'; export {ChangeRequest} from 'dataparcels'; +export {StaticParcel} from 'dataparcels'; export {DeletedParcelMarker} from 'dataparcels'; +// +// dataparcels types +// + export type {ParcelData} from 'dataparcels'; export type {ParcelConfig} from 'dataparcels'; export type {ParcelConfigInternal} from 'dataparcels'; +export type {ParcelCreateConfigType} from 'dataparcels'; export type {ParcelMeta} from 'dataparcels'; export type {ParcelBatcher} from 'dataparcels'; @@ -16,10 +27,19 @@ export type {ParcelMapper} from 'dataparcels'; export type {ParcelUpdater} from 'dataparcels'; export type {ParcelValueUpdater} from 'dataparcels'; +export type {StaticParcelSetMeta} from 'dataparcels'; +export type {StaticParcelUpdater} from 'dataparcels'; +export type {StaticParcelValueUpdater} from 'dataparcels'; +export type {StaticParcelConfigInternal} from 'dataparcels'; + export type {Key} from 'dataparcels'; export type {Index} from 'dataparcels'; export type {Property} from 'dataparcels'; +export type {ParentType} from 'dataparcels'; +// +// react-dataparcels +// export {default as ParcelHoc} from './ParcelHoc'; export {default as ParcelBoundary} from './ParcelBoundary'; From 6b51e498197f1966d6858d1e1003f1e1b0cb2ad6 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 13 Jan 2019 21:09:09 +1100 Subject: [PATCH 043/120] BREAK: add standardised value updater --- .../src/parcel/__test__/ModifyMethods-test.js | 82 +++---------------- .../src/parcel/methods/ModifyMethods.js | 22 +---- .../src/util/ValidateValueUpdater.js | 6 +- 3 files changed, 17 insertions(+), 93 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index a87db498..dc1dfaed 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -3,6 +3,7 @@ import type ChangeRequest from '../../change/ChangeRequest'; import Parcel from '../Parcel'; import StaticParcel from '../../staticParcel/StaticParcel'; +import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; test('Parcel.modifyDown() should return a new parcel with updated parcelData', () => { expect.assertions(2); @@ -36,42 +37,11 @@ test('Parcel.modifyDown() should allow non-parent types to be returned', () => { expect(updatedValue).toEqual(124); }); -test('Parcel.modifyDown() should allow childless parent types to be returned', () => { - let updatedValue = new Parcel({ - value: 123 - }) - .modifyDown(value => []) - .value; - - expect(updatedValue).toEqual([]); -}); - -test('Parcel.modifyDown() should allow parent types to be returned if they dont change', () => { - let updatedValue = new Parcel({ - value: [123] - }) - .modifyDown(value => value) - .value; - - expect(updatedValue).toEqual([123]); -}); - -test('Parcel.modifyDown() should throw error if changed parent types with children are returned', () => { - expect(() => { - new Parcel({ - value: [123] - }).modifyDown(value => [...value, 456]); - - }).toThrowError(`modifyDown()`); -}); - -test('Parcel.modifyDown() should throw error if childless is turned into parent types with children', () => { - expect(() => { - new Parcel({ - value: 123 - }).modifyDown(value => [123, 456]); - - }).toThrowError(`modifyDown()`); +test('Parcel.modifyDown() should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new Parcel({value}).modifyDown(updater).value + ); }); test('Parcel.modifyDown() should recognise if value changes types, and set value if type changes', () => { @@ -157,41 +127,11 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc }); -test('Parcel.modifyUp() should allow parent types to be returned', () => { - var handleChange = jest.fn(); - new Parcel({ - value: 123, - handleChange - }) - .modifyUp(value => [123,456]) - .onChange(456); - - expect(handleChange.mock.calls[0][0].value).toEqual([123,456]); -}); - -test('Parcel.modifyUp() should allow parent types to be returned if they dont change', () => { - var handleChange = jest.fn(); - new Parcel({ - value: [123], - handleChange - }) - .modifyUp(value => value) - .onChange([456]); - - expect(handleChange.mock.calls[0][0].value).toEqual([456]); -}); - -test('Parcel.modifyUp() should throw error if changed parent types with children are returned', () => { - expect(() => { - var handleChange = jest.fn(); - new Parcel({ - value: [123], - handleChange - }) - .modifyUp(value => [...value, 456]) - .onChange([456]); - - }).toThrowError(`modifyUp()`); +test('Parcel.modifyUp() should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new Parcel({value: undefined}).modifyUp(updater).onChange(value) + ); }); test('Parcel.modifyUp() should allow changes to meta through', () => { diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index a317c6b4..929c40e2 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -6,13 +6,11 @@ import type {ParcelValueUpdater} from '../../types/Types'; import Types from '../../types/Types'; import StaticParcel from '../../staticParcel/StaticParcel'; +import ValidateValueUpdater from '../../util/ValidateValueUpdater'; import ParcelTypes from '../ParcelTypes'; -import {ModifyValueDownChildReturnError} from '../../errors/Errors'; -import {ModifyValueUpChildReturnError} from '../../errors/Errors'; import HashString from '../../util/HashString'; -import equals from 'unmutable/lib/equals'; import filterNot from 'unmutable/lib/filterNot'; import has from 'unmutable/lib/has'; import isEmpty from 'unmutable/lib/isEmpty'; @@ -31,12 +29,9 @@ export default (_this: Parcel): Object => ({ let {value} = _this._parcelData; let updatedValue = updater(value, _this); - let updatedType = new ParcelTypes(updatedValue); - - if(updatedType.isParent() && !isEmpty()(updatedValue) && !equals(value)(updatedValue)) { - throw ModifyValueDownChildReturnError(); - } + ValidateValueUpdater(value, updatedValue); + let updatedType = new ParcelTypes(updatedValue); let updatedTypeChanged: boolean = updatedType.isParent() !== _this._parcelTypes.isParent() || updatedType.isIndexed() !== _this._parcelTypes.isIndexed(); @@ -68,17 +63,8 @@ export default (_this: Parcel): Object => ({ return _this.modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { let {value} = changeRequest.nextData; - let type = new ParcelTypes(value); - let updatedValue = updater(value, _this); - - if(type.isParent()) { - if(!equals(value)(updatedValue)) { - throw ModifyValueUpChildReturnError(); - } - parcel.dispatch(changeRequest); - return; - } + ValidateValueUpdater(value, updatedValue); // dispatch all non-value actions in this change request let valueActionFilter = actions => actions.filter(action => !action.isValueAction()); diff --git a/packages/dataparcels/src/util/ValidateValueUpdater.js b/packages/dataparcels/src/util/ValidateValueUpdater.js index b3604974..a0a21768 100644 --- a/packages/dataparcels/src/util/ValidateValueUpdater.js +++ b/packages/dataparcels/src/util/ValidateValueUpdater.js @@ -1,13 +1,11 @@ // @flow -import ParcelTypes from '../parcel/ParcelTypes'; +import isParentValue from '../parcelData/isParentValue'; import {UnsafeValueUpdaterError} from '../errors/Errors'; import equals from 'unmutable/lib/equals'; export default (value: any, updatedValue: any) => { - let type = new ParcelTypes(value); - let updatedType = new ParcelTypes(updatedValue); - if(type.isParent() && updatedType.isParent() && !equals(value)(updatedValue)) { + if(isParentValue(value) && isParentValue(updatedValue) && !equals(value)(updatedValue)) { throw UnsafeValueUpdaterError(); } }; From fa1c71c076be1cac7069457501dd826a6114f0c7 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 13 Jan 2019 21:09:51 +1100 Subject: [PATCH 044/120] add: add static parcel --- packages/dataparcels/src/errors/Errors.js | 1 + .../src/staticParcel/StaticParcel.js | 204 +++++++++++++++ .../__test__/StaticIndexedSetMethods-test.js | 74 ++++++ .../__test__/StaticParcel-test.js | 60 +++++ .../__test__/StaticParcelTypes-test.js | 181 ++++++++++++++ .../__test__/StaticParentGetMethods-test.js | 147 +++++++++++ .../__test__/StaticParentSetMethods-test.js | 236 ++++++++++++++++++ .../__test__/StaticSetMethods-test.js | 230 +++++++++++++++++ .../methods/StaticIndexedSetMethods.js | 80 ++++++ .../methods/StaticParentGetMethods.js | 72 ++++++ .../methods/StaticParentSetMethods.js | 59 +++++ .../staticParcel/methods/StaticSetMethods.js | 71 ++++++ 12 files changed, 1415 insertions(+) create mode 100644 packages/dataparcels/src/staticParcel/StaticParcel.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js create mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js create mode 100644 packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js create mode 100644 packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js create mode 100644 packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js create mode 100644 packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index 825aa921..4ae30daf 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -5,3 +5,4 @@ export const ReducerInvalidActionError = (actionType: string) => new Error(`"${a export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); +export const DeepUpdaterNonStaticChildError = () => new Error(`Every child value on a collection returned from a deep updater must be a StaticParcel`); diff --git a/packages/dataparcels/src/staticParcel/StaticParcel.js b/packages/dataparcels/src/staticParcel/StaticParcel.js new file mode 100644 index 00000000..cf81c39f --- /dev/null +++ b/packages/dataparcels/src/staticParcel/StaticParcel.js @@ -0,0 +1,204 @@ +// @flow +import type {Index} from '../types/Types'; +import type {Key} from '../types/Types'; +import type {ParcelData} from '../types/Types'; +import type {ParentType} from '../types/Types'; +import type {StaticParcelValueUpdater} from '../types/Types'; +import type {StaticParcelConfigInternal} from '../types/Types'; +import type {StaticParcelUpdater} from '../types/Types'; +import type {StaticParcelSetMeta} from '../types/Types'; + +import Types from '../types/Types'; +import {ReadOnlyError} from '../errors/Errors'; + +import ParcelTypes from '../parcel/ParcelTypes'; +import ParcelId from '../parcelId/ParcelId'; + +import StaticParentGetMethods from './methods/StaticParentGetMethods'; +import StaticParentSetMethods from './methods/StaticParentSetMethods'; +import StaticSetMethods from './methods/StaticSetMethods'; +import StaticIndexedSetMethods from './methods/StaticIndexedSetMethods'; + +import FilterMethods from '../util/FilterMethods'; + +import overload from 'unmutable/lib/util/overload'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +import prepareChildKeys from '../parcelData/prepareChildKeys'; + +export default class StaticParcel { + constructor(value: any, _configInternal: ?StaticParcelConfigInternal) { + this._parcelData = { + value + }; + + let {parent} = _configInternal || {}; + + // parent + if(parent) { + // $FlowFixMe + this._parent = parent; + } + + // types + this._parcelTypes = new ParcelTypes( + value, + parent && parent._parcelTypes, + !parent + ); + + // methods + this._methods = { + // $FlowFixMe + ...FilterMethods("Parent", StaticParentGetMethods)(this), + // $FlowFixMe + ...FilterMethods("Parent", StaticParentSetMethods)(this), + // $FlowFixMe + ...StaticSetMethods(this), + // $FlowFixMe + ...FilterMethods("Indexed", StaticIndexedSetMethods)(this) + }; + } + + // + // private + // + + // from constructor + _id: ParcelId; + _methods: { [key: string]: any }; + _parent: ?StaticParcel; + _parcelData: ParcelData; + _parcelTypes: ParcelTypes; + + static _updateFromData(updater: StaticParcelUpdater): Function { + return (parcelData: ParcelData): ParcelData => StaticParcel + .fromData(parcelData) + .updateDeep(updater) + .data; + } + + // only need this to reference static methods on StaticParcel + // without creating circular dependencies + _instanceUpdateFromData = StaticParcel._updateFromData; + + _pipeSelf = (fn: Function, _configInternal: ?StaticParcelConfigInternal): StaticParcel => pipeWith( + this._parcelData, + fn, + data => StaticParcel.fromData(data, _configInternal) + ); + + _isStaticParcel = (maybe: any): boolean => maybe instanceof StaticParcel; + + _prepareChildKeys = () => { + // prepare child keys only once per parcel instance + // by preparing them and mutating this.parcelData + + if(!this._parcelData.child) { + this._parcelData = prepareChildKeys()(this._parcelData); + } + } + + // + // getters + // + + // $FlowFixMe - this doesn't have side effects + get data(): ParcelData { + return this._parcelData; + } + + // $FlowFixMe - this doesn't have side effects + set data(value: any) { + throw ReadOnlyError(); + } + + // $FlowFixMe - this doesn't have side effects + get value(): any { + return this._parcelData.value; + } + + // $FlowFixMe - this doesn't have side effects + set value(value: any) { + throw ReadOnlyError(); + } + + // $FlowFixMe - this doesn't have side effects + get meta(): any { + let {meta = {}} = this._parcelData; + return {...meta}; + } + + // $FlowFixMe - this doesn't have side effects + set meta(value: any) { + throw ReadOnlyError(); + } + + // $FlowFixMe - this doesn't have side effects + get key(): Key { + return this._parcelData.key; + } + + // $FlowFixMe - this doesn't have side effects + set key(value: any) { + throw ReadOnlyError(); + } + + // + // public methods + // + + static fromData(parcelData: ParcelData, _configInternal: ?StaticParcelConfigInternal): StaticParcel { + Types(`StaticParcel()`, `fromData`, `parcelData`)(parcelData); + let staticParcel = new StaticParcel(parcelData.value, _configInternal); + staticParcel._parcelData = parcelData; + return staticParcel; + } + + // Parent methods + has = (key: Key|Index): boolean => this._methods.has(key); + size = (): number => this._methods.size(); + get = (key: Key|Index, notFoundValue: ?any = undefined): StaticParcel => this._methods.get(key, notFoundValue); + getIn = (keyPath: Array, notFoundValue: ?any = undefined): StaticParcel => this._methods.getIn(keyPath, notFoundValue); + children = (): ParentType => this._methods.children(); + toObject = (): { [key: string]: StaticParcel } => this._methods.toObject(); + toArray = (): Array => this._methods.toArray(); + + // Change methods + set = overload({ + ["1"]: (value: any) => this._methods.setSelf(value), + ["2"]: (key: Key|Index, value: any) => this.setIn([key], value) + }); + setMeta = (partialMeta: StaticParcelSetMeta) => this._methods.setMeta(partialMeta); + setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); + delete = (key: Key|Index) => this.deleteIn([key]); + deleteIn = (keyPath: Array) => this._methods.deleteIn(keyPath); + update = overload({ + ["1"]: (updater: StaticParcelValueUpdater): StaticParcel => this._methods.update(updater), + ["2"]: (key: Key|Index, updater: StaticParcelValueUpdater): StaticParcel => this.updateIn([key], updater) + }); + updateDeep = overload({ + ["1"]: (updater: StaticParcelUpdater): StaticParcel => this._methods.updateDeep(updater), + ["2"]: (key: Key|Index, updater: StaticParcelUpdater): StaticParcel => this.updateInDeep([key], updater) + }); + updateIn = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateIn(keyPath, updater); + updateInDeep = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateInDeep(keyPath, updater); + + // Indexed methods + insertAfter = (key: Key|Index, value: any) => this._methods.insertAfter(key, value); + insertBefore = (key: Key|Index, value: any) => this._methods.insertBefore(key, value); + push = (value: any) => this._methods.push(value); + pop = () => this._methods.pop(); + shift = () => this._methods.shift(); + swap = (keyA: Key|Index, keyB: Key|Index) => this._methods.swap(keyA, keyB); + swapNext = (key: Key|Index) => this._methods.swapNext(key); + swapPrev = (key: Key|Index) => this._methods.swapPrev(key); + unshift = (value: any) => this._methods.unshift(value); + + // Type methods + isChild = (): boolean => this._parcelTypes.isChild(); + isElement = (): boolean => this._parcelTypes.isElement(); + isIndexed = (): boolean => this._parcelTypes.isIndexed(); + isParent = (): boolean => this._parcelTypes.isParent(); + isTopLevel = (): boolean => this._parcelTypes.isTopLevel(); +} diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js new file mode 100644 index 00000000..d2027dbf --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js @@ -0,0 +1,74 @@ +// @flow +import StaticParcel from '../StaticParcel'; + +test('StaticParcels insertAfter(key, value) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.insertAfter(0, 3).data.value).toEqual([0,3,1,2]); +}); + +test('StaticParcels insertBefore(key, value) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.insertBefore(0, 3).data.value).toEqual([3,0,1,2]); +}); + +test('StaticParcels push(value) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.push(3).data.value).toEqual([0,1,2,3]); +}); + +test('StaticParcels pop() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.pop().data.value).toEqual([0,1]); +}); + +test('StaticParcels shift() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.shift().data.value).toEqual([1,2]); +}); + +test('StaticParcels swap() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.swap(0,2).data.value).toEqual([2,1,0]); +}); + +test('StaticParcels swapNext() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.swapNext(1).data.value).toEqual([0,2,1]); +}); + +test('StaticParcels swapPrev() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.swapPrev(1).data.value).toEqual([1,0,2]); +}); + +test('StaticParcels unshift(value) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.unshift(3).data.value).toEqual([3,0,1,2]); +}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js new file mode 100644 index 00000000..5a66e1ed --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js @@ -0,0 +1,60 @@ +// @flow +import StaticParcel from '../StaticParcel'; + +test('StaticParcels should accept value', () => { + let parcel = new StaticParcel(123); + expect(parcel.value).toEqual(123); +}); + +test('StaticParcels.fromData should accept parcel data', () => { + let data = { + value: [0,1,2], + meta: { + abc: 123 + }, + key: "^", + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + let parcel = StaticParcel.fromData(data); + expect(parcel.data).toEqual(data); +}); + +test('StaticParcels should return data', () => { + let parcel = new StaticParcel(123); + expect(parcel.data).toEqual({ + value: 123 + }); +}); + +test('StaticParcels should return empty meta object', () => { + let parcel = new StaticParcel(123); + expect(parcel.meta).toEqual({}); +}); + +test('StaticParcels should throw errors when attempted to set getters', () => { + let readOnly = 'This property is read-only'; + + let parcel = new StaticParcel(123); + + expect(() => { + parcel.data = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.value = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.meta = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.key = 123; + }).toThrow(readOnly); + +}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js new file mode 100644 index 00000000..6733bfd0 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js @@ -0,0 +1,181 @@ +// @flow +import {Map, List} from 'immutable'; +import StaticParcel from '../StaticParcel'; + +test('StaticParcelTypes should correctly identify primitive values', () => { + var value = 123; + expect(new StaticParcel(value).isParent()).toBe(false); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify date', () => { + var value = new Date(); + expect(new StaticParcel(value).isParent()).toBe(false); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify object values', () => { + var value = { + a: "A" + }; + expect(new StaticParcel(value).isParent()).toBe(true); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify class instance values', () => { + class Thing { + foo = "123" + } + var value = new Thing(); + expect(new StaticParcel(value).isParent()).toBe(false); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify unmutable compatible class instance values', () => { + class UnmutableCompatible { + __UNMUTABLE_COMPATIBLE__ = true; + foo = "123"; + } + var value = new UnmutableCompatible(); + expect(new StaticParcel(value).isParent()).toBe(true); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + + +test('StaticParcelTypes should correctly identify Immutable.js Map values', () => { + var value = Map({ + a: "A" + }); + expect(new StaticParcel(value).isParent()).toBe(true); + expect(new StaticParcel(value).isIndexed()).toBe(false); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + + +test('StaticParcelTypes should correctly identify array values', () => { + var value = [1,2,3]; + expect(new StaticParcel(value).isParent()).toBe(true); + expect(new StaticParcel(value).isIndexed()).toBe(true); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify Immutable.js List values', () => { + var value = List([1,2,3]); + expect(new StaticParcel(value).isParent()).toBe(true); + expect(new StaticParcel(value).isIndexed()).toBe(true); + expect(new StaticParcel(value).isChild()).toBe(false); + expect(new StaticParcel(value).isElement()).toBe(false); + expect(new StaticParcel(value).isTopLevel()).toBe(true); +}); + +test('StaticParcelTypes should correctly identify child values', () => { + var value = { + a: "A" + }; + expect(new StaticParcel(value).get("a").isParent()).toBe(false); + expect(new StaticParcel(value).get("a").isIndexed()).toBe(false); + expect(new StaticParcel(value).get("a").isChild()).toBe(true); + expect(new StaticParcel(value).get("a").isElement()).toBe(false); + expect(new StaticParcel(value).get("a").isTopLevel()).toBe(false); +}); + +test('StaticParcelTypes should correctly identify element values', () => { + var value = [1,2,3]; + expect(new StaticParcel(value).get(0).isParent()).toBe(false); + expect(new StaticParcel(value).get(0).isIndexed()).toBe(false); + expect(new StaticParcel(value).get(0).isChild()).toBe(true); + expect(new StaticParcel(value).get(0).isElement()).toBe(true); + expect(new StaticParcel(value).get(0).isTopLevel()).toBe(false); +}); + +test('StaticParcelTypes should correctly identify child values with getIn', () => { + var value = { + b: { + a: "A" + } + }; + expect(new StaticParcel(value).getIn(["b","a"]).isParent()).toBe(false); + expect(new StaticParcel(value).getIn(["b","a"]).isIndexed()).toBe(false); + expect(new StaticParcel(value).getIn(["b","a"]).isChild()).toBe(true); + expect(new StaticParcel(value).getIn(["b","a"]).isElement()).toBe(false); + expect(new StaticParcel(value).getIn(["b","a"]).isTopLevel()).toBe(false); +}); + +test('StaticParcelTypes should correctly identify element values with getIn', () => { + var value = { + b: [1,2,3] + }; + + expect(new StaticParcel(value).getIn(["b",0]).isParent()).toBe(false); + expect(new StaticParcel(value).getIn(["b",0]).isIndexed()).toBe(false); + expect(new StaticParcel(value).getIn(["b",0]).isChild()).toBe(true); + expect(new StaticParcel(value).getIn(["b",0]).isElement()).toBe(true); + expect(new StaticParcel(value).getIn(["b",0]).isTopLevel()).toBe(false); +}); + +// // method creators + +// // test('Correct methods are created for primitive values', () => { +// // var value = 123; +// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); +// // expect(() => new StaticParcel(value).has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new StaticParcel(value).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for object values', () => { +// // var value = {a: 123}; +// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); +// // expect(() => new StaticParcel(value).has('a')).not.toThrow(); +// // expect(() => new StaticParcel(value).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for array values', () => { +// // var value = [1,2,3]; +// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); +// // expect(() => new StaticParcel(value).has('a')).not.toThrow(); +// // expect(() => new StaticParcel(value).pop()).not.toThrow(); +// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for object child values', () => { +// // var value = {a: 123}; +// // expect(() => new StaticParcel(value).get("a").set('A')).not.toThrow(); +// // expect(() => new StaticParcel(value).get("a").has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new StaticParcel(value).get("a").pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new StaticParcel(value).get("a").delete()).not.toThrow(); +// // expect(() => new StaticParcel(value).get("a").swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for array element values', () => { +// // var value = [1,2,3]; +// // expect(() => new StaticParcel(value).get(0).set('A')).not.toThrow(); +// // expect(() => new StaticParcel(value).get(0).has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new StaticParcel(value).get(0).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new StaticParcel(value).get(0).delete()).not.toThrow(); +// // expect(() => new StaticParcel(value).get(0).swapNext()).not.toThrow(); +// // }); + diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js new file mode 100644 index 00000000..cdaf9447 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js @@ -0,0 +1,147 @@ +// @flow +import StaticParcel from '../StaticParcel'; + +import map from 'unmutable/lib/map'; + +test('StaticParcels getters should work', () => { + let data = { + value: [0,1,2], + meta: { + abc: 123 + }, + key: "^", + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + let parcel = StaticParcel.fromData(data); + expect(parcel.meta).toEqual(data.meta); + expect(parcel.key).toEqual(data.key); +}); + +test('StaticParcels.get should work with objects', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: { + b: 1 + }, + key: "a" + }; + + expect(staticParcel.get('a').data).toEqual(expectedParcelData); +}); + +test('StaticParcels.getIn should work with objects', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: 1, + key: "b" + }; + + expect(staticParcel.getIn(['a','b']).data).toEqual(expectedParcelData); +}); + +test('StaticParcels.getIn should work with objects with non-existent keys', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: undefined, + key: "z" + }; + + expect(staticParcel.getIn(['z']).data).toEqual(expectedParcelData); +}); + +test('StaticParcels.getIn should return undefined if asking through a non-parent', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1 + } + }); + + let expectedParcelData = { + value: undefined, + key: "b" + }; + + expect(staticParcel.getIn(['a', 'b']).data).toEqual(expectedParcelData); +}); + +test('StaticParcels.size() should return size of parcel', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + } + }); + + expect(staticParcel.size()).toBe(2); +}); + +test('StaticParcels.has(key) should return a boolean indicating if key exists', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + } + }); + + expect(staticParcel.has('a')).toBe(true); + expect(staticParcel.has('z')).toBe(false); +}); + +test('StaticParcels.children() should make a parent data type full of static parcels', () => { + let children = StaticParcel.fromData({ + value: {a:1,b:2,c:3} + }) + .children(); + + expect(map(ii => ii.value)(children)).toEqual({a:1,b:2,c:3}); +}); + +test('StaticParcels.toObject() should make an object', () => { + let staticParcel = StaticParcel.fromData({ + value: {a:1,b:2,c:3}, + meta: { + a: {a:4,b:5,c:6} + } + }); + + var expectedValue = {a:1,b:2,c:3}; + expect(map(ii => ii.value)(staticParcel.toObject())).toEqual(expectedValue); +}); + +test('StaticParcels.toArray() should make an array', () => { + let staticParcel = StaticParcel.fromData({ + value: {a:1,b:2,c:3}, + meta: { + a: {a:4,b:5,c:6} + } + }); + + var expectedValue = [1,2,3]; + expect(map(ii => ii.value)(staticParcel.toArray())).toEqual(expectedValue); +}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js new file mode 100644 index 00000000..6bb2ed75 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js @@ -0,0 +1,236 @@ +// @flow +import StaticParcel from '../StaticParcel'; +import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; + +test('StaticParcels set(key) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + }, + child: { + a: {key: "a"}, + b: {key: "b"} + } + }); + + let expectedData = { + value: { + a: 456, + b: 4 + }, + child: { + a: { + child: undefined, + key: "a" + }, + b: { + key: "b" + } + } + }; + + expect(staticParcel.set('a', 456).data).toEqual(expectedData); +}); + +test('StaticParcels setIn(keyPath) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 123 + }, + c: 456 + } + }); + + let expectedData = { + value: { + a: { + b: 456 + }, + c: 456 + }, + child: { + a: { + child: { + b: { + child: undefined, + key: "b" + } + }, + key: "a" + }, + c: { + key: "c" + } + } + }; + + expect(staticParcel.setIn(['a', 'b'], 456).data).toEqual(expectedData); +}); + +test('StaticParcels delete(key) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + }, + child: { + a: {key: "a"}, + b: {key: "b"} + } + }); + + let expectedData = { + value: { + b: 4 + }, + child: { + b: { + key: "b" + } + } + }; + + expect(staticParcel.delete('a').data).toEqual(expectedData); +}); + +test('StaticParcels deleteIn(keyPath) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 123 + }, + c: 456 + } + }); + + let expectedData = { + value: { + a: {}, + c: 456 + }, + child: { + a: { + child: {}, + key: "a" + }, + c: { + key: "c" + } + } + }; + + expect(staticParcel.deleteIn(['a', 'b']).data).toEqual(expectedData); +}); + +test('StaticParcels update(key) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + } + }); + + let expectedData = { + value: { + a: 2, + b: 4 + }, + child: { + a: { + child: undefined, + key: "a" + }, + b: { + child: undefined, + key: "b" + } + } + }; + + expect(staticParcel.update('a', ii => ii + 1).data).toEqual(expectedData); +}); + +test('StaticParcels update(key) should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new StaticParcel({ + abc: value + }).update('abc', updater) + ); +}); + +test('StaticParcels updateIn(keyPath) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: { + b: 123 + } + } + }); + + let expectedData = { + value: { + a: { + b: 124 + } + }, + child: { + a: { + child: { + b: { + child: undefined, + key: "b" + } + }, + key: "a" + } + } + }; + + expect(staticParcel.updateIn(['a', 'b'], ii => ii + 1).data).toEqual(expectedData); +}); + +test('StaticParcels updateIn(keyPath) should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new StaticParcel({ + a: { + b: value + } + }).updateIn(['a', 'b'], updater) + ); +}); + +test('StaticParcels updateDeep(key) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + abc: [1,2,3] + } + }); + + let expectedValue = { + abc: [1,2,3,4] + }; + + expect(staticParcel.updateDeep('abc', staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); +}); + +test('StaticParcels updateInDeep(keyPath) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + abc: { + def: [1,2,3] + } + } + }); + + let expectedValue = { + abc: { + def: [1,2,3,4] + } + }; + + expect(staticParcel.updateInDeep(['abc', 'def'], staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); +}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js new file mode 100644 index 00000000..647379e9 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js @@ -0,0 +1,230 @@ +// @flow +import StaticParcel from '../StaticParcel'; +import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; + +test('StaticParcels set() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: { + a: 1, + b: 4 + }, + child: { + a: {key: "a"}, + b: {key: "b"} + } + }); + + let expectedData = { + value: 456 + }; + + expect(staticParcel.set(456).data).toEqual(expectedData); +}); + +test('StaticParcels setMeta(partialMeta) should work', () => { + let staticParcel = StaticParcel.fromData({ + value: 123, + meta: { + abc: 123 + } + }); + + let expectedData = { + value: 123, + meta: { + abc: 123, + def: 456 + } + }; + + expect(staticParcel.setMeta({def: 456}).data).toEqual(expectedData); +}); + +test('StaticParcels setMeta(updater) should work', () => { + let updater = jest.fn(meta => ({def: 456})); + + let staticParcel = StaticParcel.fromData({ + value: 123, + meta: { + abc: 123 + } + }); + + let expectedData = { + value: 123, + meta: { + abc: 123, + def: 456 + } + }; + + let {data} = staticParcel.setMeta(updater); + + expect(updater.mock.calls[0][0]).toEqual({ + abc: 123 + }); + + expect(data).toEqual(expectedData); +}); + +test('StaticParcels update() should work', () => { + let staticParcel = StaticParcel.fromData({ + value: 123 + }); + + let expectedData = { + value: 124 + }; + + expect(staticParcel.update(ii => ii + 1).data).toEqual(expectedData); +}); + +test('StaticParcels update() should validate value updater', () => { + TestValidateValueUpdater( + expect, + (value, updater) => new StaticParcel(value).update(updater) + ); +}); + +test('StaticParcels updateDeep() should work with returned StaticParcel', () => { + let staticParcel = StaticParcel.fromData({ + value: 123, + meta: { + abc: 789 + }, + key: "z" + }); + + let expectedData = { + value: 456, + meta: { + abc: 789 + }, + key: "z" + }; + + expect(staticParcel.updateDeep(staticParcel => staticParcel.set(456)).data).toEqual(expectedData); +}); + +test('StaticParcels updateDeep() should work with returned primitive', () => { + let staticParcel = StaticParcel.fromData({ + value: 123, + meta: { + abc: 789 + }, + key: "z" + }); + + let expectedData = { + value: 456, + meta: { + abc: 789 + }, + key: "z" + }; + + expect(staticParcel.updateDeep(() => 456).data).toEqual(expectedData); +}); + +test('StaticParcels updateDeep() should work with returned parent value', () => { + let staticParcel = StaticParcel.fromData({ + value: [1,2,3], + meta: { + abc: 789 + }, + key: "z" + }); + + let expectedData = { + value: [2,3,4], + meta: { + abc: 789 + }, + child: [ + {key: "#a", child: undefined}, + {key: "#b", child: undefined}, + {key: "#c", child: undefined} + ], + key: "z" + }; + + let {data} = staticParcel.updateDeep((staticParcel) => { + return staticParcel + .children() + .map((child => child.update(value => value + 1))) + }); + + expect(data).toEqual(expectedData); +}); + +test('StaticParcels updateDeep() should work with returned parent value of different type', () => { + let staticParcel = StaticParcel.fromData({ + value: { + abc: 123, + def: 456 + }, + meta: { + abc: 789 + }, + key: "z" + }); + + let expectedData = { + value: [ + 123, + 456 + ], + meta: { + abc: 789 + }, + child: [ + {key: "#a", child: undefined}, + {key: "#b", child: undefined} + ], + key: "z" + }; + + let {data} = staticParcel.updateDeep((staticParcel) => staticParcel.toArray()); + + expect(data).toEqual(expectedData); +}); + +test('StaticParcels updateDeep() should retain childs keys', () => { + let staticParcel = StaticParcel.fromData({ + value: ["a","b","c","d"], + child: [ + {key: "#a", child: undefined}, + {key: "#b", child: undefined, meta: {abc: 123}}, + {key: "#c", child: undefined}, + {key: "#d", child: undefined} + ] + }); + + let expectedData = { + value: ["b","d"], + child: [ + {key: "#b", child: undefined, meta: {abc: 123}}, + {key: "#d", child: undefined} + ] + }; + + let {data} = staticParcel.updateDeep((staticParcel) => { + return staticParcel + .toArray() + .filter((value, key) => key % 2 === 1) + }); + + expect(data).toEqual(expectedData); +}); + +test('StaticParcels updateDeep() should throw error if non staticparcel is a child of the return value', () => { + let staticParcel = StaticParcel.fromData({ + value: [123, 456] + }); + + expect(() => staticParcel.updateDeep((staticParcel) => { + let arr = staticParcel.toArray(); + arr.push(789); + return arr; + })).toThrow('Every child value on a collection returned from a deep updater must be a StaticParcel'); +}); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js new file mode 100644 index 00000000..3a9901d4 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js @@ -0,0 +1,80 @@ +// @flow +import type {Index} from '../../types/Types'; +import type {Key} from '../../types/Types'; +import type StaticParcel from '../StaticParcel'; + +import insertAfter from '../../parcelData/insertAfter'; +import insertBefore from '../../parcelData/insertBefore'; +import pop from '../../parcelData/pop'; +import push from '../../parcelData/push'; +import shift from '../../parcelData/shift'; +import swap from '../../parcelData/swap'; +import swapNext from '../../parcelData/swapNext'; +import swapPrev from '../../parcelData/swapPrev'; +import unshift from '../../parcelData/unshift'; + +export default (_this: StaticParcel) => ({ + + insertAfter: (key: Key|Index, value: *): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + insertAfter(key, value) + ); + }, + + insertBefore: (key: Key|Index, value: *): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + insertBefore(key, value) + ); + }, + + pop: (): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + pop() + ); + }, + + push: (value: *): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + push(value) + ); + }, + + shift: (): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + shift() + ); + }, + + swap: (keyA: Key|Index, keyB: Key|Index): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + swap(keyA, keyB) + ); + }, + + swapNext: (key: Key|Index): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + swapNext(key) + ); + }, + + swapPrev: (key: Key|Index): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + swapPrev(key) + ); + }, + + unshift: (value: *): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + unshift(value) + ); + } +}); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js new file mode 100644 index 00000000..e59c030b --- /dev/null +++ b/packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js @@ -0,0 +1,72 @@ +// @flow +import type {Index} from '../../types/Types'; +import type {Key} from '../../types/Types'; +import type {ParentType} from '../../types/Types'; +import type StaticParcel from '../StaticParcel'; + +import parcelGet from '../../parcelData/get'; +import parcelHas from '../../parcelData/has'; +import parcelKeyOrIndexToKey from '../../parcelData/keyOrIndexToKey'; + +import map from 'unmutable/lib/map'; +import size from 'unmutable/lib/size'; +import toArray from 'unmutable/lib/toArray'; +import toObject from 'unmutable/lib/toObject'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +export default (_this: StaticParcel) => ({ + + has: (key: Key|Index): boolean => { + _this._prepareChildKeys(); + return parcelHas(key)(_this._parcelData); + }, + + size: (): number => { + return size()(_this._parcelData.value); + }, + + get: (key: Key|Index, notFoundValue: ?* = undefined): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + parcelGet(key, notFoundValue), + { + parent: _this + } + ); + }, + + getIn: (keyPath: Array, notFoundValue: ?* = undefined): StaticParcel => { + let staticParcel = _this; + + for(let key of keyPath) { + if(!staticParcel.isParent() || !staticParcel.has(key)) { + return _this._pipeSelf( + () => ({ + value: notFoundValue, + key: parcelKeyOrIndexToKey(key)(staticParcel.data) + }), + { + parent: _this + } + ); + } + staticParcel = staticParcel.get(key, notFoundValue); + } + return staticParcel; + }, + + children: (): ParentType => { + return pipeWith( + _this._parcelData.value, + map((value, key) => _this.get(key)) + ); + }, + + toObject: (): { [key: string]: StaticParcel } => { + return toObject()(_this.children()); + }, + + toArray: (): Array => { + return toArray()(_this.children()); + } +}); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js new file mode 100644 index 00000000..4db33cbc --- /dev/null +++ b/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js @@ -0,0 +1,59 @@ +// @flow +import type {Index} from '../../types/Types'; +import type {Key} from '../../types/Types'; +import type {StaticParcelUpdater} from '../../types/Types'; +import type {StaticParcelValueUpdater} from '../../types/Types'; +import type StaticParcel from '../StaticParcel'; + +import parcelDelete from '../../parcelData/delete'; +import parcelSetSelf from '../../parcelData/setSelf'; +import parcelUpdateIn from '../../parcelData/updateIn'; +import ValidateValueUpdater from '../../util/ValidateValueUpdater'; + +import butLast from 'unmutable/lib/butLast'; +import last from 'unmutable/lib/last'; + +export default (_this: StaticParcel) => ({ + + setIn: (keyPath: Array, value: any): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + parcelUpdateIn(keyPath, parcelSetSelf(value)) + ); + }, + + deleteIn: (keyPath: Array): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + parcelUpdateIn( + butLast()(keyPath), + parcelDelete(last()(keyPath)) + ) + ); + }, + + updateIn: (keyPath: Array, updater: StaticParcelValueUpdater): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + parcelUpdateIn( + keyPath, + (parcelData) => { + let {value} = parcelData; + let updatedValue = updater(value, _this); + ValidateValueUpdater(value, updatedValue); + return parcelSetSelf(updatedValue)(parcelData); + } + ) + ); + }, + + updateInDeep: (keyPath: Array, updater: StaticParcelUpdater): StaticParcel => { + _this._prepareChildKeys(); + return _this._pipeSelf( + parcelUpdateIn( + keyPath, + (parcelData) => _this._instanceUpdateFromData(updater)(parcelData) + ) + ); + } +}); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js new file mode 100644 index 00000000..ff1c73c6 --- /dev/null +++ b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js @@ -0,0 +1,71 @@ +// @flow +import type StaticParcel from '../StaticParcel'; +import type {ParcelDataEvaluator} from '../../types/Types'; +import type {StaticParcelValueUpdater} from '../../types/Types'; +import type {StaticParcelSetMeta} from '../../types/Types'; +import type {StaticParcelUpdater} from '../../types/Types'; + +import {DeepUpdaterNonStaticChildError} from '../../errors/Errors'; +import isParentValue from '../../parcelData/isParentValue'; +import parcelSetMeta from '../../parcelData/setMeta'; +import parcelSetSelf from '../../parcelData/setSelf'; +import parcelUpdate from '../../parcelData/update'; +import ValidateValueUpdater from '../../util/ValidateValueUpdater'; + +import clear from 'unmutable/lib/clear'; +import del from 'unmutable/lib/delete'; +import map from 'unmutable/lib/map'; +import set from 'unmutable/lib/set'; +import pipe from 'unmutable/lib/util/pipe'; +import pipeWith from 'unmutable/lib/util/pipeWith'; + +export default (_this: StaticParcel) => ({ + + setSelf: (value: *): StaticParcel => { + return _this._pipeSelf( + parcelSetSelf(value) + ); + }, + + setMeta: (partialMeta: StaticParcelSetMeta): StaticParcel => { + let meta = typeof partialMeta === "function" + ? partialMeta(_this._parcelData.meta || {}) + : partialMeta; + + return _this._pipeSelf( + parcelSetMeta(meta) + ); + }, + + update: (updater: StaticParcelValueUpdater): StaticParcel => { + let {value} = _this; + let updatedValue = updater(value, _this); + ValidateValueUpdater(value, updatedValue); + return _this.set(updatedValue); + }, + + updateDeep: (updater: StaticParcelUpdater): StaticParcel => { + let updated: any = updater(_this); + if(_this._isStaticParcel(updated)) { + return updated; + } + + if(!isParentValue(updated)) { + return _this.set(updated); + } + + return _this._pipeSelf(pipe( + set('value', clear()(updated)), + del('child'), + ...pipeWith( + updated, + map((childStaticParcel: StaticParcel, key: string|number): ParcelDataEvaluator => { + if(!_this._isStaticParcel(childStaticParcel)) { + throw DeepUpdaterNonStaticChildError(); + } + return parcelUpdate(key, () => childStaticParcel.data); + }) + ) + )); + } +}); From 91b7162d68f5cead5d3d003e31f6bd184dc0b66d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 13 Jan 2019 21:10:12 +1100 Subject: [PATCH 045/120] amend: amend usage of old modify method --- packages/react-dataparcels/src/__test__/ParcelHoc-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js index ffe93313..87fce0ce 100644 --- a/packages/react-dataparcels/src/__test__/ParcelHoc-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelHoc-test.js @@ -99,7 +99,7 @@ test('ParcelHoc config should accept a pipe function', () => { pipe: (props) => (parcel) => { expect(456).toBe(parcel.value); expect({}).toEqual(props); - return parcel.modifyValueDown(ii => ii + 1); + return parcel.modifyDown(ii => ii + 1); } }) ).props(); From 26b04c29b61338b6e7fba0a66cdcd35835f46369 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 13 Jan 2019 21:10:25 +1100 Subject: [PATCH 046/120] docs: add docs --- .../src/component/APINavigation.jsx | 1 + packages/dataparcels-docs/src/content/API.js | 2 +- .../src/docs/api/parcel/children.md | 2 +- .../src/docs/api/parcel/key.md | 2 +- .../src/docs/api/parcel/pipe.md | 8 +- .../src/docs/api/staticParcel/StaticParcel.md | 37 +++++ .../src/docs/api/staticParcel/children.md | 3 + .../src/docs/api/staticParcel/data.md | 11 ++ .../src/docs/api/staticParcel/delete.md | 4 + .../src/docs/api/staticParcel/deleteIn.md | 3 + .../src/docs/api/staticParcel/get.md | 38 +++++ .../src/docs/api/staticParcel/getIn.md | 25 ++++ .../src/docs/api/staticParcel/has.md | 5 + .../src/docs/api/staticParcel/insertAfter.md | 4 + .../src/docs/api/staticParcel/insertBefore.md | 4 + .../src/docs/api/staticParcel/isChild.md | 9 ++ .../src/docs/api/staticParcel/isElement.md | 9 ++ .../src/docs/api/staticParcel/isIndexed.md | 9 ++ .../src/docs/api/staticParcel/isParent.md | 9 ++ .../src/docs/api/staticParcel/isTopLevel.md | 7 + .../src/docs/api/staticParcel/key.md | 7 + .../src/docs/api/staticParcel/meta.md | 6 + .../src/docs/api/staticParcel/pop.md | 3 + .../src/docs/api/staticParcel/push.md | 3 + .../src/docs/api/staticParcel/set.md | 4 + .../src/docs/api/staticParcel/setIn.md | 3 + .../src/docs/api/staticParcel/setMeta.md | 3 + .../src/docs/api/staticParcel/shift.md | 3 + .../src/docs/api/staticParcel/size.md | 5 + .../src/docs/api/staticParcel/swap.md | 4 + .../src/docs/api/staticParcel/swapNext.md | 4 + .../src/docs/api/staticParcel/swapPrev.md | 4 + .../src/docs/api/staticParcel/toArray.md | 3 + .../src/docs/api/staticParcel/toConsole.md | 5 + .../src/docs/api/staticParcel/toObject.md | 3 + .../src/docs/api/staticParcel/unshift.md | 3 + .../src/docs/api/staticParcel/update.md | 4 + .../src/docs/api/staticParcel/updateDeep.md | 4 + .../src/docs/api/staticParcel/updateIn.md | 3 + .../src/docs/api/staticParcel/updateInDeep.md | 3 + .../src/docs/api/staticParcel/value.md | 7 + .../src/pages/api/StaticParcel.jsx | 134 ++++++++++++++++++ .../src/pages/deep-updaters.js | 10 ++ .../src/pages/parcel-types.md | 16 ++- .../src/pages/value-updaters.js | 10 ++ 45 files changed, 433 insertions(+), 13 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/children.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/data.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/delete.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/get.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/has.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/key.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/meta.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/pop.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/push.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/set.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/shift.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/size.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/swap.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/update.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/value.md create mode 100644 packages/dataparcels-docs/src/pages/api/StaticParcel.jsx create mode 100644 packages/dataparcels-docs/src/pages/deep-updaters.js create mode 100644 packages/dataparcels-docs/src/pages/value-updaters.js diff --git a/packages/dataparcels-docs/src/component/APINavigation.jsx b/packages/dataparcels-docs/src/component/APINavigation.jsx index da66d33f..a808c5ea 100644 --- a/packages/dataparcels-docs/src/component/APINavigation.jsx +++ b/packages/dataparcels-docs/src/component/APINavigation.jsx @@ -9,6 +9,7 @@ export default () => - ParcelHoc - ParcelBoundary - ParcelBoundaryHoc + - StaticParcel - ChangeRequest - Action ; diff --git a/packages/dataparcels-docs/src/content/API.js b/packages/dataparcels-docs/src/content/API.js index a9f414b9..596b95fe 100644 --- a/packages/dataparcels-docs/src/content/API.js +++ b/packages/dataparcels-docs/src/content/API.js @@ -59,5 +59,5 @@ export default () => } image={IconParcelBoundaryHoc} /> - See also: ChangeRequest, Action. + See also: StaticParcel, ChangeRequest, Action. ; diff --git a/packages/dataparcels-docs/src/docs/api/parcel/children.md b/packages/dataparcels-docs/src/docs/api/parcel/children.md index 16e558bc..18f8d0d5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/children.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/children.md @@ -1,3 +1,3 @@ ```flow -children(mapper?: Function): Parent // only on ParentParcels +children(mapper?: Function): ParentType // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/key.md b/packages/dataparcels-docs/src/docs/api/parcel/key.md index 85f12434..36c6ae05 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/key.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/key.md @@ -4,7 +4,7 @@ import Link from 'component/Link'; key: string ``` -Returns the Parcel's `key`. Parcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. +Returns the Parcel's `key`. Dataarcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated in the Editing Arrays example. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/pipe.md b/packages/dataparcels-docs/src/docs/api/parcel/pipe.md index cdc62acb..c38f899a 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/pipe.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/pipe.md @@ -5,8 +5,8 @@ pipe(...updaters: Function[]): Parcel The `pipe` method allows for a parcel to be passed through one or more parcel modifying functions, while retaining the ability to chain. It allows for easier function composition. ```js -let valueToString = (parcel) => parcel.modifyValueDown(value => `${value}`); -let changeToNumber = (parcel) => parcel.modifyValueUp(value => Number(value)); +let valueToString = (parcel) => parcel.modifyDown(value => `${value}`); +let changeToNumber = (parcel) => parcel.modifyUp(value => Number(value)); let parcel = new Parcel({value: 123}); parcel @@ -22,7 +22,7 @@ The above is equivalent to: ```js let parcel = new Parcel({value: 123}); parcel - .modifyValueDown(value => `${value}`) - .modifyValueUp(value => Number(value)) + .modifyDown(value => `${value}`) + .modifyUp(value => Number(value)) .value // returns "123" ``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md new file mode 100644 index 00000000..267e34a3 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md @@ -0,0 +1,37 @@ +import Link from 'component/Link'; +import Param from 'component/Param'; +import ApiPageIcon from 'component/ApiPageIcon'; +import ParcelCreateReact from 'docs/notes/ParcelCreateReact.md'; +import IconParcel from 'content/parcel.gif'; + +# StaticParcel + +{IconParcel} + +StaticParcel is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter it's data. + +These exist to be used with deep updaters, to provide a safe way to alter the shape of data in a Parcel. +Its methods a subset of Parcel's methods. + +```js +import {StaticParcel} from 'dataparcels'; +import {StaticParcel} from 'react-dataparcels'; +``` + +```flow +new StaticParcel(value?: any); +``` + +* + The value you want to put in the StaticParcel. This value will be changed immutably when change methods are called on the StaticParcel. The data type of the `value` will determine the type of StaticParcel that will be created, and will determine which methods you can use to change the value. Please read Parcel types for more info. + +```js +// creates a Parcel that contains a value of 123 +let staticParcel = new StaticParcel(123); +``` + +## Example Usage + +StaticParcels are used in a very similar way to (Immutable.js Maps and Lists)[https://facebook.github.io/immutable-js/docs/], by calling methods that return new and updated StaticParcels. + +TODO diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/children.md b/packages/dataparcels-docs/src/docs/api/staticParcel/children.md new file mode 100644 index 00000000..18f8d0d5 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/children.md @@ -0,0 +1,3 @@ +```flow +children(mapper?: Function): ParentType // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/data.md b/packages/dataparcels-docs/src/docs/api/staticParcel/data.md new file mode 100644 index 00000000..f7f5eef4 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/data.md @@ -0,0 +1,11 @@ +import Link from 'component/Link'; + +```flow +data: Object +``` + +Returns an object containing the StaticParcel's data, which includes: +* `value` - The StaticParcel's value +* `meta` - The StaticParcel's meta object +* `key` - The StaticParcel's key +* `child` - The StaticParcel's child information, which includes any `meta`, `key` and `child` data related to the `value`s children. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/delete.md b/packages/dataparcels-docs/src/docs/api/staticParcel/delete.md new file mode 100644 index 00000000..135f718c --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/delete.md @@ -0,0 +1,4 @@ +```flow +delete(): void +delete(key: string|number): void // only on ParentParcels, will delete a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md b/packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md new file mode 100644 index 00000000..ca08ddb9 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md @@ -0,0 +1,3 @@ +```flow +deleteIn(keyPath: Array): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/get.md b/packages/dataparcels-docs/src/docs/api/staticParcel/get.md new file mode 100644 index 00000000..02e0085e --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/get.md @@ -0,0 +1,38 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + +```flow +get(key: string|number): StaticParcel // only on ParentParcels +get(key: string|number, notSetValue: any): StaticParcel // only on ParentParcels +``` + +Returns a StaticParcel containing the value associated with the provided key / index. +If the key / index doesn't exist, a StaticParcel with a value of `notSetValue` will be returned. +If `notSetValue` is not provided then a StaticParcel with a value of + `undefined` will be returned. + +```js +let value = { + abc: 123, + def: 456 +}; +let staticParcel = new StaticParcel(value); +staticParcel.get('abc').value; // returns 123 +staticParcel.get('xyz').value; // returns undefined +staticParcel.get('xyz', 789).value; // returns 789 +``` + +#### get() with indexed values + +When called on a StaticParcel with an indexed value, such as an array, `get()` can accept an `index` or a `key`. +- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. +- `key` (string) is used to get a specific value by its unique key within the StaticParcel. + + + +```js +let value = ['abc', 'def', 'ghi']; +let staticParcel = new StaticParcel(value); +staticParcel.get(0).value; // returns 'abc' +staticParcel.get(-1).value; // returns 'ghi' +staticParcel.get('#a').value; // returns 'abc' +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md b/packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md new file mode 100644 index 00000000..f45a0a79 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md @@ -0,0 +1,25 @@ +```flow +getIn(keyPath: Array): Parcel // only on ParentParcels +getIn(keyPath: Array, notSetValue: any): Parcel // only on ParentParcels +``` + +Returns a Parcel containing the value associated with the provided key path. +If the key path doesn't exist, a Parcel with a value of `notSetValue` will be returned. +If `notSetValue` is not provided then a Parcel with a value of + `undefined` will be returned. + +```js +let value = { + a: { + b: 123 + } +}; +let parcel = new Parcel({value}); +parcel.get(['a','b']).value; // returns 123 +parcel.get(['a','z']).value; // returns undefined +parcel.get(['a','z'], 789).value; // returns 789 +``` + +#### getIn() with indexed values + +... diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/has.md b/packages/dataparcels-docs/src/docs/api/staticParcel/has.md new file mode 100644 index 00000000..86e1e119 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/has.md @@ -0,0 +1,5 @@ +```flow +has(key: string|number): boolean // only on ParentParcels +``` + +Returns true if the parcel has a child at the provided `key` or `index`, or false otherwise. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md b/packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md new file mode 100644 index 00000000..d6b3369a --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md @@ -0,0 +1,4 @@ +```flow +insertAfter(value: *): void // only on ElementParcels, will insert after self +insertAfter(key: string|number, value: *): void // only on IndexedParcels, will insert after child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md b/packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md new file mode 100644 index 00000000..5e788267 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md @@ -0,0 +1,4 @@ +```flow +insertBefore(value: *): void // only on ElementParcels, will insert before self +insertBefore(key: string|number, value: *): void // only on IndexedParcels, will insert before child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md new file mode 100644 index 00000000..b8f5ca63 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isChild(): boolean +``` + +Returns true if the StaticParcels is a child parcel. Read Parcel types for more info. + +When a StaticParcel is a child parcel, it allows the use of child methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md new file mode 100644 index 00000000..9c883bc1 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isElement(): boolean +``` + +Returns true if the StaticParcel is an element parcel. Read Parcel types for more info. + +When a StaticParcel is an element parcel, it allows the use of element methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md new file mode 100644 index 00000000..408b5036 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isIndexed(): boolean +``` + +Returns true if the StaticParcel is an indexed parcel. Read Parcel types for more info. + +When a StaticParcel is an indexed parcel, it allows the use of indexed methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md new file mode 100644 index 00000000..19807099 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isParent(): boolean +``` + +Returns true if the StaticParcel is a parent parcel. Read Parcel types for more info. + +When a StaticParcel is a parent parcel, it allows the use of parent methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md new file mode 100644 index 00000000..d7bb94ba --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md @@ -0,0 +1,7 @@ +import Link from 'component/Link'; + +```flow +isTopLevel(): boolean +``` + +Returns true if the StaticParcel is a top level parcel. Read Parcel types for more info. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/key.md b/packages/dataparcels-docs/src/docs/api/staticParcel/key.md new file mode 100644 index 00000000..824e31a9 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/key.md @@ -0,0 +1,7 @@ +import Link from 'component/Link'; + +```flow +key: string +``` + +Returns the StaticParcel's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/meta.md b/packages/dataparcels-docs/src/docs/api/staticParcel/meta.md new file mode 100644 index 00000000..a2dfeb30 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/meta.md @@ -0,0 +1,6 @@ +import ParcelMeta from 'docs/notes/ParcelMeta.md'; + +```flow +meta: Object +``` +Returns an object containing the StaticParcels's meta data. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/pop.md b/packages/dataparcels-docs/src/docs/api/staticParcel/pop.md new file mode 100644 index 00000000..daca3ead --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/pop.md @@ -0,0 +1,3 @@ +```flow +pop(): void // only on IndexedParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/push.md b/packages/dataparcels-docs/src/docs/api/staticParcel/push.md new file mode 100644 index 00000000..c61a8ed4 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/push.md @@ -0,0 +1,3 @@ +```flow +push(value: *): void // only on IndexedParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/set.md b/packages/dataparcels-docs/src/docs/api/staticParcel/set.md new file mode 100644 index 00000000..9db7e179 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/set.md @@ -0,0 +1,4 @@ +```flow +set(value: *): void +set(key: string|number, value: *): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md b/packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md new file mode 100644 index 00000000..dfee5742 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md @@ -0,0 +1,3 @@ +```flow +setIn(keyPath: Array, value: *): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md b/packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md new file mode 100644 index 00000000..662f84bb --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md @@ -0,0 +1,3 @@ +```flow +setMeta(partialMeta: Object): void +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/shift.md b/packages/dataparcels-docs/src/docs/api/staticParcel/shift.md new file mode 100644 index 00000000..143be743 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/shift.md @@ -0,0 +1,3 @@ +```flow +shift(): void // only on IndexedParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/size.md b/packages/dataparcels-docs/src/docs/api/staticParcel/size.md new file mode 100644 index 00000000..3b56d840 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/size.md @@ -0,0 +1,5 @@ +```flow +size(): number // only on ParentParcels +``` + +Returns the number of children this parcel has. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swap.md b/packages/dataparcels-docs/src/docs/api/staticParcel/swap.md new file mode 100644 index 00000000..853d6e4d --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/swap.md @@ -0,0 +1,4 @@ +```flow +swap(key: string|number): void // only on ElementParcels, will swap with sibling +swap(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will swap children +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md b/packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md new file mode 100644 index 00000000..c18f553a --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md @@ -0,0 +1,4 @@ +```flow +swapNext(): void // only on ElementParcels, will swap with next sibling +swapNext(key: string|number): void // only on IndexedParcels, will swap child with next child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md b/packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md new file mode 100644 index 00000000..61155893 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md @@ -0,0 +1,4 @@ +```flow +swapPrev(): void // only on ElementParcels, will swap with previous sibling +swapPrev(key: string|number): void // only on IndexedParcels, will swap child with previous child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md b/packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md new file mode 100644 index 00000000..e7b262b0 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md @@ -0,0 +1,3 @@ +```flow +toArray(mapper?: Function): Array // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md b/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md new file mode 100644 index 00000000..93157220 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md @@ -0,0 +1,5 @@ +```flow +toConsole(): void +``` + +Outputs the StaticParcel's data to the console. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md b/packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md new file mode 100644 index 00000000..00bab19b --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md @@ -0,0 +1,3 @@ +```flow +toObject(mapper?: Function): {[key: string]: Parcel} // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md b/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md new file mode 100644 index 00000000..a896e692 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md @@ -0,0 +1,3 @@ +```flow +unshift(value: *): void // only on IndexedParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/update.md b/packages/dataparcels-docs/src/docs/api/staticParcel/update.md new file mode 100644 index 00000000..def55433 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/update.md @@ -0,0 +1,4 @@ +```flow +update(updater: Function): void +update(key: string|number, updater: Function): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md new file mode 100644 index 00000000..d5e06ae4 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md @@ -0,0 +1,4 @@ +```flow +updateDeep(updater: Function): void +updateDeep(key: string|number, updater: Function): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md new file mode 100644 index 00000000..0dadd4ff --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md @@ -0,0 +1,3 @@ +```flow +updateIn(keyPath: Array, updater: Function): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md new file mode 100644 index 00000000..b7a986df --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md @@ -0,0 +1,3 @@ +```flow +updateInDeep(keyPath: Array, updater: Function): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/value.md b/packages/dataparcels-docs/src/docs/api/staticParcel/value.md new file mode 100644 index 00000000..b976c555 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/value.md @@ -0,0 +1,7 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + +```flow +value: any +``` + +Returns the StaticParcel's value. diff --git a/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx b/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx new file mode 100644 index 00000000..e033f5c7 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx @@ -0,0 +1,134 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import ApiPage from 'component/ApiPage'; +import Markdown_StaticParcel from 'docs/api/staticParcel/StaticParcel.md'; +import Markdown_value from 'docs/api/staticParcel/value.md'; +import Markdown_meta from 'docs/api/staticParcel/meta.md'; +import Markdown_data from 'docs/api/staticParcel/data.md'; +import Markdown_key from 'docs/api/staticParcel/key.md'; +import Markdown_get from 'docs/api/staticParcel/get.md'; +import Markdown_getIn from 'docs/api/staticParcel/getIn.md'; +import Markdown_children from 'docs/api/staticParcel/children.md'; +import Markdown_toObject from 'docs/api/staticParcel/toObject.md'; +import Markdown_toArray from 'docs/api/staticParcel/toArray.md'; +import Markdown_has from 'docs/api/staticParcel/has.md'; +import Markdown_size from 'docs/api/staticParcel/size.md'; +import Markdown_set from 'docs/api/staticParcel/set.md'; +import Markdown_setIn from 'docs/api/staticParcel/setIn.md'; +import Markdown_update from 'docs/api/staticParcel/update.md'; +import Markdown_updateDeep from 'docs/api/staticParcel/updateDeep.md'; +import Markdown_updateIn from 'docs/api/staticParcel/updateIn.md'; +import Markdown_updateInDeep from 'docs/api/staticParcel/updateInDeep.md'; +import Markdown_delete from 'docs/api/staticParcel/delete.md'; +import Markdown_deleteIn from 'docs/api/staticParcel/deleteIn.md'; +import Markdown_insertAfter from 'docs/api/staticParcel/insertAfter.md'; +import Markdown_insertBefore from 'docs/api/staticParcel/insertBefore.md'; +import Markdown_pop from 'docs/api/staticParcel/pop.md'; +import Markdown_push from 'docs/api/staticParcel/push.md'; +import Markdown_shift from 'docs/api/staticParcel/shift.md'; +import Markdown_swap from 'docs/api/staticParcel/swap.md'; +import Markdown_swapNext from 'docs/api/staticParcel/swapNext.md'; +import Markdown_swapPrev from 'docs/api/staticParcel/swapPrev.md'; +import Markdown_unshift from 'docs/api/staticParcel/unshift.md'; +import Markdown_setMeta from 'docs/api/staticParcel/setMeta.md'; +import Markdown_isChild from 'docs/api/staticParcel/isChild.md'; +import Markdown_isElement from 'docs/api/staticParcel/isElement.md'; +import Markdown_isIndexed from 'docs/api/staticParcel/isIndexed.md'; +import Markdown_isParent from 'docs/api/staticParcel/isParent.md'; +import Markdown_isTopLevel from 'docs/api/staticParcel/isTopLevel.md'; +import Markdown_toConsole from 'docs/api/staticParcel/toConsole.md'; + +const md = { + _desc: Markdown_StaticParcel, + value: Markdown_value, + meta: Markdown_meta, + data: Markdown_data, + key: Markdown_key, + get: Markdown_get, + getIn: Markdown_getIn, + children: Markdown_children, + toObject: Markdown_toObject, + toArray: Markdown_toArray, + has: Markdown_has, + size: Markdown_size, + set: Markdown_set, + setIn: Markdown_setIn, + update: Markdown_update, + updateDeep: Markdown_updateDeep, + updateIn: Markdown_updateIn, + updateInDeep: Markdown_updateInDeep, + delete: Markdown_delete, + deleteIn: Markdown_deleteIn, + insertAfter: Markdown_insertAfter, + insertBefore: Markdown_insertBefore, + pop: Markdown_pop, + push: Markdown_push, + shift: Markdown_shift, + swap: Markdown_swap, + swapNext: Markdown_swapNext, + swapPrev: Markdown_swapPrev, + unshift: Markdown_unshift, + setMeta: Markdown_setMeta, + isChild: Markdown_isChild, + isElement: Markdown_isElement, + isIndexed: Markdown_isIndexed, + isParent: Markdown_isParent, + isTopLevel: Markdown_isTopLevel, + toConsole: Markdown_toConsole +} + +const api = ` +# Properties +value +meta +data +key + +# Parent methods +get() +getIn() +children() +toObject() +toArray() +has() +size() + +# Set methods +set() +setIn() +delete() +deleteIn() +update() +updateDeep() +updateIn() +updateInDeep() + +# Indexed & element change methods +insertAfter() +insertBefore() +push() +pop() +shift() +swap() +swapNext() +swapPrev() +unshift() + +# Type methods +isChild() +isElement() +isIndexed() +isParent() +isTopLevel() + +# Debug methods +toConsole() + +`; + +export default () => ; diff --git a/packages/dataparcels-docs/src/pages/deep-updaters.js b/packages/dataparcels-docs/src/pages/deep-updaters.js new file mode 100644 index 00000000..2dc96278 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/deep-updaters.js @@ -0,0 +1,10 @@ +// @flow +import React from 'react'; +import {Box, CenteredLanding, Text} from 'dcme-style'; + +export default () => + Deep Updaters} + bottom={() => This doesn't exist yet. These docs are still very much under construction.} + /> +; diff --git a/packages/dataparcels-docs/src/pages/parcel-types.md b/packages/dataparcels-docs/src/pages/parcel-types.md index b1f49e38..7a33333e 100644 --- a/packages/dataparcels-docs/src/pages/parcel-types.md +++ b/packages/dataparcels-docs/src/pages/parcel-types.md @@ -8,6 +8,8 @@ Any parcel can be more than one type at once. You can check a parcel's type by using their type methods. +Parcel's can contain any type of value you like, but only a subset of these values will give you the ability to edit child values. A parcel with the ability to edit child values will be of type ParentParcel. + - ParentParcel - ChildParcel - IndexedParcel @@ -16,7 +18,7 @@ You can check a parcel's type by using their branch methods and parent methods. ### ChildParcel -A parcel is a child parcel if it contains a child value from a parent parcel. Child parcels are created using branching methods. +A parcel is a `ChildParcel` if it contains a child value from a parent parcel. Child parcels are created using branching methods. When a parcel is a child parcel, it allows the use of child methods. ### IndexedParcel -A parcel is an indexed parcel if it contains an indexed data type, such as an array or an Immutable.js List. IndexedParcels are also always parent parcels. +A parcel is an `IndexedParcel` if it contains an indexed data type, such as an array or an Immutable.js List. IndexedParcels are also always parent parcels. When a parcel is an indexed parcel, it allows the use of indexed methods. ### ElementParcel -A parcel is an element parcel if it contains the child value of an indexed parcel. +A parcel is an `ElementParcel` if it contains the child value of an indexed parcel. When a parcel is an element parcel, it allows the use of element methods. ### TopLevelParcel -A parcel is a top level parcel if it is not a child parcel. Examples: the parcel provided by a ParcelHoc, or a parcel created with `new Parcel`. +A parcel is a `TopLevelParcel` if it is not a child parcel. Examples: the parcel provided by a ParcelHoc, or a parcel created with `new Parcel`. diff --git a/packages/dataparcels-docs/src/pages/value-updaters.js b/packages/dataparcels-docs/src/pages/value-updaters.js new file mode 100644 index 00000000..45398ae4 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/value-updaters.js @@ -0,0 +1,10 @@ +// @flow +import React from 'react'; +import {Box, CenteredLanding, Text} from 'dcme-style'; + +export default () => + Value Updaters} + bottom={() => This doesn't exist yet. These docs are still very much under construction.} + /> +; From 9c85074c9fc8eca32b470a561c80b2f2fbc13f29 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 11:49:26 +1100 Subject: [PATCH 047/120] test: add sanity test --- .../src/parcel/__test__/ModifyMethods-test.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index dc1dfaed..1c61a839 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -280,3 +280,23 @@ test('Parcel.initialMeta() should merge', () => { b: 3 }); }); + +test('Sanity check: A big strange test of a big strange chain of deep updatery stuff', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(value => value + "333"); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }) + .modifyDownDeep(staticParcel => staticParcel.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) + .modifyUpDeep(staticParcel => staticParcel.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) + .get(0) // 2. get the first element (value: 3) + .modifyDown(value => value + "") // 3. cast number to string value: "3") + .modifyUp(value => parseInt(value, 10)) // 5. cast string to number (value will be: 3333) + .update(updater); // 4. make a change to the data, append three threes (value will be: "3333") + + expect(updater.mock.calls[0][0]).toBe("3"); + expect(handleChange.mock.calls[0][0].value).toEqual([1,2,3333]); +}); From 487506a9b8b7118cb1b885609f134672fd942f19 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 11:49:41 +1100 Subject: [PATCH 048/120] amend: fix lint --- packages/dataparcels/src/parcelData/updateIn.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dataparcels/src/parcelData/updateIn.js b/packages/dataparcels/src/parcelData/updateIn.js index ecbee149..eecea8ed 100644 --- a/packages/dataparcels/src/parcelData/updateIn.js +++ b/packages/dataparcels/src/parcelData/updateIn.js @@ -1,7 +1,6 @@ // @flow import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; -import type {ParcelData} from '../types/Types'; import type {ParcelDataEvaluator} from '../types/Types'; import update from './update'; From 166085974e1a2837da8f887deaa3145c4921c0f6 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 11:49:58 +1100 Subject: [PATCH 049/120] build: commit new lock file --- yarn.lock | 82 ++++++------------------------------------------------- 1 file changed, 8 insertions(+), 74 deletions(-) diff --git a/yarn.lock b/yarn.lock index ed315301..cc4e0997 100644 --- a/yarn.lock +++ b/yarn.lock @@ -607,12 +607,6 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@2.6.1, async@^2.0.1, async@^2.1.2, async@^2.1.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - dependencies: - lodash "^4.17.10" - async@^0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -621,6 +615,12 @@ async@^1.3.0, async@^1.4.0, async@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" +async@^2.0.1, async@^2.1.2, async@^2.1.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + dependencies: + lodash "^4.17.10" + async@~0.2.6: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" @@ -2589,10 +2589,6 @@ command-join@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/command-join/-/command-join-2.0.0.tgz#52e8b984f4872d952ff1bdc8b98397d27c7144cf" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - commander@2.9.0, commander@2.9.x: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -4421,25 +4417,6 @@ filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" -filename-reserved-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" - -filenamify-url@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/filenamify-url/-/filenamify-url-1.0.0.tgz#b32bd81319ef5863b73078bed50f46a4f7975f50" - dependencies: - filenamify "^1.0.0" - humanize-url "^1.0.0" - -filenamify@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5" - dependencies: - filename-reserved-regex "^1.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - fileset@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" @@ -4726,14 +4703,6 @@ fs-extra@^4.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -5130,18 +5099,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -gh-pages@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-1.2.0.tgz#1acb92801078f7c038a167f447221d1496ccfbee" - dependencies: - async "2.6.1" - commander "2.15.1" - filenamify-url "^1.0.0" - fs-extra "^5.0.0" - globby "^6.1.0" - graceful-fs "4.1.11" - rimraf "^2.6.2" - git-raw-commits@^1.3.0, git-raw-commits@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-1.3.6.tgz#27c35a32a67777c1ecd412a239a6c19d71b95aff" @@ -5381,7 +5338,7 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@4.1.11, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -5829,13 +5786,6 @@ hullabaloo-config-manager@^1.1.0: resolve-from "^3.0.0" safe-buffer "^5.0.1" -humanize-url@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-1.0.1.tgz#f4ab99e0d288174ca4e1e50407c55fbae464efff" - dependencies: - normalize-url "^1.0.0" - strip-url-auth "^1.0.0" - iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -8333,7 +8283,7 @@ normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" -normalize-url@^1.0.0, normalize-url@^1.4.0: +normalize-url@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" dependencies: @@ -11649,16 +11599,6 @@ strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0. version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -strip-outer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - dependencies: - escape-string-regexp "^1.0.2" - -strip-url-auth@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-url-auth/-/strip-url-auth-1.0.1.tgz#22b0fa3a41385b33be3f331551bbb837fa0cd7ae" - strong-log-transformer@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-1.0.6.tgz#f7fb93758a69a571140181277eea0c2eb1301fa3" @@ -12062,12 +12002,6 @@ trim-off-newlines@^1.0.0, trim-off-newlines@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - dependencies: - escape-string-regexp "^1.0.2" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" From 072106de7006f4d6874f2df7d0610832bbb8d556 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 13:10:37 +1100 Subject: [PATCH 050/120] amend: rename updater methods --- .../src/docs/api/parcel/modifyDown.md | 1 + .../src/docs/api/parcel/modifyShapeDown.md | 3 ++ .../src/docs/api/parcel/modifyShapeUp.md | 3 ++ .../src/docs/api/parcel/updateDeep.md | 4 -- .../src/docs/api/parcel/updateInDeep.md | 3 -- .../src/docs/api/parcel/updateInShape.md | 3 ++ .../src/docs/api/parcel/updateShape.md | 4 ++ .../docs/api/staticParcel/modifyShapeDown.md | 3 ++ .../docs/api/staticParcel/modifyShapeUp.md | 3 ++ .../src/docs/api/staticParcel/updateDeep.md | 4 -- .../src/docs/api/staticParcel/updateInDeep.md | 3 -- .../src/docs/api/staticParcel/updateShape.md | 4 ++ .../docs/api/staticParcel/updateShapeIn.md | 3 ++ .../dataparcels-docs/src/pages/api/Parcel.jsx | 54 ++++++++++--------- .../src/pages/api/StaticParcel.jsx | 12 ++--- packages/dataparcels/src/parcel/Parcel.js | 10 ++-- .../src/parcel/__test__/ModifyMethods-test.js | 20 +++---- .../__test__/ParcelChangeMethods-test.js | 4 +- .../__test__/ParentChangeMethods-test.js | 8 +-- .../src/parcel/methods/ModifyMethods.js | 8 +-- .../src/parcel/methods/ParentChangeMethods.js | 12 ++--- .../src/staticParcel/StaticParcel.js | 10 ++-- .../__test__/StaticParentSetMethods-test.js | 8 +-- .../__test__/StaticSetMethods-test.js | 24 ++++----- .../methods/StaticParentSetMethods.js | 2 +- .../staticParcel/methods/StaticSetMethods.js | 2 +- 26 files changed, 116 insertions(+), 99 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateShape.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md create mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md index 28dbb598..1bbab5f1 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md @@ -1,3 +1,4 @@ ```flow modifyDown(updater: Function): Parcel ``` + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md new file mode 100644 index 00000000..0a8057a8 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): Parcel +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md new file mode 100644 index 00000000..0a8057a8 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): Parcel +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md b/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md deleted file mode 100644 index d5e06ae4..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateDeep.md +++ /dev/null @@ -1,4 +0,0 @@ -```flow -updateDeep(updater: Function): void -updateDeep(key: string|number, updater: Function): void // only on ParentParcels, will set a child -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md b/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md deleted file mode 100644 index b7a986df..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateInDeep.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -updateInDeep(keyPath: Array, updater: Function): void // only on ParentParcels -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md b/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md new file mode 100644 index 00000000..856d5dbc --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md @@ -0,0 +1,3 @@ +```flow +updateInShape(keyPath: Array, updater: Function): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md b/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md new file mode 100644 index 00000000..c28d5b64 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md @@ -0,0 +1,4 @@ +```flow +updateShape(updater: Function): void +updateShape(key: string|number, updater: Function): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md new file mode 100644 index 00000000..eb7160d6 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): StaticParcel +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md new file mode 100644 index 00000000..eb7160d6 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): StaticParcel +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md deleted file mode 100644 index d5e06ae4..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/updateDeep.md +++ /dev/null @@ -1,4 +0,0 @@ -```flow -updateDeep(updater: Function): void -updateDeep(key: string|number, updater: Function): void // only on ParentParcels, will set a child -``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md deleted file mode 100644 index b7a986df..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/updateInDeep.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -updateInDeep(keyPath: Array, updater: Function): void // only on ParentParcels -``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md new file mode 100644 index 00000000..c28d5b64 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md @@ -0,0 +1,4 @@ +```flow +updateShape(updater: Function): void +updateShape(key: string|number, updater: Function): void // only on ParentParcels, will set a child +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md b/packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md new file mode 100644 index 00000000..50aa9bcc --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md @@ -0,0 +1,3 @@ +```flow +updateShapeIn(keyPath: Array, updater: Function): void // only on ParentParcels +``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 78507ae1..443a9c54 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -26,9 +26,9 @@ import Markdown_onChangeDOM from 'docs/api/parcel/onChangeDOM.md'; import Markdown_set from 'docs/api/parcel/set.md'; import Markdown_setIn from 'docs/api/parcel/setIn.md'; import Markdown_update from 'docs/api/parcel/update.md'; -import Markdown_updateDeep from 'docs/api/parcel/updateDeep.md'; +import Markdown_updateShape from 'docs/api/parcel/updateShape.md'; import Markdown_updateIn from 'docs/api/parcel/updateIn.md'; -import Markdown_updateInDeep from 'docs/api/parcel/updateInDeep.md'; +import Markdown_updateInShape from 'docs/api/parcel/updateInShape.md'; import Markdown_delete from 'docs/api/parcel/delete.md'; import Markdown_deleteIn from 'docs/api/parcel/deleteIn.md'; import Markdown_insertAfter from 'docs/api/parcel/insertAfter.md'; @@ -47,6 +47,8 @@ import Markdown_batch from 'docs/api/parcel/batch.md'; import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; import Markdown_modifyDown from 'docs/api/parcel/modifyDown.md'; import Markdown_modifyUp from 'docs/api/parcel/modifyUp.md'; +import Markdown_modifyShapeDown from 'docs/api/parcel/modifyShapeDown.md'; +import Markdown_modifyShapeUp from 'docs/api/parcel/modifyShapeUp.md'; import Markdown_modifyChange from 'docs/api/parcel/modifyChange.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; import Markdown_isChild from 'docs/api/parcel/isChild.md'; @@ -86,9 +88,9 @@ const md = { set: Markdown_set, setIn: Markdown_setIn, update: Markdown_update, - updateDeep: Markdown_updateDeep, + updateShape: Markdown_updateShape, updateIn: Markdown_updateIn, - updateInDeep: Markdown_updateInDeep, + updateInShape: Markdown_updateInShape, delete: Markdown_delete, deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, @@ -107,6 +109,8 @@ const md = { batchAndReturn: Markdown_batchAndReturn, modifyDown: Markdown_modifyDown, modifyUp: Markdown_modifyUp, + modifyShapeDown: Markdown_modifyShapeDown, + modifyShapeUp: Markdown_modifyShapeUp, modifyChange: Markdown_modifyChange, initialMeta: Markdown_initialMeta, isChild: Markdown_isChild, @@ -134,6 +138,8 @@ path # Spread methods spread() spreadDOM() +onChange() +onChangeDOM() # Branch methods get() @@ -142,25 +148,19 @@ children() toObject() toArray() -# Parent methods -has() -size() - # Child methods isFirst() isLast() # Change methods -onChange() -onChangeDOM() set() setIn() delete() deleteIn() update() -updateDeep() +updateShape() updateIn() -updateInDeep() +updateShapeIn() # Indexed & element change methods insertAfter() @@ -173,18 +173,9 @@ swapNext() swapPrev() unshift() -# Advanced change methods -setMeta() -setChangeRequestMeta() -dispatch() -batch() -batchAndReturn() - -# Modify methods -modifyDown() -modifyUp() -modifyChange() -initialMeta() +# Parent methods +has() +size() # Type methods isChild() @@ -193,7 +184,20 @@ isIndexed() isParent() isTopLevel() -# Status methods +# Modify methods +modifyDown() +modifyUp() +modifyShapeDown() +modifyShapeUp() +modifyChange() +initialMeta() + +# Advanced change methods +setMeta() +setChangeRequestMeta() +dispatch() +batch() +batchAndReturn() hasDispatched() # Side-effect methods diff --git a/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx b/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx index e033f5c7..85e7e2b3 100644 --- a/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx @@ -17,9 +17,9 @@ import Markdown_size from 'docs/api/staticParcel/size.md'; import Markdown_set from 'docs/api/staticParcel/set.md'; import Markdown_setIn from 'docs/api/staticParcel/setIn.md'; import Markdown_update from 'docs/api/staticParcel/update.md'; -import Markdown_updateDeep from 'docs/api/staticParcel/updateDeep.md'; +import Markdown_updateShape from 'docs/api/staticParcel/updateShape.md'; import Markdown_updateIn from 'docs/api/staticParcel/updateIn.md'; -import Markdown_updateInDeep from 'docs/api/staticParcel/updateInDeep.md'; +import Markdown_updateShapeIn from 'docs/api/staticParcel/updateShapeIn.md'; import Markdown_delete from 'docs/api/staticParcel/delete.md'; import Markdown_deleteIn from 'docs/api/staticParcel/deleteIn.md'; import Markdown_insertAfter from 'docs/api/staticParcel/insertAfter.md'; @@ -55,9 +55,9 @@ const md = { set: Markdown_set, setIn: Markdown_setIn, update: Markdown_update, - updateDeep: Markdown_updateDeep, + updateShape: Markdown_updateShape, updateIn: Markdown_updateIn, - updateInDeep: Markdown_updateInDeep, + updateShapeIn: Markdown_updateShapeIn, delete: Markdown_delete, deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, @@ -100,9 +100,9 @@ setIn() delete() deleteIn() update() -updateDeep() +updateShape() updateIn() -updateInDeep() +updateShapeIn() # Indexed & element change methods insertAfter() diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index ea9fb195..4f00f62c 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -286,13 +286,13 @@ export default class Parcel { ["1"]: (updater: ParcelValueUpdater) => this._methods.updateSelf(updater), ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); - updateDeep = overload({ + updateShape = overload({ ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfDeep(updater), - ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateDeep(key, updater) + ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateShape(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateInDeep = (keyPath: Array, updater: StaticParcelUpdater) => this._methods.updateInDeep(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: StaticParcelUpdater) => this._methods.updateShapeIn(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) @@ -335,8 +335,8 @@ export default class Parcel { // Modify methods modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); modifyUp = (updater: Function): Parcel => this._methods.modifyUp(updater); - modifyDownDeep = (updater: Function): Parcel => this._methods.modifyDownDeep(updater); - modifyUpDeep = (updater: Function): Parcel => this._methods.modifyUpDeep(updater); + modifyShapeDown = (updater: Function): Parcel => this._methods.modifyShapeDown(updater); + modifyShapeUp = (updater: Function): Parcel => this._methods.modifyShapeUp(updater); modifyChange = (batcher: ParcelBatcher): Parcel => this._methods.modifyChange(batcher); initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 1c61a839..59969638 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -156,7 +156,7 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { }); }); -test('Parcel.modifyDownDeep() should be called with static parcel and return with no change', () => { +test('Parcel.modifyShapeDown() should be called with static parcel and return with no change', () => { let handleChange = jest.fn(); let updater = jest.fn(staticParcel => staticParcel); @@ -167,7 +167,7 @@ test('Parcel.modifyDownDeep() should be called with static parcel and return wit }); let {value} = parcel - .modifyDownDeep(updater) + .modifyShapeDown(updater) .data; let expectedValue = [1,2,3]; @@ -177,7 +177,7 @@ test('Parcel.modifyDownDeep() should be called with static parcel and return wit expect(updater.mock.calls[0][0].data.value).toEqual(expectedValue); }); -test('Parcel.modifyDownDeep() should modify value', () => { +test('Parcel.modifyShapeDown() should modify value', () => { let handleChange = jest.fn(); let updater = jest.fn(staticParcel => staticParcel.push(4)); @@ -187,7 +187,7 @@ test('Parcel.modifyDownDeep() should modify value', () => { value: [1,2,3] }); - let parcelWithModifier = parcel.modifyDownDeep(updater); + let parcelWithModifier = parcel.modifyShapeDown(updater); let {value} = parcelWithModifier.data; parcelWithModifier.push(5); @@ -195,7 +195,7 @@ test('Parcel.modifyDownDeep() should modify value', () => { expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); }); -test('Parcel.modifyUpDeep() should be called with static parcel and return with no change', () => { +test('Parcel.modifyShapeUp() should be called with static parcel and return with no change', () => { let handleChange = jest.fn(); let updater = jest.fn(staticParcel => staticParcel); @@ -205,7 +205,7 @@ test('Parcel.modifyUpDeep() should be called with static parcel and return with value: 123 }); - let parcelWithModifier = parcel.modifyUpDeep(updater); + let parcelWithModifier = parcel.modifyShapeUp(updater); let {value} = parcelWithModifier.data; expect(value).toEqual(123); @@ -217,7 +217,7 @@ test('Parcel.modifyUpDeep() should be called with static parcel and return with expect(updater.mock.calls[0][0].data.value).toEqual(456); }); -test('Parcel.modifyUpDeep() should modify value', () => { +test('Parcel.modifyShapeUp() should modify value', () => { let handleChange = jest.fn(); let updater = jest.fn(staticParcel => staticParcel.push(5)); @@ -227,7 +227,7 @@ test('Parcel.modifyUpDeep() should modify value', () => { value: [1,2,3] }); - let parcelWithModifier = parcel.modifyUpDeep(updater); + let parcelWithModifier = parcel.modifyShapeUp(updater); let {value} = parcelWithModifier.data; expect(value).toEqual([1,2,3]); @@ -290,8 +290,8 @@ test('Sanity check: A big strange test of a big strange chain of deep updatery s handleChange, value: [1,2,3] }) - .modifyDownDeep(staticParcel => staticParcel.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) - .modifyUpDeep(staticParcel => staticParcel.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) + .modifyShapeDown(staticParcel => staticParcel.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) + .modifyShapeUp(staticParcel => staticParcel.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) .get(0) // 2. get the first element (value: 3) .modifyDown(value => value + "") // 3. cast number to string value: "3") .modifyUp(value => parseInt(value, 10)) // 5. cast string to number (value will be: 3333) diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 6b907af7..217de877 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -91,7 +91,7 @@ test('Parcel.update() should validate value updater', () => { ); }); -test('Parcel.updateDeep() should call the Parcels handleChange function with the new parcelData', () => { +test('Parcel.updateShape() should call the Parcels handleChange function with the new parcelData', () => { let handleChange = jest.fn(); let updater = jest.fn(staticParcel => staticParcel.push(4)); @@ -99,7 +99,7 @@ test('Parcel.updateDeep() should call the Parcels handleChange function with the new Parcel({ value: [1,2,3], handleChange - }).updateDeep(updater); + }).updateShape(updater); expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); diff --git a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js index e2df00e6..00f3df8a 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js @@ -36,7 +36,7 @@ test('ParentParcel.update(key) should call the Parcels handleChange function wit }); }); -test('ParentParcel.updateDeep(key) should call the Parcels handleChange function with the new parcelData', () => { +test('ParentParcel.updateShape(key) should call the Parcels handleChange function with the new parcelData', () => { let updater = jest.fn(staticParcel => staticParcel.push(4)); let handleChange = jest.fn(); @@ -45,7 +45,7 @@ test('ParentParcel.updateDeep(key) should call the Parcels handleChange function abc: [1,2,3] }, handleChange - }).updateDeep("abc", updater); + }).updateShape("abc", updater); expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ @@ -110,7 +110,7 @@ test('ParentParcel.updateIn(keyPath) should call the Parcels handleChange functi }); }); -test('ParentParcel.updateInDeep(keyPath) should call the Parcels handleChange function with the new parcelData', () => { +test('ParentParcel.updateShapeIn(keyPath) should call the Parcels handleChange function with the new parcelData', () => { let updater = jest.fn(staticParcel => staticParcel.push(4)); let handleChange = jest.fn(); @@ -121,7 +121,7 @@ test('ParentParcel.updateInDeep(keyPath) should call the Parcels handleChange fu } }, handleChange - }).updateInDeep(["abc", "def"], updater); + }).updateShapeIn(["abc", "def"], updater); expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 929c40e2..5ed01e1d 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -74,8 +74,8 @@ export default (_this: Parcel): Object => ({ }); }, - modifyDownDeep: (updater: Function): Parcel => { - Types(`modifyDownDeep()`, `updater`, `function`)(updater); + modifyShapeDown: (updater: Function): Parcel => { + Types(`modifyShapeDown()`, `updater`, `function`)(updater); let staticUpdater = StaticParcel._updateFromData(updater); @@ -88,8 +88,8 @@ export default (_this: Parcel): Object => ({ }); }, - modifyUpDeep: (updater: Function): Parcel => { - Types(`modifyUpDeep()`, `updater`, `function`)(updater); + modifyShapeUp: (updater: Function): Parcel => { + Types(`modifyShapeUp()`, `updater`, `function`)(updater); let staticUpdater = StaticParcel._updateFromData(updater); diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index eb055bca..caff6930 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -34,10 +34,10 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).update(updater); }, - updateDeep: (key: Key|Index, updater: StaticParcelUpdater) => { + updateShape: (key: Key|Index, updater: StaticParcelUpdater) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); - _this.get(key).updateDeep(updater); + _this.get(key).updateShape(updater); }, updateIn: (keyPath: Array, updater: ParcelValueUpdater) => { @@ -46,9 +46,9 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.getIn(keyPath).update(updater); }, - updateInDeep: (keyPath: Array, updater: StaticParcelUpdater) => { - Types(`updateInDeep()`, `keyPath`, `keyIndexPath`)(keyPath); - Types(`updateInDeep()`, `updater`, `function`)(updater); - _this.getIn(keyPath).updateDeep(updater); + updateShapeIn: (keyPath: Array, updater: StaticParcelUpdater) => { + Types(`updateShapeIn()`, `keyPath`, `keyIndexPath`)(keyPath); + Types(`updateShapeIn()`, `updater`, `function`)(updater); + _this.getIn(keyPath).updateShape(updater); } }); diff --git a/packages/dataparcels/src/staticParcel/StaticParcel.js b/packages/dataparcels/src/staticParcel/StaticParcel.js index cf81c39f..0e730325 100644 --- a/packages/dataparcels/src/staticParcel/StaticParcel.js +++ b/packages/dataparcels/src/staticParcel/StaticParcel.js @@ -74,7 +74,7 @@ export default class StaticParcel { static _updateFromData(updater: StaticParcelUpdater): Function { return (parcelData: ParcelData): ParcelData => StaticParcel .fromData(parcelData) - .updateDeep(updater) + .updateShape(updater) .data; } @@ -177,12 +177,12 @@ export default class StaticParcel { ["1"]: (updater: StaticParcelValueUpdater): StaticParcel => this._methods.update(updater), ["2"]: (key: Key|Index, updater: StaticParcelValueUpdater): StaticParcel => this.updateIn([key], updater) }); - updateDeep = overload({ - ["1"]: (updater: StaticParcelUpdater): StaticParcel => this._methods.updateDeep(updater), - ["2"]: (key: Key|Index, updater: StaticParcelUpdater): StaticParcel => this.updateInDeep([key], updater) + updateShape = overload({ + ["1"]: (updater: StaticParcelUpdater): StaticParcel => this._methods.updateShape(updater), + ["2"]: (key: Key|Index, updater: StaticParcelUpdater): StaticParcel => this.updateShapeIn([key], updater) }); updateIn = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateInDeep = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateInDeep(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateShapeIn(keyPath, updater); // Indexed methods insertAfter = (key: Key|Index, value: any) => this._methods.insertAfter(key, value); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js index 6bb2ed75..ed7fa125 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js +++ b/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js @@ -203,7 +203,7 @@ test('StaticParcels updateIn(keyPath) should validate value updater', () => { ); }); -test('StaticParcels updateDeep(key) should work', () => { +test('StaticParcels updateShape(key) should work', () => { let staticParcel = StaticParcel.fromData({ value: { abc: [1,2,3] @@ -214,10 +214,10 @@ test('StaticParcels updateDeep(key) should work', () => { abc: [1,2,3,4] }; - expect(staticParcel.updateDeep('abc', staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); + expect(staticParcel.updateShape('abc', staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); }); -test('StaticParcels updateInDeep(keyPath) should work', () => { +test('StaticParcels updateShapeIn(keyPath) should work', () => { let staticParcel = StaticParcel.fromData({ value: { abc: { @@ -232,5 +232,5 @@ test('StaticParcels updateInDeep(keyPath) should work', () => { } }; - expect(staticParcel.updateInDeep(['abc', 'def'], staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); + expect(staticParcel.updateShapeIn(['abc', 'def'], staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); }); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js index 647379e9..27c765f6 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js +++ b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js @@ -86,7 +86,7 @@ test('StaticParcels update() should validate value updater', () => { ); }); -test('StaticParcels updateDeep() should work with returned StaticParcel', () => { +test('StaticParcels updateShape() should work with returned StaticParcel', () => { let staticParcel = StaticParcel.fromData({ value: 123, meta: { @@ -103,10 +103,10 @@ test('StaticParcels updateDeep() should work with returned StaticParcel', () => key: "z" }; - expect(staticParcel.updateDeep(staticParcel => staticParcel.set(456)).data).toEqual(expectedData); + expect(staticParcel.updateShape(staticParcel => staticParcel.set(456)).data).toEqual(expectedData); }); -test('StaticParcels updateDeep() should work with returned primitive', () => { +test('StaticParcels updateShape() should work with returned primitive', () => { let staticParcel = StaticParcel.fromData({ value: 123, meta: { @@ -123,10 +123,10 @@ test('StaticParcels updateDeep() should work with returned primitive', () => { key: "z" }; - expect(staticParcel.updateDeep(() => 456).data).toEqual(expectedData); + expect(staticParcel.updateShape(() => 456).data).toEqual(expectedData); }); -test('StaticParcels updateDeep() should work with returned parent value', () => { +test('StaticParcels updateShape() should work with returned parent value', () => { let staticParcel = StaticParcel.fromData({ value: [1,2,3], meta: { @@ -148,7 +148,7 @@ test('StaticParcels updateDeep() should work with returned parent value', () => key: "z" }; - let {data} = staticParcel.updateDeep((staticParcel) => { + let {data} = staticParcel.updateShape((staticParcel) => { return staticParcel .children() .map((child => child.update(value => value + 1))) @@ -157,7 +157,7 @@ test('StaticParcels updateDeep() should work with returned parent value', () => expect(data).toEqual(expectedData); }); -test('StaticParcels updateDeep() should work with returned parent value of different type', () => { +test('StaticParcels updateShape() should work with returned parent value of different type', () => { let staticParcel = StaticParcel.fromData({ value: { abc: 123, @@ -184,12 +184,12 @@ test('StaticParcels updateDeep() should work with returned parent value of diffe key: "z" }; - let {data} = staticParcel.updateDeep((staticParcel) => staticParcel.toArray()); + let {data} = staticParcel.updateShape((staticParcel) => staticParcel.toArray()); expect(data).toEqual(expectedData); }); -test('StaticParcels updateDeep() should retain childs keys', () => { +test('StaticParcels updateShape() should retain childs keys', () => { let staticParcel = StaticParcel.fromData({ value: ["a","b","c","d"], child: [ @@ -208,7 +208,7 @@ test('StaticParcels updateDeep() should retain childs keys', () => { ] }; - let {data} = staticParcel.updateDeep((staticParcel) => { + let {data} = staticParcel.updateShape((staticParcel) => { return staticParcel .toArray() .filter((value, key) => key % 2 === 1) @@ -217,12 +217,12 @@ test('StaticParcels updateDeep() should retain childs keys', () => { expect(data).toEqual(expectedData); }); -test('StaticParcels updateDeep() should throw error if non staticparcel is a child of the return value', () => { +test('StaticParcels updateShape() should throw error if non staticparcel is a child of the return value', () => { let staticParcel = StaticParcel.fromData({ value: [123, 456] }); - expect(() => staticParcel.updateDeep((staticParcel) => { + expect(() => staticParcel.updateShape((staticParcel) => { let arr = staticParcel.toArray(); arr.push(789); return arr; diff --git a/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js index 4db33cbc..aad68f33 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js +++ b/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js @@ -47,7 +47,7 @@ export default (_this: StaticParcel) => ({ ); }, - updateInDeep: (keyPath: Array, updater: StaticParcelUpdater): StaticParcel => { + updateShapeIn: (keyPath: Array, updater: StaticParcelUpdater): StaticParcel => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( diff --git a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js index ff1c73c6..6b6cea2d 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js +++ b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js @@ -44,7 +44,7 @@ export default (_this: StaticParcel) => ({ return _this.set(updatedValue); }, - updateDeep: (updater: StaticParcelUpdater): StaticParcel => { + updateShape: (updater: StaticParcelUpdater): StaticParcel => { let updated: any = updater(_this); if(_this._isStaticParcel(updated)) { return updated; From fcc9430f13d189bb5aaa74e916fd280414c4463a Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 13:13:39 +1100 Subject: [PATCH 051/120] docs: fix link --- .../dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md index 267e34a3..3fb088ce 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md @@ -32,6 +32,6 @@ let staticParcel = new StaticParcel(123); ## Example Usage -StaticParcels are used in a very similar way to (Immutable.js Maps and Lists)[https://facebook.github.io/immutable-js/docs/], by calling methods that return new and updated StaticParcels. +StaticParcels are used in a very similar way to [Immutable.js Maps and Lists](https://facebook.github.io/immutable-js/docs/), by calling methods that return new and updated StaticParcels. TODO From 602df3a3c35d46b904dfc16c8e2fb946f3e29540 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 13:30:57 +1100 Subject: [PATCH 052/120] amend: deep updater renamed to shape updaters --- .../src/docs/api/staticParcel/StaticParcel.md | 2 +- .../src/pages/{deep-updaters.js => shape-updaters.js} | 2 +- packages/dataparcels/src/errors/Errors.js | 2 +- packages/dataparcels/src/parcel/Parcel.js | 2 +- .../dataparcels/src/parcel/methods/ParcelChangeMethods.js | 4 ++-- .../src/staticParcel/__test__/StaticSetMethods-test.js | 2 +- .../dataparcels/src/staticParcel/methods/StaticSetMethods.js | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) rename packages/dataparcels-docs/src/pages/{deep-updaters.js => shape-updaters.js} (94%) diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md index 3fb088ce..4fcbd829 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md @@ -10,7 +10,7 @@ import IconParcel from 'content/parcel.gif'; StaticParcel is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter it's data. -These exist to be used with deep updaters, to provide a safe way to alter the shape of data in a Parcel. +These exist to be used with shape updaters, to provide a safe way to alter the shape of data in a Parcel. Its methods a subset of Parcel's methods. ```js diff --git a/packages/dataparcels-docs/src/pages/deep-updaters.js b/packages/dataparcels-docs/src/pages/shape-updaters.js similarity index 94% rename from packages/dataparcels-docs/src/pages/deep-updaters.js rename to packages/dataparcels-docs/src/pages/shape-updaters.js index 2dc96278..59897ee2 100644 --- a/packages/dataparcels-docs/src/pages/deep-updaters.js +++ b/packages/dataparcels-docs/src/pages/shape-updaters.js @@ -4,7 +4,7 @@ import {Box, CenteredLanding, Text} from 'dcme-style'; export default () => Deep Updaters} + top={() => Shape Updaters} bottom={() => This doesn't exist yet. These docs are still very much under construction.} /> ; diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index 4ae30daf..7090fcbc 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -5,4 +5,4 @@ export const ReducerInvalidActionError = (actionType: string) => new Error(`"${a export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); -export const DeepUpdaterNonStaticChildError = () => new Error(`Every child value on a collection returned from a deep updater must be a StaticParcel`); +export const ShapeUpdaterNonStaticChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a StaticParcel`); diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 4f00f62c..84cff200 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -287,7 +287,7 @@ export default class Parcel { ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); updateShape = overload({ - ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfDeep(updater), + ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfShape(updater), ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateShape(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 2e68b858..d5c77441 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -24,8 +24,8 @@ export default (_this: Parcel, dispatch: Function) => ({ _this.set(updatedValue); }, - updateSelfDeep: (updater: StaticParcelUpdater) => { - Types(`updateSelfDeep()`, `updater`, `function`)(updater); + updateSelfShape: (updater: StaticParcelUpdater) => { + Types(`updateSelfShape()`, `updater`, `function`)(updater); let staticParcelUpdater = StaticParcel._updateFromData(updater); let updated = staticParcelUpdater(_this._parcelData); dispatch(ActionCreators.setData(updated)); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js index 27c765f6..b8d664ae 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js +++ b/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js @@ -226,5 +226,5 @@ test('StaticParcels updateShape() should throw error if non staticparcel is a ch let arr = staticParcel.toArray(); arr.push(789); return arr; - })).toThrow('Every child value on a collection returned from a deep updater must be a StaticParcel'); + })).toThrow('Every child value on a collection returned from a shape updater must be a StaticParcel'); }); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js index 6b6cea2d..483792ca 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js +++ b/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js @@ -5,7 +5,7 @@ import type {StaticParcelValueUpdater} from '../../types/Types'; import type {StaticParcelSetMeta} from '../../types/Types'; import type {StaticParcelUpdater} from '../../types/Types'; -import {DeepUpdaterNonStaticChildError} from '../../errors/Errors'; +import {ShapeUpdaterNonStaticChildError} from '../../errors/Errors'; import isParentValue from '../../parcelData/isParentValue'; import parcelSetMeta from '../../parcelData/setMeta'; import parcelSetSelf from '../../parcelData/setSelf'; @@ -61,7 +61,7 @@ export default (_this: StaticParcel) => ({ updated, map((childStaticParcel: StaticParcel, key: string|number): ParcelDataEvaluator => { if(!_this._isStaticParcel(childStaticParcel)) { - throw DeepUpdaterNonStaticChildError(); + throw ShapeUpdaterNonStaticChildError(); } return parcelUpdate(key, () => childStaticParcel.data); }) From 55e24567de15b46ae946f4f4d06595688dca7990 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 16:41:59 +1100 Subject: [PATCH 053/120] build: add size limit --- package.json | 14 +- packages/dataparcels/package.json | 4 + yarn.lock | 1633 ++++++++++++++++++++++++++++- 3 files changed, 1597 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index 62998601..7edad929 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "flow-coverage": "blueflag-test flow-coverage -M", "lint": "blueflag-test lint --monorepo", "test": "yarn jest --maxWorkers=4", - "test-all": "yarn lint && yarn flow && yarn test --maxWorkers=4 && yarn flow-coverage", + "test-all": "yarn lint && yarn flow && yarn test --maxWorkers=4 && yarn flow-coverage && yarn size-limit", "deploy-docs": "yarn lerna --scope dataparcels-docs run deploy", "view-coverage": "open ./coverage/lcov-report/index.html", "watch": "lerna run watch --parallel --" @@ -36,5 +36,15 @@ }, "dependencies": { "babel-plugin-extract-flow-types": "^1.0.0" - } + }, + "size-limit": [ + { + "limit": "25 KB", + "path": "packages/dataparcels/lib/index.js" + }, + { + "limit": "30 KB", + "path": "packages/react-dataparcels/lib/index.js" + } + ] } diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index f4dd47af..9405a9d9 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -19,11 +19,15 @@ "scripts": { "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore **/*-test.js", "build-all": "yarn build", + "size": "size-limit", "watch": "yarn run build -w" }, "dependencies": { "babel-runtime": "6.23.0", "escape-string-regexp": "^1.0.5", "unmutable": "^0.39.0" + }, + "devDependencies": { + "size-limit": "^0.21.1" } } diff --git a/yarn.lock b/yarn.lock index cc4e0997..0534f183 100644 --- a/yarn.lock +++ b/yarn.lock @@ -143,6 +143,17 @@ pretty-ms "^0.2.1" text-table "^0.2.0" +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + "@sinonjs/formatio@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" @@ -197,6 +208,10 @@ version "7.0.68" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.68.tgz#f468d9a4407259faa64b472f64d795ff85d51a77" +"@types/q@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" + "@types/react-router-dom@^4.2.2": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.0.tgz#c91796d02deb3a5b24bc1c5db4a255df0d18b8b5" @@ -222,6 +237,139 @@ version "0.0.32" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.32.tgz#0d3cb31022f8427ea58c008af32b80da126ca4e3" +"@webassemblyjs/ast@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace" + dependencies: + "@webassemblyjs/helper-module-context" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/wast-parser" "1.7.11" + +"@webassemblyjs/floating-point-hex-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz#a69f0af6502eb9a3c045555b1a6129d3d3f2e313" + +"@webassemblyjs/helper-api-error@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz#c7b6bb8105f84039511a2b39ce494f193818a32a" + +"@webassemblyjs/helper-buffer@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz#3122d48dcc6c9456ed982debe16c8f37101df39b" + +"@webassemblyjs/helper-code-frame@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz#cf8f106e746662a0da29bdef635fcd3d1248364b" + dependencies: + "@webassemblyjs/wast-printer" "1.7.11" + +"@webassemblyjs/helper-fsm@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz#df38882a624080d03f7503f93e3f17ac5ac01181" + +"@webassemblyjs/helper-module-context@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz#d874d722e51e62ac202476935d649c802fa0e209" + +"@webassemblyjs/helper-wasm-bytecode@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz#dd9a1e817f1c2eb105b4cf1013093cb9f3c9cb06" + +"@webassemblyjs/helper-wasm-section@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz#9c9ac41ecf9fbcfffc96f6d2675e2de33811e68a" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + +"@webassemblyjs/ieee754@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b" + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.11.tgz#d7267a1ee9c4594fd3f7e37298818ec65687db63" + dependencies: + "@xtuc/long" "4.2.1" + +"@webassemblyjs/utf8@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.11.tgz#06d7218ea9fdc94a6793aa92208160db3d26ee82" + +"@webassemblyjs/wasm-edit@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz#8c74ca474d4f951d01dbae9bd70814ee22a82005" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/helper-wasm-section" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + "@webassemblyjs/wasm-opt" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + "@webassemblyjs/wast-printer" "1.7.11" + +"@webassemblyjs/wasm-gen@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz#9bbba942f22375686a6fb759afcd7ac9c45da1a8" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/ieee754" "1.7.11" + "@webassemblyjs/leb128" "1.7.11" + "@webassemblyjs/utf8" "1.7.11" + +"@webassemblyjs/wasm-opt@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz#b331e8e7cef8f8e2f007d42c3a36a0580a7d6ca7" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + +"@webassemblyjs/wasm-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz#6e3d20fa6a3519f6b084ef9391ad58211efb0a1a" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-api-error" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/ieee754" "1.7.11" + "@webassemblyjs/leb128" "1.7.11" + "@webassemblyjs/utf8" "1.7.11" + +"@webassemblyjs/wast-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz#25bd117562ca8c002720ff8116ef9072d9ca869c" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/floating-point-hex-parser" "1.7.11" + "@webassemblyjs/helper-api-error" "1.7.11" + "@webassemblyjs/helper-code-frame" "1.7.11" + "@webassemblyjs/helper-fsm" "1.7.11" + "@xtuc/long" "4.2.1" + +"@webassemblyjs/wast-printer@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz#c4245b6de242cb50a2cc950174fdbf65c78d7813" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/wast-parser" "1.7.11" + "@xtuc/long" "4.2.1" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + +"@xtuc/long@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8" + "@zeit/schemas@1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-1.7.0.tgz#84624e270a0d420714be7279ffabc7e1745afc1a" @@ -252,6 +400,12 @@ accepts@^1.3.0, accepts@~1.3.4, accepts@~1.3.5: mime-types "~2.1.18" negotiator "0.6.1" +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" + dependencies: + acorn "^5.0.0" + acorn-globals@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" @@ -278,6 +432,10 @@ acorn@^5.0.0, acorn@^5.0.3, acorn@^5.5.0, acorn@^5.5.3, acorn@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" +acorn@^5.6.2, acorn@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -290,11 +448,15 @@ after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" -ajv-keywords@^3.0.0: +ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" @@ -323,6 +485,15 @@ ajv@^5.0.0, ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" +ajv@^6.1.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96" + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -331,7 +502,7 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" -alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: +alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -413,7 +584,7 @@ append-transform@^1.0.0: dependencies: default-require-extensions "^2.0.0" -aproba@^1.0.3: +aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1781,10 +1952,23 @@ better-queue@^3.8.6, better-queue@^3.8.7: node-eta "^0.9.0" uuid "^3.0.0" +bfj@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" + dependencies: + bluebird "^3.5.1" + check-types "^7.3.0" + hoopy "^0.1.2" + tryer "^1.0.0" + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" @@ -1810,6 +1994,10 @@ bluebird@^3.0.0, bluebird@^3.0.5, bluebird@^3.3.4, bluebird@^3.5.0: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" +bluebird@^3.5.1, bluebird@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + blueflag-test@^0.18.1: version "0.18.1" resolved "https://registry.yarnpkg.com/blueflag-test/-/blueflag-test-0.18.1.tgz#2f1ef068b6a270f9152e872a52cab61b740162bd" @@ -1882,7 +2070,22 @@ body-parser@1.18.2: raw-body "2.3.2" type-is "~1.6.15" -boolbase@~1.0.0: +body-parser@1.18.3: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + +boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -1919,7 +2122,7 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.3.1: +braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: @@ -2027,6 +2230,14 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" +browserslist@^4.0.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.0.tgz#7050d1412cbfc5274aba609ed5e50359ca1a5fdf" + dependencies: + caniuse-lite "^1.0.30000928" + electron-to-chromium "^1.3.100" + node-releases "^1.1.3" + bruce@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/bruce/-/bruce-4.0.0.tgz#e6f05dde87e31d849744c68c54727482164c822b" @@ -2090,10 +2301,29 @@ byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" -bytes@3.0.0: +bytes@3.0.0, bytes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" +cacache@^11.0.2, cacache@^11.2.0: + version "11.3.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" + dependencies: + bluebird "^3.5.3" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.3" + graceful-fs "^4.1.15" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2133,12 +2363,24 @@ call-signature@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + dependencies: + callsites "^2.0.0" + caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" dependencies: callsites "^0.2.0" +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + dependencies: + caller-callsite "^2.0.0" + callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" @@ -2182,6 +2424,10 @@ camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +camelcase@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + caniuse-api@^1.5.2, caniuse-api@^1.5.3: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -2191,10 +2437,23 @@ caniuse-api@^1.5.2, caniuse-api@^1.5.3: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: version "1.0.30000872" resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000872.tgz#3f6e53b63d373768bf99e896133d66ef89c49999" +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000928: + version "1.0.30000928" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000928.tgz#805e828dc72b06498e3683a32e61c7507fd67b88" + caniuse-lite@^1.0.30000844: version "1.0.30000872" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000872.tgz#aa1346ac88ed8dcdc7e372a42989bf9bea696f06" @@ -2250,6 +2509,14 @@ chalk@^0.4.0: has-color "~0.1.0" strip-ansi "~0.1.0" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + character-entities-html4@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" @@ -2274,6 +2541,10 @@ charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" +check-types@^7.3.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" + cheerio@^0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" @@ -2321,10 +2592,39 @@ chokidar@^1.0.0, chokidar@^1.4.2, chokidar@^1.6.1, chokidar@^1.7.0: optionalDependencies: fsevents "^1.0.0" +chokidar@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + lodash.debounce "^4.0.8" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.5" + optionalDependencies: + fsevents "^1.2.2" + chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + +chrome-trace-event@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" + dependencies: + tslib "^1.9.0" + chunk-manifest-webpack-plugin@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/chunk-manifest-webpack-plugin/-/chunk-manifest-webpack-plugin-0.1.0.tgz#6138488fc21ddab4ccfb7c1c11d51bb80a943186" @@ -2335,6 +2635,10 @@ ci-info@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" +ci-job-number@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ci-job-number/-/ci-job-number-0.3.0.tgz#34bdd114b0dece1960287bd40a57051041a2a800" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -2478,6 +2782,14 @@ coa@~1.0.1: dependencies: q "^1.1.2" +coa@~2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + code-excerpt@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" @@ -2509,11 +2821,17 @@ color-convert@^1.3.0, color-convert@^1.9.0: dependencies: color-name "1.1.1" +color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + dependencies: + color-name "1.1.3" + color-name@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" -color-name@^1.0.0: +color-name@1.1.3, color-name@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -2523,6 +2841,13 @@ color-string@^0.3.0: dependencies: color-name "^1.0.0" +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + color@^0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/color/-/color-0.10.1.tgz#c04188df82a209ddebccecdacd3ec320f193739f" @@ -2538,6 +2863,13 @@ color@^0.11.0, color@^0.11.3, color@^0.11.4: color-convert "^1.3.0" color-string "^0.3.0" +color@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + colormin@^1.0.5: version "1.1.2" resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" @@ -2599,6 +2931,14 @@ commander@^2.11.0, commander@^2.9.0: version "2.16.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" +commander@^2.18.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + +commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + common-path-prefix@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-1.0.0.tgz#cd52f6f0712e0baab97d6f9732874f22f47752c0" @@ -2650,6 +2990,17 @@ compressible@~2.0.14: dependencies: mime-db ">= 1.34.0 < 2" +compression-webpack-plugin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-2.0.0.tgz#46476350c1eb27f783dccc79ac2f709baa2cffbc" + dependencies: + cacache "^11.2.0" + find-cache-dir "^2.0.0" + neo-async "^2.5.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + webpack-sources "^1.0.1" + compression@^1.5.2: version "1.7.3" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db" @@ -2666,7 +3017,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.10, concat-stream@^1.6.0: +concat-stream@^1.4.10, concat-stream@^1.5.0, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: @@ -2898,6 +3249,17 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" @@ -2932,6 +3294,15 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +cosmiconfig@^5.0.0, cosmiconfig@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04" + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -3003,7 +3374,7 @@ cross-spawn@^4: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: @@ -3061,10 +3432,17 @@ css-color-function@^1.2.0: debug "^3.1.0" rgb "~0.1.0" -css-color-names@0.0.4, css-color-names@~0.0.3: +css-color-names@0.0.4, css-color-names@^0.0.4, css-color-names@~0.0.3: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + css-loader@^0.26.1: version "0.26.4" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.26.4.tgz#b61e9e30db94303e6ffc892f10ecd09ad025a1fd" @@ -3082,6 +3460,25 @@ css-loader@^0.26.1: postcss-modules-values "^1.1.0" source-list-map "^0.1.7" +css-loader@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.0.tgz#42952ac22bca5d076978638e9813abce49b8f0cc" + dependencies: + icss-utils "^4.0.0" + loader-utils "^1.2.1" + lodash "^4.17.11" + postcss "^7.0.6" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^2.0.3" + postcss-modules-scope "^2.0.0" + postcss-modules-values "^2.0.0" + postcss-value-parser "^3.3.0" + schema-utils "^1.0.0" + +css-select-base-adapter@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + css-select@^1.1.0, css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -3091,6 +3488,15 @@ css-select@^1.1.0, css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" +css-select@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + dependencies: + boolbase "^1.0.0" + css-what "^2.1.2" + domutils "^1.7.0" + nth-check "^1.0.2" + css-selector-parser@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.3.0.tgz#5f1ad43e2d8eefbfdc304fcd39a521664943e3eb" @@ -3103,14 +3509,97 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" +css-tree@1.0.0-alpha.28: + version "1.0.0-alpha.28" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + +css-url-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" + css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" +css-what@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" + cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + +cssnano-preset-default@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.6.tgz#92379e2a6db4a91c0ea727f5f556eeac693eab6a" + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.0" + postcss-colormin "^4.0.2" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.1" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.10" + postcss-merge-rules "^4.0.2" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.1" + postcss-minify-params "^4.0.1" + postcss-minify-selectors "^4.0.1" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.1" + postcss-normalize-positions "^4.0.1" + postcss-normalize-repeat-style "^4.0.1" + postcss-normalize-string "^4.0.1" + postcss-normalize-timing-functions "^4.0.1" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.1" + postcss-ordered-values "^4.1.1" + postcss-reduce-initial "^4.0.2" + postcss-reduce-transforms "^4.0.1" + postcss-svgo "^4.0.1" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + "cssnano@>=2.6.1 <4": version "3.10.0" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" @@ -3148,6 +3637,21 @@ cssesc@^0.1.0: postcss-value-parser "^3.2.3" postcss-zindex "^2.0.1" +cssnano@^4.1.0: + version "4.1.8" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.8.tgz#8014989679d5fd42491e4499a521dbfb85c95fd1" + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.6" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + dependencies: + css-tree "1.0.0-alpha.29" + csso@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" @@ -3175,6 +3679,10 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" @@ -3260,7 +3768,7 @@ decamelize-keys@^1.0.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3479,6 +3987,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" + dependencies: + arrify "^1.0.1" + path-type "^3.0.0" + discontinuous-range@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" @@ -3557,7 +4072,7 @@ domutils@1.5.1: dom-serializer "0" domelementtype "1" -domutils@^1.5.1: +domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" dependencies: @@ -3570,7 +4085,7 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" -dot-prop@^4.1.0: +dot-prop@^4.1.0, dot-prop@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" dependencies: @@ -3592,6 +4107,15 @@ duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + eastasianwidth@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.1.1.tgz#44d656de9da415694467335365fb3147b8572b7c" @@ -3607,10 +4131,18 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +ejs@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" + electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47: version "1.3.55" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.55.tgz#f150e10b20b77d9d41afcca312efe0c3b1a7fdce" +electron-to-chromium@^1.3.100: + version "1.3.102" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.102.tgz#3ac43a037c8a63bca3dfa189eb3d90f097196787" + element-resize-detector@^1.1.12: version "1.1.14" resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.1.14.tgz#af064a0a618a820ad570a95c5eec5b77be0128c1" @@ -3697,6 +4229,14 @@ engine.io@~3.2.0: engine.io-parser "~2.1.0" ws "~3.3.1" +enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + enhanced-resolve@~0.9.0: version "0.9.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" @@ -3778,7 +4318,7 @@ err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" -errno@^0.1.3: +errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: @@ -4159,6 +4699,18 @@ execa@^0.8.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exenv@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" @@ -4265,6 +4817,41 @@ express@^4.13.3, express@^4.14.0: utils-merge "1.0.1" vary "~1.1.2" +express@^4.16.3: + version "4.16.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.3" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.4" + qs "6.5.2" + range-parser "~1.2.0" + safe-buffer "5.1.2" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4346,6 +4933,17 @@ fast-glob@^1.0.1: micromatch "^3.0.3" readdir-enhanced "^1.5.2" +fast-glob@^2.0.2: + version "2.2.6" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -4394,6 +4992,10 @@ fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -4413,6 +5015,13 @@ file-loader@^0.9.0: dependencies: loader-utils "~0.2.5" +file-loader@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" + dependencies: + loader-utils "^1.0.2" + schema-utils "^1.0.0" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -4428,6 +5037,10 @@ filesize@3.5.11: version "3.5.11" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" +filesize@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -4482,6 +5095,14 @@ find-cache-dir@^1.0.0: make-dir "^1.0.0" pkg-dir "^2.0.0" +find-cache-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" + dependencies: + commondir "^1.0.1" + make-dir "^1.0.0" + pkg-dir "^3.0.0" + find-file-up@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/find-file-up/-/find-file-up-0.1.3.tgz#cf68091bcf9f300a40da411b37da5cce5a2fbea0" @@ -4515,6 +5136,12 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + dependencies: + locate-path "^3.0.0" + findup-sync@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.2.tgz#a8117d0f73124f5a4546839579fe52d7129fb5e5" @@ -4602,6 +5229,13 @@ flow-coverage-report@^0.5.0: terminal-table "0.0.12" yargs "8.0.1" +flush-write-stream@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.4" + fn-name@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" @@ -4681,6 +5315,13 @@ friendly-errors-webpack-plugin@^1.6.1: error-stack-parser "^2.0.0" string-width "^2.0.0" +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + front-matter@^2.1.0, front-matter@^2.1.2: version "2.3.0" resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.3.0.tgz#7203af896ce357ee04e2aa45169ea91ed7f67504" @@ -4721,11 +5362,20 @@ fs-readdir-recursive@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.0.0, fsevents@^1.2.3: +fsevents@^1.0.0, fsevents@^1.2.2, fsevents@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" dependencies: @@ -5089,6 +5739,12 @@ get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -5213,13 +5869,24 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, gl once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" +glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: - ini "^1.3.4" - -global-modules@1.0.0, global-modules@^1.0.0: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + +global-modules@1.0.0, global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" dependencies: @@ -5289,6 +5956,18 @@ globby@^6.0.0, globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +globby@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" + dependencies: + array-union "^1.0.1" + dir-glob "2.0.0" + fast-glob "^2.0.2" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + globule@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" @@ -5342,6 +6021,10 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +graceful-fs@^4.1.15: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -5386,6 +6069,13 @@ gzip-size@3.0.0: dependencies: duplexer "^0.1.1" +gzip-size@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" + dependencies: + duplexer "^0.1.1" + pify "^3.0.0" + handlebars@^4.0.11, handlebars@^4.0.2, handlebars@^4.0.3: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" @@ -5499,7 +6189,7 @@ has-yarn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-1.0.0.tgz#89e25db604b725c8f5976fff0addc921b828a5a7" -has@^1.0.1, has@^1.0.3: +has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: @@ -5609,6 +6299,10 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + history@^4.6.2, history@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" @@ -5652,10 +6346,22 @@ homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" +hoopy@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + hosted-git-info@^2.1.4, hosted-git-info@^2.5.0: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + html-comment-regex@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" @@ -5703,7 +6409,7 @@ http-errors@1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-errors@1.6.3, http-errors@~1.6.2: +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" dependencies: @@ -5800,10 +6506,20 @@ icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" +icss-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.0.0.tgz#d52cf4bcdcfa1c45c2dbefb4ffdf6b00ef608098" + dependencies: + postcss "^7.0.5" + ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + ignore-by-default@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -5814,7 +6530,7 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.3: +ignore@^3.3.3, ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -5830,6 +6546,13 @@ immutable@~3.7.6: version "3.7.6" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -5948,6 +6671,10 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" @@ -5998,6 +6725,10 @@ is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -6028,6 +6759,17 @@ is-ci@^1.0.10, is-ci@^1.0.7: dependencies: ci-info "^1.0.0" +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -6064,6 +6806,10 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -6291,6 +7037,12 @@ is-svg@^2.0.0: dependencies: html-comment-regex "^1.1.0" +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + dependencies: + html-comment-regex "^1.1.0" + is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" @@ -6883,6 +7635,13 @@ js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.5.2, js-yaml@^3.7.0, js-yaml@^3.9.1 argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.12.0, js-yaml@^3.9.0: + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@~2.1.0: version "2.1.3" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-2.1.3.tgz#0ffb5617be55525878063d7a16aee7fdd282e84c" @@ -6952,7 +7711,7 @@ json-loader@^0.5.2: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" -json-parse-better-errors@^1.0.1: +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -6990,6 +7749,12 @@ json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + dependencies: + minimist "^1.2.0" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -7116,6 +7881,13 @@ kleur@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.1.tgz#7cc64b0d188d0dcbc98bdcdfdda2cc10619ddce8" +last-call-webpack-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" + dependencies: + lodash "^4.17.5" + webpack-sources "^1.1.0" + last-line-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/last-line-stream/-/last-line-stream-1.0.0.tgz#d1b64d69f86ff24af2d04883a2ceee14520a5600" @@ -7138,6 +7910,12 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + dependencies: + invert-kv "^2.0.0" + left-pad@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" @@ -7254,6 +8032,10 @@ load-pkg@^3.0.1: dependencies: find-pkg "^0.1.0" +loader-runner@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" + loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.3, loader-utils@~0.2.5: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" @@ -7271,6 +8053,14 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" +loader-utils@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7278,6 +8068,13 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash-es@^4.2.1: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.10.tgz#62cd7104cdf5dd87f235a837f0ede0e8e5117e05" @@ -7334,7 +8131,7 @@ lodash.clonedeepwith@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4" -lodash.debounce@^4.0.3: +lodash.debounce@^4.0.3, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -7500,6 +8297,10 @@ lodash@4.11.1: version "4.11.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.11.1.tgz#a32106eb8e2ec8e82c241611414773c9df15f8bc" +lodash@^4.17.11: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + log-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -7551,6 +8352,12 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + dependencies: + yallist "^3.0.2" + ltcdr@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf" @@ -7573,6 +8380,12 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + dependencies: + p-defer "^1.0.0" + map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -7716,6 +8529,10 @@ mdast-util-toc@^2.0.1: mdast-util-to-string "^1.0.2" unist-util-visit "^1.1.0" +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -7749,20 +8566,28 @@ mem@^1.1.0: dependencies: mimic-fn "^1.0.0" +mem@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^1.0.0" + p-is-promise "^1.1.0" + memory-fs@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" -memory-fs@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" +memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" dependencies: errno "^0.1.3" readable-stream "^2.0.1" -memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" +memory-fs@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -7812,6 +8637,10 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" +merge2@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" + merge@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" @@ -7961,6 +8790,21 @@ minizlib@^1.1.0: dependencies: minipass "^2.2.1" +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + mitt@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" @@ -7994,6 +8838,17 @@ moo@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8069,6 +8924,10 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +neo-async@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + netrc@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444" @@ -8213,6 +9072,12 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" +node-releases@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.3.tgz#aad9ce0dcb98129c753f772c0aa01360fb90fbd2" + dependencies: + semver "^5.3.0" + node-sass@^4.5.2: version "4.9.2" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.2.tgz#5e63fe6bd0f2ae3ac9d6c14ede8620e2b8bdb437" @@ -8292,6 +9157,10 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + npm-bundled@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" @@ -8332,6 +9201,12 @@ nth-check@^1.0.1, nth-check@~1.0.1: dependencies: boolbase "~1.0.0" +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + dependencies: + boolbase "~1.0.0" + null-loader@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-0.1.1.tgz#17be9abfcd3ff0e1512f6fc4afcb1f5039378fae" @@ -8522,6 +9397,10 @@ open@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + opn@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" @@ -8541,6 +9420,13 @@ optimist@^0.6.1, optimist@~0.6.0, optimist@~0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" +optimize-css-assets-webpack-plugin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz#9eb500711d35165b45e7fd60ba2df40cb3eb9159" + dependencies: + cssnano "^4.1.0" + last-call-webpack-plugin "^3.0.0" + option-chain@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-1.0.0.tgz#938d73bd4e1783f948d34023644ada23669e30f2" @@ -8588,6 +9474,14 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -8611,22 +9505,42 @@ p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" dependencies: p-try "^1.0.0" +p-limit@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" dependencies: p-limit "^1.1.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + dependencies: + p-limit "^2.0.0" + p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" @@ -8641,6 +9555,10 @@ p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" +p-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + package-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-1.2.0.tgz#003e56cd57b736a6ed6114cc2b81542672770e44" @@ -8673,6 +9591,14 @@ pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" @@ -8959,6 +9885,12 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + dependencies: + find-up "^3.0.0" + pkg-resolve@^0.1.7: version "0.1.14" resolved "https://registry.yarnpkg.com/pkg-resolve/-/pkg-resolve-0.1.14.tgz#329b2e76ccbb372e22e6a3a41cb30ab0457836ba" @@ -9019,6 +9951,15 @@ postcss-calc@^5.0.0, postcss-calc@^5.2.0: postcss-message-helpers "^2.0.0" reduce-css-calc "^1.2.6" +postcss-calc@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + postcss-color-function@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-2.0.1.tgz#9ad226f550e8a7c7f8b8a77860545b6dd7f55241" @@ -9092,6 +10033,16 @@ postcss-colormin@^2.1.8: postcss "^5.0.13" postcss-value-parser "^3.2.3" +postcss-colormin@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.2.tgz#93cd1fa11280008696887db1a528048b18e7ed99" + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-convert-values@^2.3.4: version "2.6.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" @@ -9099,6 +10050,13 @@ postcss-convert-values@^2.3.4: postcss "^5.0.11" postcss-value-parser "^3.1.2" +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-cssnext@^2.8.0: version "2.11.0" resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-2.11.0.tgz#31e68f001e409604da703b66de14b8b8c8c9f2b1" @@ -9162,24 +10120,48 @@ postcss-discard-comments@^2.0.4: dependencies: postcss "^5.0.14" +postcss-discard-comments@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.1.tgz#30697735b0c476852a7a11050eb84387a67ef55d" + dependencies: + postcss "^7.0.0" + postcss-discard-duplicates@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" dependencies: postcss "^5.0.4" +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + dependencies: + postcss "^7.0.0" + postcss-discard-empty@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" dependencies: postcss "^5.0.14" +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + dependencies: + postcss "^7.0.0" + postcss-discard-overridden@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" dependencies: postcss "^5.0.16" +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + dependencies: + postcss "^7.0.0" + postcss-discard-unused@^2.2.1: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" @@ -9265,6 +10247,15 @@ postcss-merge-longhand@^2.0.1: dependencies: postcss "^5.0.4" +postcss-merge-longhand@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.10.tgz#c4d63ab57bdc054ab4067ab075d488c8c2978380" + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + postcss-merge-rules@^2.0.3: version "2.1.2" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" @@ -9275,6 +10266,17 @@ postcss-merge-rules@^2.0.3: postcss-selector-parser "^2.2.2" vendors "^1.0.0" +postcss-merge-rules@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.2.tgz#2be44401bf19856f27f32b8b12c0df5af1b88e74" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + postcss-message-helpers@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" @@ -9287,6 +10289,13 @@ postcss-minify-font-values@^1.0.2: postcss "^5.0.4" postcss-value-parser "^3.0.2" +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-minify-gradients@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" @@ -9294,6 +10303,15 @@ postcss-minify-gradients@^1.0.1: postcss "^5.0.12" postcss-value-parser "^3.3.0" +postcss-minify-gradients@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.1.tgz#6da95c6e92a809f956bb76bf0c04494953e1a7dd" + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-minify-params@^1.0.4: version "1.2.2" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" @@ -9303,6 +10321,17 @@ postcss-minify-params@^1.0.4: postcss-value-parser "^3.0.2" uniqs "^2.0.0" +postcss-minify-params@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.1.tgz#5b2e2d0264dd645ef5d68f8fec0d4c38c1cf93d2" + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + postcss-minify-selectors@^2.0.4: version "2.1.1" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" @@ -9312,12 +10341,27 @@ postcss-minify-selectors@^2.0.4: postcss "^5.0.14" postcss-selector-parser "^2.0.0" +postcss-minify-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.1.tgz#a891c197977cc37abf60b3ea06b84248b1c1e9cd" + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + postcss-modules-extract-imports@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" dependencies: postcss "^6.0.1" +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + dependencies: + postcss "^7.0.5" + postcss-modules-local-by-default@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" @@ -9325,6 +10369,14 @@ postcss-modules-local-by-default@^1.0.1: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" +postcss-modules-local-by-default@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.4.tgz#a000bb07e4f57f412ba35c904d035cfd4a7b9446" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^7.0.6" + postcss-value-parser "^3.3.1" + postcss-modules-scope@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" @@ -9332,6 +10384,13 @@ postcss-modules-scope@^1.0.0: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" +postcss-modules-scope@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.0.1.tgz#2c0f2394cde4cd09147db054c68917e38f6d43a4" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^7.0.6" + postcss-modules-values@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" @@ -9339,6 +10398,13 @@ postcss-modules-values@^1.1.0: icss-replace-symbols "^1.1.0" postcss "^6.0.1" +postcss-modules-values@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64" + dependencies: + icss-replace-symbols "^1.1.0" + postcss "^7.0.6" + postcss-nesting@^2.0.5: version "2.3.1" resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-2.3.1.tgz#94a6b6a4ef707fbec20a87fee5c957759b4e01cf" @@ -9351,6 +10417,62 @@ postcss-normalize-charset@^1.1.0: dependencies: postcss "^5.0.5" +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz#d9a83d47c716e8a980f22f632c8b0458cfb48a4c" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.1.tgz#ee2d4b67818c961964c6be09d179894b94fd6ba1" + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.1.tgz#5293f234b94d7669a9f805495d35b82a581c50e5" + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.1.tgz#23c5030c2cc24175f66c914fa5199e2e3c10fef3" + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.1.tgz#8be83e0b9cb3ff2d1abddee032a49108f05f95d7" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-normalize-url@^3.0.7: version "3.0.8" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" @@ -9360,6 +10482,22 @@ postcss-normalize-url@^3.0.7: postcss "^5.0.14" postcss-value-parser "^3.2.3" +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.1.tgz#d14cb639b61238418ac8bc8d3b7bdd65fc86575e" + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-ordered-values@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" @@ -9367,6 +10505,14 @@ postcss-ordered-values@^2.1.0: postcss "^5.0.4" postcss-value-parser "^3.0.1" +postcss-ordered-values@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.1.tgz#2e3b432ef3e489b18333aeca1f1295eb89be9fc2" + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-pseudo-class-any-link@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-1.0.0.tgz#903239196401d335fe73ac756186fa62e693af26" @@ -9393,6 +10539,15 @@ postcss-reduce-initial@^1.0.0: dependencies: postcss "^5.0.4" +postcss-reduce-initial@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.2.tgz#bac8e325d67510ee01fa460676dc8ea9e3b40f15" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-reduce-transforms@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" @@ -9401,6 +10556,15 @@ postcss-reduce-transforms@^1.0.3: postcss "^5.0.8" postcss-value-parser "^3.0.1" +postcss-reduce-transforms@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.1.tgz#8600d5553bdd3ad640f43bff81eb52f8760d4561" + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + postcss-replace-overflow-wrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-1.0.0.tgz#f0a03b31eab9636a6936bfd210e2aef1b434a643" @@ -9446,6 +10610,22 @@ postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.0, postcss-selector indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-svgo@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" @@ -9455,6 +10635,15 @@ postcss-svgo@^2.1.1: postcss-value-parser "^3.2.3" svgo "^0.7.0" +postcss-svgo@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.1.tgz#5628cdb38f015de6b588ce6d0bf0724b492b581d" + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + postcss-unique-selectors@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" @@ -9463,6 +10652,18 @@ postcss-unique-selectors@^2.0.2: postcss "^5.0.4" uniqs "^2.0.0" +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" @@ -9492,6 +10693,14 @@ postcss@^6.0.1, postcss@^6.0.14: source-map "^0.6.1" supports-color "^5.4.0" +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.11" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.11.tgz#f63c513b78026d66263bb2ca995bf02e3d1a697d" + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -9566,6 +10775,10 @@ promise-each@^2.2.0: dependencies: any-promise "^0.1.0" +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -9606,7 +10819,7 @@ property-information@^3.0.0, property-information@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-3.2.0.tgz#fd1483c8fbac61808f5fe359e7693a1f48a58331" -proxy-addr@~2.0.3: +proxy-addr@~2.0.3, proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" dependencies: @@ -9650,6 +10863,28 @@ pump@^1.0.0: end-of-stream "^1.1.0" once "^1.3.1" +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -9674,14 +10909,14 @@ qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@6.5.2, qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -9756,7 +10991,7 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" -raw-body@^2.3.2: +raw-body@2.3.3, raw-body@^2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" dependencies: @@ -10034,6 +11269,13 @@ read-pkg-up@^3.0.0: find-up "^2.0.0" read-pkg "^3.0.0" +read-pkg-up@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" + dependencies: + find-up "^3.0.0" + read-pkg "^3.0.0" + read-pkg@^1.0.0, read-pkg@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -10064,16 +11306,7 @@ read@^1.0.7: dependencies: mute-stream "~0.0.4" -readable-stream@1.0, readable-stream@~1.0.31: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -10085,6 +11318,15 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@1.0, readable-stream@~1.0.31: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdir-enhanced@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/readdir-enhanced/-/readdir-enhanced-1.5.2.tgz#61463048690ac6a455b75b62fa78a88f8dc85e53" @@ -10615,10 +11857,18 @@ rgb-hex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-1.0.0.tgz#bfaf8cd9cd9164b5a26d71eb4f15a0965324b3c1" +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + rgb@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/rgb/-/rgb-0.1.0.tgz#be27b291e8feffeac1bd99729721bfa40fc037b5" +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + ric@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ric/-/ric-1.3.0.tgz#8e95042609ce8213548a83164d08e94fae94909f" @@ -10678,6 +11928,12 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + dependencies: + aproba "^1.1.1" + rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" @@ -10779,7 +12035,7 @@ sass-loader@^4.1.1: loader-utils "^0.2.15" object-assign "^4.1.0" -sax@^1.2.4, sax@~1.2.1: +sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -10819,6 +12075,21 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" +schema-utils@^0.4.4: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + scroll-behavior@^0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.9.tgz#ebfe0658455b82ad885b66195215416674dacce2" @@ -10877,6 +12148,10 @@ serialize-error@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" +serialize-javascript@^1.4.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" + serve-handler@3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-3.6.0.tgz#f4167c06d0a26c38ed753418230ed43a59adf9cb" @@ -11034,6 +12309,12 @@ signedsource@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + dependencies: + is-arrayish "^0.3.1" + sinon@^5.0.7: version "5.1.1" resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.1.1.tgz#19c59810ffb733ea6e76a28b94a71fc4c2f523b8" @@ -11050,6 +12331,28 @@ sisteransi@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" +size-limit@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/size-limit/-/size-limit-0.21.1.tgz#755ecd318a02570574ff7a815b88c6801f9a9995" + dependencies: + bytes "^3.0.0" + chalk "^2.4.1" + ci-job-number "^0.3.0" + compression-webpack-plugin "^2.0.0" + cosmiconfig "^5.0.7" + css-loader "^2.1.0" + escape-string-regexp "^1.0.5" + file-loader "^3.0.1" + globby "^8.0.1" + gzip-size "^5.0.0" + memory-fs "^0.4.1" + optimize-css-assets-webpack-plugin "^5.0.1" + read-pkg-up "^4.0.0" + style-loader "^0.23.1" + webpack "^4.28.2" + webpack-bundle-analyzer "^3.0.3" + yargs "^12.0.5" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -11206,6 +12509,10 @@ source-list-map@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" @@ -11235,6 +12542,13 @@ source-map-support@~0.2.8: dependencies: source-map "0.1.32" +source-map-support@~0.5.6: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -11362,6 +12676,16 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + dependencies: + figgy-pudding "^3.5.1" + +stable@~0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + stack-trace@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -11470,6 +12794,13 @@ stream-cache@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/stream-cache/-/stream-cache-0.0.2.tgz#1ac5ad6832428ca55667dbdee395dad4e6db118f" +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + stream-http@^2.3.1, stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" @@ -11480,6 +12811,10 @@ stream-http@^2.3.1, stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -11615,6 +12950,21 @@ style-loader@^0.13.0: dependencies: loader-utils "^1.0.2" +style-loader@^0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" + dependencies: + loader-utils "^1.1.0" + schema-utils "^1.0.0" + +stylehacks@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.1.tgz#3186595d047ab0df813d213e51c8b94e0b9010f2" + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + supertap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e" @@ -11641,6 +12991,12 @@ supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + dependencies: + has-flag "^3.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -11653,6 +13009,25 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" +svgo@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" + dependencies: + coa "~2.0.1" + colors "~1.1.2" + css-select "^2.0.0" + css-select-base-adapter "~0.1.0" + css-tree "1.0.0-alpha.28" + css-url-regex "^1.1.0" + csso "^3.5.0" + js-yaml "^3.12.0" + mkdirp "~0.5.1" + object.values "^1.0.4" + sax "~1.2.4" + stable "~0.1.6" + unquote "~1.1.1" + util.promisify "~1.0.0" + svgo@~0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.4.5.tgz#ba56155fb1733728956c01b405221ee7e789a2a4" @@ -11741,6 +13116,10 @@ tapable@^0.1.8, tapable@~0.1.8: version "0.1.10" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" +tapable@^1.0.0, tapable@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" + tar-fs@^1.13.0: version "1.16.3" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" @@ -11824,6 +13203,27 @@ terminal-table@0.0.12: colors "^1.0.3" eastasianwidth "^0.1.0" +terser-webpack-plugin@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#7545da9ae5f4f9ae6a0ac961eb46f5e7c845cc26" + dependencies: + cacache "^11.0.2" + find-cache-dir "^2.0.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + terser "^3.8.1" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + +terser@^3.8.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + source-map-support "~0.5.6" + test-exclude@^4.2.0, test-exclude@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" @@ -11879,6 +13279,10 @@ timers-browserify@^2.0.2, timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + tiny-emitter@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c" @@ -12024,7 +13428,11 @@ trough@^1.0.0: dependencies: glob "^6.0.4" -tslib@^1.6.0: +tryer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + +tslib@^1.6.0, tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -12163,6 +13571,18 @@ uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" + dependencies: + imurmurhash "^0.1.4" + unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" @@ -12273,6 +13693,10 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -12284,6 +13708,10 @@ unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + update-check@1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28" @@ -12306,7 +13734,7 @@ update-notifier@^2.3.0: semver-diff "^2.0.0" xdg-basedir "^3.0.0" -uri-js@^4.2.1: +uri-js@^4.2.1, uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" dependencies: @@ -12364,7 +13792,7 @@ util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util.promisify@^1.0.0: +util.promisify@^1.0.0, util.promisify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" dependencies: @@ -12516,6 +13944,14 @@ watchpack@^0.2.1: chokidar "^1.0.0" graceful-fs "^4.1.2" +watchpack@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + wcwidth@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -12530,6 +13966,23 @@ webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" +webpack-bundle-analyzer@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.3.tgz#dbc7fff8f52058b6714a20fddf309d0790e3e0a0" + dependencies: + acorn "^5.7.3" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.10" + mkdirp "^0.5.1" + opener "^1.5.1" + ws "^6.0.0" + webpack-configurator@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/webpack-configurator/-/webpack-configurator-0.3.1.tgz#d16802afa674101a0cbfa6fc344d415c9649540b" @@ -12606,6 +14059,13 @@ webpack-sources@^0.2.0: source-list-map "^1.1.1" source-map "~0.5.3" +webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + webpack-stats-plugin@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.1.5.tgz#29e5f12ebfd53158d31d656a113ac1f7b86179d9" @@ -12646,6 +14106,35 @@ webpack@^1.13.3: watchpack "^0.2.1" webpack-core "~0.6.9" +webpack@^4.28.2: + version "4.28.4" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.28.4.tgz#1ddae6c89887d7efb752adf0c3cd32b9b07eacd0" + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-module-context" "1.7.11" + "@webassemblyjs/wasm-edit" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + acorn "^5.6.2" + acorn-dynamic-import "^3.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + micromatch "^3.1.8" + mkdirp "~0.5.0" + neo-async "^2.5.0" + node-libs-browser "^2.0.0" + schema-utils "^0.4.4" + tapable "^1.1.0" + terser-webpack-plugin "^1.1.0" + watchpack "^1.5.0" + webpack-sources "^1.3.0" + websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" @@ -12737,6 +14226,12 @@ wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +worker-farm@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + dependencies: + errno "~0.1.7" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -12801,6 +14296,12 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" +ws@^6.0.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.2.tgz#3cc7462e98792f0ac679424148903ded3b9c3ad8" + dependencies: + async-limiter "~1.0.0" + ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -12837,6 +14338,10 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -12851,6 +14356,13 @@ yaml-loader@^0.4.0: dependencies: js-yaml "^3.5.2" +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" @@ -12935,6 +14447,23 @@ yargs@8.0.1: y18n "^3.2.1" yargs-parser "^7.0.0" +yargs@^12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + dependencies: + cliui "^4.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^1.0.1" + os-locale "^3.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" + yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From 827537fea2bad82c4e93727f7fdbf9123a54e031 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 16:43:55 +1100 Subject: [PATCH 054/120] amend: use external size limit config file --- .size-limit | 10 ++++++++++ package.json | 12 +----------- 2 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 .size-limit diff --git a/.size-limit b/.size-limit new file mode 100644 index 00000000..254ccea1 --- /dev/null +++ b/.size-limit @@ -0,0 +1,10 @@ +[ + { + limit: "25 KB", + path: "packages/dataparcels/lib/index.js" + }, + { + limit: "30 KB", + path: "packages/react-dataparcels/lib/index.js" + } +] diff --git a/package.json b/package.json index 7edad929..685dab6b 100644 --- a/package.json +++ b/package.json @@ -36,15 +36,5 @@ }, "dependencies": { "babel-plugin-extract-flow-types": "^1.0.0" - }, - "size-limit": [ - { - "limit": "25 KB", - "path": "packages/dataparcels/lib/index.js" - }, - { - "limit": "30 KB", - "path": "packages/react-dataparcels/lib/index.js" - } - ] + } } From f5d1eda3d92cc70545b0276b608791ccb95323e3 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 17:09:40 +1100 Subject: [PATCH 055/120] add: ability for push and unshift to accept multiple args --- .../dataparcels-docs/src/docs/api/parcel/push.md | 2 +- .../src/docs/api/parcel/unshift.md | 2 +- .../src/docs/api/staticParcel/push.md | 2 +- .../src/docs/api/staticParcel/unshift.md | 2 +- .../dataparcels/src/change/ActionCreators.js | 8 ++++---- .../src/change/ChangeRequestReducer.js | 6 +++--- .../__test__/ChangeRequestReducerIndexed-test.js | 12 ++++++------ packages/dataparcels/src/parcel/Parcel.js | 4 ++-- .../parcel/__test__/IndexedParcelMethods-test.js | 16 +++++++++------- .../src/parcel/methods/IndexedChangeMethods.js | 8 ++++---- packages/dataparcels/src/parcelData/push.js | 8 +++++--- packages/dataparcels/src/parcelData/unshift.js | 8 +++++--- .../dataparcels/src/staticParcel/StaticParcel.js | 4 ++-- .../__test__/StaticIndexedSetMethods-test.js | 4 ++-- .../methods/StaticIndexedSetMethods.js | 8 ++++---- 15 files changed, 50 insertions(+), 44 deletions(-) diff --git a/packages/dataparcels-docs/src/docs/api/parcel/push.md b/packages/dataparcels-docs/src/docs/api/parcel/push.md index c61a8ed4..8148a42b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/push.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/push.md @@ -1,3 +1,3 @@ ```flow -push(value: *): void // only on IndexedParcels +push(...values: Array<*>): void // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/unshift.md b/packages/dataparcels-docs/src/docs/api/parcel/unshift.md index a896e692..1611c11e 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/unshift.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/unshift.md @@ -1,3 +1,3 @@ ```flow -unshift(value: *): void // only on IndexedParcels +unshift(...values: Array<*>): void // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/push.md b/packages/dataparcels-docs/src/docs/api/staticParcel/push.md index c61a8ed4..8148a42b 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/push.md +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/push.md @@ -1,3 +1,3 @@ ```flow -push(value: *): void // only on IndexedParcels +push(...values: Array<*>): void // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md b/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md index a896e692..1611c11e 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md +++ b/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md @@ -1,3 +1,3 @@ ```flow -unshift(value: *): void // only on IndexedParcels +unshift(...values: Array<*>): void // only on IndexedParcels ``` diff --git a/packages/dataparcels/src/change/ActionCreators.js b/packages/dataparcels/src/change/ActionCreators.js index 0aada7ab..383b3884 100644 --- a/packages/dataparcels/src/change/ActionCreators.js +++ b/packages/dataparcels/src/change/ActionCreators.js @@ -49,11 +49,11 @@ const insertBeforeSelf: Function = (value: *): Action => { }); }; -const push: Function = (value: *): Action => { +const push: Function = (values: Array<*>): Action => { return new Action({ type: "push", payload: { - value + values } }); }; @@ -140,11 +140,11 @@ const swapSelf: Function = (keyB: Key|Index): Action => { }); }; -const unshift: Function = (value: *): Action => { +const unshift: Function = (values: Array<*>): Action => { return new Action({ type: "unshift", payload: { - value + values } }); }; diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 0c22f0ec..e3782d49 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -32,12 +32,12 @@ const actionMap = { insertAfter: ({lastKey, value}) => insertAfter(lastKey, value), insertBefore: ({lastKey, value}) => insertBefore(lastKey, value), pop: () => pop(), - push: ({value}) => push(value), + push: ({values}) => push(...values), setData: parcelData => () => parcelData, setMeta: ({meta}) => setMeta(meta), set: ({value}) => setSelf(value), shift: () => shift(), - swap: ({lastKey, swapKey}) => { + swap: ({lastKey, swapKey}: any): ParcelDataEvaluator => { if(typeof swapKey === "undefined") { throw ReducerSwapKeyError(); } @@ -45,7 +45,7 @@ const actionMap = { }, swapNext: ({lastKey}) => swapNext(lastKey), swapPrev: ({lastKey}) => swapPrev(lastKey), - unshift: ({value}) => unshift(value) + unshift: ({values}) => unshift(...values) }; const parentActionMap = { diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js index 3b2a2dfe..ac8dbc7b 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js @@ -259,12 +259,12 @@ TestIndex([ type: "push", keyPath: [], payload: { - value: 3 + values: [3,4] } }, expectedData: { - value: [0,1,2,3], - child: [{key: "#a"},{key: "#b"}, {key: "#c"},{key: "#d"}], + value: [0,1,2,3,4], + child: [{key: "#a"},{key: "#b"}, {key: "#c"},{key: "#d"},{key: "#e"}], ...EXPECTED_KEY_AND_META } } @@ -430,12 +430,12 @@ TestIndex([ type: "unshift", keyPath: [], payload: { - value: 3 + values: [3,4] } }, expectedData: { - value: [3,0,1,2], - child: [{key: "#d"},{key: "#a"},{key: "#b"}, {key: "#c"}], + value: [3,4,0,1,2], + child: [{key: "#d"},{key: "#e"},{key: "#a"},{key: "#b"}, {key: "#c"}], ...EXPECTED_KEY_AND_META } } diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 84cff200..5cced170 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -315,7 +315,7 @@ export default class Parcel { ["1"]: (value: any) => this._methods.insertBeforeSelf(value), ["2"]: (key: Key|Index, value: any) => this._methods.insertBefore(key, value) }); - push = (value: any) => this._methods.push(value); + push = (...values: Array) => this._methods.push(...values); pop = () => this._methods.pop(); shift = () => this._methods.shift(); swap = overload({ @@ -330,7 +330,7 @@ export default class Parcel { ["0"]: () => this._methods.swapPrevSelf(), ["1"]: (key: Key|Index) => this._methods.swapPrev(key) }); - unshift = (value: any) => this._methods.unshift(value); + unshift = (...values: Array) => this._methods.unshift(...values); // Modify methods modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); diff --git a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js index bdb6ce73..724c66fe 100644 --- a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js @@ -204,13 +204,14 @@ test('IndexedParcel.push() should push', () => { var expectedData = { meta: {}, - value: [1,2,3,4], + value: [1,2,3,4,5], key: '^', child: [ {key: "#a"}, {key: "#b"}, {key: "#c"}, - {key: "#d"} + {key: "#d"}, + {key: "#e"} ] }; @@ -218,7 +219,7 @@ test('IndexedParcel.push() should push', () => { type: "push", keyPath: [], payload: { - value: 4 + values: [4,5] } }; @@ -228,7 +229,7 @@ test('IndexedParcel.push() should push', () => { expect(expectedData).toEqual(parcel.data); expect(expectedAction).toEqual(GetAction(changeRequest)); } - }).push(4); + }).push(4,5); }); test('IndexedParcel.pop() should pop', () => { @@ -464,10 +465,11 @@ test('IndexedParcel.unshift() should unshift', () => { var expectedData = { meta: {}, - value: [4,1,2,3], + value: [4,5,1,2,3], key: '^', child: [ {key: "#d"}, + {key: "#e"}, {key: "#a"}, {key: "#b"}, {key: "#c"} @@ -478,7 +480,7 @@ test('IndexedParcel.unshift() should unshift', () => { type: "unshift", keyPath: [], payload: { - value: 4 + values: [4,5] } }; @@ -488,5 +490,5 @@ test('IndexedParcel.unshift() should unshift', () => { expect(expectedData).toEqual(parcel.data); expect(expectedAction).toEqual(GetAction(changeRequest)); } - }).unshift(4); + }).unshift(4,5); }); diff --git a/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js b/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js index e4e411d3..f1b00f83 100644 --- a/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js @@ -18,8 +18,8 @@ export default (_this: Parcel, dispatch: Function): Object => ({ dispatch(ActionCreators.insertBefore(key, value)); }, - push: (value: *) => { - dispatch(ActionCreators.push(value)); + push: (...values: Array<*>) => { + dispatch(ActionCreators.push(values)); }, pop: () => { @@ -46,7 +46,7 @@ export default (_this: Parcel, dispatch: Function): Object => ({ dispatch(ActionCreators.swapPrev(key)); }, - unshift: (value: *) => { - dispatch(ActionCreators.unshift(value)); + unshift: (...values: Array<*>) => { + dispatch(ActionCreators.unshift(values)); } }); diff --git a/packages/dataparcels/src/parcelData/push.js b/packages/dataparcels/src/parcelData/push.js index 32afade6..523eda23 100644 --- a/packages/dataparcels/src/parcelData/push.js +++ b/packages/dataparcels/src/parcelData/push.js @@ -5,11 +5,13 @@ import updateChildKeys from './updateChildKeys'; import push from 'unmutable/lib/push'; -export default (newValue: *) => (parcelData: ParcelData): ParcelData => { +export default (...newValues: Array<*>) => (parcelData: ParcelData): ParcelData => { let {value, child, ...rest} = prepareChildKeys()(parcelData); + let emptyChildren = newValues.map(() => ({})); + return updateChildKeys()({ ...rest, - value: push(newValue)(value), - child: push({})(child) + value: push(...newValues)(value), + child: push(...emptyChildren)(child) }); }; diff --git a/packages/dataparcels/src/parcelData/unshift.js b/packages/dataparcels/src/parcelData/unshift.js index d687af79..43920a33 100644 --- a/packages/dataparcels/src/parcelData/unshift.js +++ b/packages/dataparcels/src/parcelData/unshift.js @@ -5,11 +5,13 @@ import updateChildKeys from './updateChildKeys'; import unshift from 'unmutable/lib/unshift'; -export default (newValue: *) => (parcelData: ParcelData): ParcelData => { +export default (...newValues: Array<*>) => (parcelData: ParcelData): ParcelData => { let {value, child, ...rest} = prepareChildKeys()(parcelData); + let emptyChildren = newValues.map(() => ({})); + return updateChildKeys()({ ...rest, - value: unshift(newValue)(value), - child: unshift({})(child) + value: unshift(...newValues)(value), + child: unshift(...emptyChildren)(child) }); }; diff --git a/packages/dataparcels/src/staticParcel/StaticParcel.js b/packages/dataparcels/src/staticParcel/StaticParcel.js index 0e730325..5f71baeb 100644 --- a/packages/dataparcels/src/staticParcel/StaticParcel.js +++ b/packages/dataparcels/src/staticParcel/StaticParcel.js @@ -187,13 +187,13 @@ export default class StaticParcel { // Indexed methods insertAfter = (key: Key|Index, value: any) => this._methods.insertAfter(key, value); insertBefore = (key: Key|Index, value: any) => this._methods.insertBefore(key, value); - push = (value: any) => this._methods.push(value); + push = (...values: Array) => this._methods.push(...values); pop = () => this._methods.pop(); shift = () => this._methods.shift(); swap = (keyA: Key|Index, keyB: Key|Index) => this._methods.swap(keyA, keyB); swapNext = (key: Key|Index) => this._methods.swapNext(key); swapPrev = (key: Key|Index) => this._methods.swapPrev(key); - unshift = (value: any) => this._methods.unshift(value); + unshift = (...values: Array) => this._methods.unshift(...values); // Type methods isChild = (): boolean => this._parcelTypes.isChild(); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js index d2027dbf..7e39269c 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js +++ b/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js @@ -22,7 +22,7 @@ test('StaticParcels push(value) should work', () => { value: [0,1,2] }); - expect(staticParcel.push(3).data.value).toEqual([0,1,2,3]); + expect(staticParcel.push(3,4).data.value).toEqual([0,1,2,3,4]); }); test('StaticParcels pop() should work', () => { @@ -70,5 +70,5 @@ test('StaticParcels unshift(value) should work', () => { value: [0,1,2] }); - expect(staticParcel.unshift(3).data.value).toEqual([3,0,1,2]); + expect(staticParcel.unshift(3,4).data.value).toEqual([3,4,0,1,2]); }); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js b/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js index 3a9901d4..8fb986ba 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js +++ b/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js @@ -36,10 +36,10 @@ export default (_this: StaticParcel) => ({ ); }, - push: (value: *): StaticParcel => { + push: (...values: Array<*>): StaticParcel => { _this._prepareChildKeys(); return _this._pipeSelf( - push(value) + push(...values) ); }, @@ -71,10 +71,10 @@ export default (_this: StaticParcel) => ({ ); }, - unshift: (value: *): StaticParcel => { + unshift: (...values: Array<*>): StaticParcel => { _this._prepareChildKeys(); return _this._pipeSelf( - unshift(value) + unshift(...values) ); } }); From 91f34c33e4d83e9d258bc58d09b83b0d44dbc32f Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 14 Jan 2019 17:34:01 +1100 Subject: [PATCH 056/120] test: improve Parcel.initialMeta tests --- .../src/parcel/__test__/ModifyMethods-test.js | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 59969638..894b2944 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -240,44 +240,52 @@ test('Parcel.modifyShapeUp() should modify value', () => { }); test('Parcel.initialMeta() should work', () => { - expect.assertions(3); - - let meta = {a:1, b:2}; + let handleChange = jest.fn(); - var data = { + let parcel = new Parcel({ value: 123, - handleChange: (parcel: Parcel) => { - let {meta} = parcel.data; - expect({a:1, b:3}).toEqual(meta); - expect({a:1, b:3}).toEqual(parcel.initialMeta().meta); - } - }; + handleChange + }).initialMeta({a:1, b:2}); + + expect(parcel.meta).toEqual({a:1, b:2}); + + parcel.setMeta({b: 3}); - let parcel = new Parcel(data).initialMeta(meta); - expect(meta).toEqual(parcel.meta); - parcel.setMeta({ - b: 3 + expect(handleChange.mock.calls[0][0].data).toEqual({ + value: 123, + meta: { + a: 1, + b: 3 + }, + child: undefined, + key: "^" }); }); test('Parcel.initialMeta() should merge', () => { - expect.assertions(2); - - let meta = {a:1, b:2}; - let meta2 = {b:1, c:3}; // this b will be ignored because it will have already been set by the time this is applied + let handleChange = jest.fn(); - var data = { + let parcel = new Parcel({ value: 123, - handleChange: (parcel: Parcel) => { - let {meta} = parcel.data; - expect({a:1, b:3, c:3}).toEqual(meta); - } - }; + handleChange + }) + .initialMeta({a:1, b:2}) + .initialMeta({b:3, c:4}) + + expect(parcel.meta).toEqual({a:1, b:2, c:4}); - let parcel = new Parcel(data).initialMeta(meta).initialMeta(meta2); - expect({a:1, b:2, c:3}).toEqual(parcel.meta); - parcel.setMeta({ - b: 3 + parcel.setMeta({d: 5}); + + expect(handleChange.mock.calls[0][0].data).toEqual({ + value: 123, + meta: { + a: 1, + b: 2, + c: 4, + d: 5 + }, + child: undefined, + key: "^" }); }); From 653a9fc344ce28dc44a5a3fefd395f29a092de0b Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:26:30 +1100 Subject: [PATCH 057/120] fix: prevent value from being removed if initialMeta is set --- .../src/parcel/__test__/ModifyMethods-test.js | 42 ++++++++++++++++- .../src/parcel/methods/ModifyMethods.js | 46 +++++++++---------- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 894b2944..d8096921 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -247,7 +247,15 @@ test('Parcel.initialMeta() should work', () => { handleChange }).initialMeta({a:1, b:2}); - expect(parcel.meta).toEqual({a:1, b:2}); + expect(parcel.data).toEqual({ + value: 123, + meta: { + a: 1, + b: 2 + }, + child: undefined, + key: "^" + }); parcel.setMeta({b: 3}); @@ -272,7 +280,16 @@ test('Parcel.initialMeta() should merge', () => { .initialMeta({a:1, b:2}) .initialMeta({b:3, c:4}) - expect(parcel.meta).toEqual({a:1, b:2, c:4}); + expect(parcel.data).toEqual({ + value: 123, + meta: { + a: 1, + b: 2, + c: 4 + }, + child: undefined, + key: "^" + }); parcel.setMeta({d: 5}); @@ -289,6 +306,27 @@ test('Parcel.initialMeta() should merge', () => { }); }); +test('Parcel.initialMeta() should do nothing to data if all meta keys are already set', () => { + let handleChange = jest.fn(); + + let parcel = new Parcel({ + value: 123, + handleChange + }) + .initialMeta({a:1, b:2}) + .initialMeta({a:1, b:2}) // do nothing to data + + expect(parcel.data).toEqual({ + value: 123, + meta: { + a: 1, + b: 2 + }, + child: undefined, + key: "^" + }); +}); + test('Sanity check: A big strange test of a big strange chain of deep updatery stuff', () => { let handleChange = jest.fn(); diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 5ed01e1d..32984662 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -15,9 +15,7 @@ import filterNot from 'unmutable/lib/filterNot'; import has from 'unmutable/lib/has'; import isEmpty from 'unmutable/lib/isEmpty'; import merge from 'unmutable/lib/merge'; -import set from 'unmutable/lib/set'; -import setIn from 'unmutable/lib/setIn'; -import pipe from 'unmutable/lib/util/pipe'; +import update from 'unmutable/lib/update'; import pipeWith from 'unmutable/lib/util/pipeWith'; let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; @@ -114,34 +112,36 @@ export default (_this: Parcel): Object => ({ }); }, - initialMeta: (initialMeta: ParcelMeta = {}): Parcel => { + initialMeta: (initialMeta: ParcelMeta): Parcel => { Types(`initialMeta()`, `initialMeta`, `object`)(initialMeta); let {meta} = _this._parcelData; - let partialMetaToSet = pipeWith( + let partialMetaToSet: {[key: string]: any} = pipeWith( initialMeta, filterNot((value, key) => has(key)(meta)) ); - let metaSetter = isEmpty()(partialMetaToSet) - ? ii => ii - : pipe( - setIn(['parcelData', 'meta'], merge(partialMetaToSet)(meta)), - set('onDispatch', (changeRequest: ChangeRequest) => { - _this.batch((parcel: Parcel) => { - parcel.setMeta(partialMetaToSet); - parcel.dispatch(changeRequest); - }); - }) - ); + let create = (other = {}) => _this._create({ + id: _this._id.pushModifier('im'), + ...other + }); - return pipeWith( - { - id: _this._id.pushModifier('im') - }, - metaSetter, - _this._create - ); + if(isEmpty()(partialMetaToSet)) { + return create(); + } + + return create({ + parcelData: pipeWith( + _this._parcelData, + update('meta', merge(partialMetaToSet)) + ), + onDispatch: (changeRequest: ChangeRequest) => { + _this.batch((parcel: Parcel) => { + parcel.setMeta(partialMetaToSet); + parcel.dispatch(changeRequest); + }); + } + }); }, _boundarySplit: ({handleChange}: *): Parcel => { From 4bd114dc3539becc1c28d8f6555d317d843f66fe Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:27:35 +1100 Subject: [PATCH 058/120] refactor: initialMeta must be passed an object --- packages/dataparcels/src/parcel/Parcel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 84cff200..497652f5 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -338,7 +338,7 @@ export default class Parcel { modifyShapeDown = (updater: Function): Parcel => this._methods.modifyShapeDown(updater); modifyShapeUp = (updater: Function): Parcel => this._methods.modifyShapeUp(updater); modifyChange = (batcher: ParcelBatcher): Parcel => this._methods.modifyChange(batcher); - initialMeta = (initialMeta: ParcelMeta = {}): Parcel => this._methods.initialMeta(initialMeta); + initialMeta = (initialMeta: ParcelMeta): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); // Type methods From 1a9cf665f78dc2a6db30181863e4cdecd89a551b Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:41:38 +1100 Subject: [PATCH 059/120] amend: rename StaticParcel to ParcelShape --- .../src/component/APINavigation.jsx | 2 +- packages/dataparcels-docs/src/content/API.js | 2 +- .../src/docs/api/parcelShape/ParcelShape.md | 37 ++++ .../{staticParcel => parcelShape}/children.md | 0 .../src/docs/api/parcelShape/data.md | 11 ++ .../{staticParcel => parcelShape}/delete.md | 0 .../{staticParcel => parcelShape}/deleteIn.md | 0 .../src/docs/api/parcelShape/get.md | 38 ++++ .../{staticParcel => parcelShape}/getIn.md | 0 .../api/{staticParcel => parcelShape}/has.md | 0 .../insertAfter.md | 0 .../insertBefore.md | 0 .../src/docs/api/parcelShape/isChild.md | 9 + .../src/docs/api/parcelShape/isElement.md | 9 + .../src/docs/api/parcelShape/isIndexed.md | 9 + .../src/docs/api/parcelShape/isParent.md | 9 + .../src/docs/api/parcelShape/isTopLevel.md | 7 + .../src/docs/api/parcelShape/key.md | 7 + .../api/{staticParcel => parcelShape}/meta.md | 2 +- .../docs/api/parcelShape/modifyShapeDown.md | 3 + .../src/docs/api/parcelShape/modifyShapeUp.md | 3 + .../api/{staticParcel => parcelShape}/pop.md | 0 .../api/{staticParcel => parcelShape}/push.md | 0 .../api/{staticParcel => parcelShape}/set.md | 0 .../{staticParcel => parcelShape}/setIn.md | 0 .../{staticParcel => parcelShape}/setMeta.md | 0 .../{staticParcel => parcelShape}/shift.md | 0 .../api/{staticParcel => parcelShape}/size.md | 0 .../api/{staticParcel => parcelShape}/swap.md | 0 .../{staticParcel => parcelShape}/swapNext.md | 0 .../{staticParcel => parcelShape}/swapPrev.md | 0 .../{staticParcel => parcelShape}/toArray.md | 0 .../src/docs/api/parcelShape/toConsole.md | 5 + .../{staticParcel => parcelShape}/toObject.md | 0 .../{staticParcel => parcelShape}/unshift.md | 0 .../{staticParcel => parcelShape}/update.md | 0 .../{staticParcel => parcelShape}/updateIn.md | 0 .../updateShape.md | 0 .../updateShapeIn.md | 0 .../{staticParcel => parcelShape}/value.md | 2 +- .../src/docs/api/staticParcel/StaticParcel.md | 37 ---- .../src/docs/api/staticParcel/data.md | 11 -- .../src/docs/api/staticParcel/get.md | 38 ---- .../src/docs/api/staticParcel/isChild.md | 9 - .../src/docs/api/staticParcel/isElement.md | 9 - .../src/docs/api/staticParcel/isIndexed.md | 9 - .../src/docs/api/staticParcel/isParent.md | 9 - .../src/docs/api/staticParcel/isTopLevel.md | 7 - .../src/docs/api/staticParcel/key.md | 7 - .../docs/api/staticParcel/modifyShapeDown.md | 3 - .../docs/api/staticParcel/modifyShapeUp.md | 3 - .../src/docs/api/staticParcel/toConsole.md | 5 - .../src/pages/api/ParcelShape.jsx | 134 +++++++++++++ .../src/pages/api/StaticParcel.jsx | 134 ------------- packages/dataparcels/src/errors/Errors.js | 2 +- packages/dataparcels/src/index.js | 10 +- packages/dataparcels/src/parcel/Parcel.js | 8 +- .../src/parcel/__test__/ModifyMethods-test.js | 24 +-- .../__test__/ParcelChangeMethods-test.js | 6 +- .../__test__/ParentChangeMethods-test.js | 10 +- .../src/parcel/methods/ModifyMethods.js | 12 +- .../src/parcel/methods/ParcelChangeMethods.js | 10 +- .../src/parcel/methods/ParentChangeMethods.js | 6 +- .../ParcelShape.js} | 78 ++++---- .../__test__/ParcelShape-test.js} | 22 +-- .../ParcelShapeIndexedSetMethods-test.js | 74 +++++++ .../ParcelShapeParentGetMethods-test.js | 147 ++++++++++++++ .../ParcelShapeParentSetMethods-test.js} | 58 +++--- .../__test__/ParcelShapeSetMethods-test.js} | 74 +++---- .../__test__/ParcelShapeTypes-test.js | 181 ++++++++++++++++++ .../methods/ParcelShapeIndexedSetMethods.js} | 22 +-- .../methods/ParcelShapeParentGetMethods.js} | 24 +-- .../methods/ParcelShapeParentSetMethods.js} | 16 +- .../methods/ParcelShapeSetMethods.js} | 30 +-- .../__test__/StaticIndexedSetMethods-test.js | 74 ------- .../__test__/StaticParcelTypes-test.js | 181 ------------------ .../__test__/StaticParentGetMethods-test.js | 147 -------------- packages/dataparcels/src/types/Types.js | 18 +- .../dataparcels/src/util/FilterMethods.js | 4 +- packages/react-dataparcels/src/index.js | 10 +- 80 files changed, 909 insertions(+), 909 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/children.md (100%) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/data.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/delete.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/deleteIn.md (100%) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/get.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/getIn.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/has.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/insertAfter.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/insertBefore.md (100%) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/isElement.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/isIndexed.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/isParent.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/isTopLevel.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/key.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/meta.md (55%) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/pop.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/push.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/set.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/setIn.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/setMeta.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/shift.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/size.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/swap.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/swapNext.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/swapPrev.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/toArray.md (100%) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/toConsole.md rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/toObject.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/unshift.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/update.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/updateIn.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/updateShape.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/updateShapeIn.md (100%) rename packages/dataparcels-docs/src/docs/api/{staticParcel => parcelShape}/value.md (69%) delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/data.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/get.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/key.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md delete mode 100644 packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md create mode 100644 packages/dataparcels-docs/src/pages/api/ParcelShape.jsx delete mode 100644 packages/dataparcels-docs/src/pages/api/StaticParcel.jsx rename packages/dataparcels/src/{staticParcel/StaticParcel.js => parcelShape/ParcelShape.js} (60%) rename packages/dataparcels/src/{staticParcel/__test__/StaticParcel-test.js => parcelShape/__test__/ParcelShape-test.js} (58%) create mode 100644 packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js create mode 100644 packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentGetMethods-test.js rename packages/dataparcels/src/{staticParcel/__test__/StaticParentSetMethods-test.js => parcelShape/__test__/ParcelShapeParentSetMethods-test.js} (63%) rename packages/dataparcels/src/{staticParcel/__test__/StaticSetMethods-test.js => parcelShape/__test__/ParcelShapeSetMethods-test.js} (59%) create mode 100644 packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js rename packages/dataparcels/src/{staticParcel/methods/StaticIndexedSetMethods.js => parcelShape/methods/ParcelShapeIndexedSetMethods.js} (74%) rename packages/dataparcels/src/{staticParcel/methods/StaticParentGetMethods.js => parcelShape/methods/ParcelShapeParentGetMethods.js} (71%) rename packages/dataparcels/src/{staticParcel/methods/StaticParentSetMethods.js => parcelShape/methods/ParcelShapeParentSetMethods.js} (72%) rename packages/dataparcels/src/{staticParcel/methods/StaticSetMethods.js => parcelShape/methods/ParcelShapeSetMethods.js} (61%) delete mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js delete mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js delete mode 100644 packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js diff --git a/packages/dataparcels-docs/src/component/APINavigation.jsx b/packages/dataparcels-docs/src/component/APINavigation.jsx index a808c5ea..85965e5f 100644 --- a/packages/dataparcels-docs/src/component/APINavigation.jsx +++ b/packages/dataparcels-docs/src/component/APINavigation.jsx @@ -9,7 +9,7 @@ export default () => - ParcelHoc - ParcelBoundary - ParcelBoundaryHoc - - StaticParcel + - ParcelShape - ChangeRequest - Action ; diff --git a/packages/dataparcels-docs/src/content/API.js b/packages/dataparcels-docs/src/content/API.js index 596b95fe..02c5f9e9 100644 --- a/packages/dataparcels-docs/src/content/API.js +++ b/packages/dataparcels-docs/src/content/API.js @@ -59,5 +59,5 @@ export default () => } image={IconParcelBoundaryHoc} /> - See also: StaticParcel, ChangeRequest, Action. + See also: ParcelShape, ChangeRequest, Action. ; diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md new file mode 100644 index 00000000..98ef8fab --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md @@ -0,0 +1,37 @@ +import Link from 'component/Link'; +import Param from 'component/Param'; +import ApiPageIcon from 'component/ApiPageIcon'; +import ParcelCreateReact from 'docs/notes/ParcelCreateReact.md'; +import IconParcel from 'content/parcel.gif'; + +# ParcelShape + +{IconParcel} + +ParcelShape is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter its data. + +These exist to be used with shape updaters, to provide a safe way to alter the shape of data in a Parcel. +ParcelShape's methods are a subset of Parcel's methods. + +```js +import {ParcelShape} from 'dataparcels'; +import {ParcelShape} from 'react-dataparcels'; +``` + +```flow +new ParcelShape(value?: any); +``` + +* + The value you want to put in the ParcelShape. This value will be changed immutably when change methods are called on the ParcelShape. The data type of the `value` will determine the type of ParcelShape that will be created, and will determine which methods you can use to change the value. Please read Parcel types for more info. + +```js +// creates a Parcel that contains a value of 123 +let parcelShape = new ParcelShape(123); +``` + +## Example Usage + +ParcelShapes are used in a very similar way to [Immutable.js Maps and Lists](https://facebook.github.io/immutable-js/docs/), by calling methods that return new and updated ParcelShapes. + +TODO diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/children.md b/packages/dataparcels-docs/src/docs/api/parcelShape/children.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/children.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/children.md diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/data.md b/packages/dataparcels-docs/src/docs/api/parcelShape/data.md new file mode 100644 index 00000000..2a2e9eed --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/data.md @@ -0,0 +1,11 @@ +import Link from 'component/Link'; + +```flow +data: Object +``` + +Returns an object containing the ParcelShape's data, which includes: +* `value` - The ParcelShape's value +* `meta` - The ParcelShape's meta object +* `key` - The ParcelShape's key +* `child` - The ParcelShape's child information, which includes any `meta`, `key` and `child` data related to the `value`s children. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/delete.md b/packages/dataparcels-docs/src/docs/api/parcelShape/delete.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/delete.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/delete.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/deleteIn.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/get.md b/packages/dataparcels-docs/src/docs/api/parcelShape/get.md new file mode 100644 index 00000000..78b27485 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/get.md @@ -0,0 +1,38 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + +```flow +get(key: string|number): ParcelShape // only on ParentParcels +get(key: string|number, notSetValue: any): ParcelShape // only on ParentParcels +``` + +Returns a ParcelShape containing the value associated with the provided key / index. +If the key / index doesn't exist, a ParcelShape with a value of `notSetValue` will be returned. +If `notSetValue` is not provided then a ParcelShape with a value of + `undefined` will be returned. + +```js +let value = { + abc: 123, + def: 456 +}; +let parcelShape = new ParcelShape(value); +parcelShape.get('abc').value; // returns 123 +parcelShape.get('xyz').value; // returns undefined +parcelShape.get('xyz', 789).value; // returns 789 +``` + +#### get() with indexed values + +When called on a ParcelShape with an indexed value, such as an array, `get()` can accept an `index` or a `key`. +- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. +- `key` (string) is used to get a specific value by its unique key within the ParcelShape. + + + +```js +let value = ['abc', 'def', 'ghi']; +let parcelShape = new ParcelShape(value); +parcelShape.get(0).value; // returns 'abc' +parcelShape.get(-1).value; // returns 'ghi' +parcelShape.get('#a').value; // returns 'abc' +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/getIn.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/has.md b/packages/dataparcels-docs/src/docs/api/parcelShape/has.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/has.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/has.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md b/packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/insertAfter.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md b/packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/insertBefore.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md new file mode 100644 index 00000000..438c96d4 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isChild(): boolean +``` + +Returns true if the ParcelShapes is a child parcel. Read Parcel types for more info. + +When a ParcelShape is a child parcel, it allows the use of child methods. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isElement.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isElement.md new file mode 100644 index 00000000..6f8ca285 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isElement.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isElement(): boolean +``` + +Returns true if the ParcelShape is an element parcel. Read Parcel types for more info. + +When a ParcelShape is an element parcel, it allows the use of element methods. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isIndexed.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isIndexed.md new file mode 100644 index 00000000..435fd902 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isIndexed.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isIndexed(): boolean +``` + +Returns true if the ParcelShape is an indexed parcel. Read Parcel types for more info. + +When a ParcelShape is an indexed parcel, it allows the use of indexed methods. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isParent.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isParent.md new file mode 100644 index 00000000..7056835a --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isParent.md @@ -0,0 +1,9 @@ +import Link from 'component/Link'; + +```flow +isParent(): boolean +``` + +Returns true if the ParcelShape is a parent parcel. Read Parcel types for more info. + +When a ParcelShape is a parent parcel, it allows the use of parent methods. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isTopLevel.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isTopLevel.md new file mode 100644 index 00000000..f01d0258 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isTopLevel.md @@ -0,0 +1,7 @@ +import Link from 'component/Link'; + +```flow +isTopLevel(): boolean +``` + +Returns true if the ParcelShape is a top level parcel. Read Parcel types for more info. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/key.md b/packages/dataparcels-docs/src/docs/api/parcelShape/key.md new file mode 100644 index 00000000..ebe60278 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/key.md @@ -0,0 +1,7 @@ +import Link from 'component/Link'; + +```flow +key: string +``` + +Returns the ParcelShape's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/meta.md b/packages/dataparcels-docs/src/docs/api/parcelShape/meta.md similarity index 55% rename from packages/dataparcels-docs/src/docs/api/staticParcel/meta.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/meta.md index a2dfeb30..97db82be 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/meta.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/meta.md @@ -3,4 +3,4 @@ import ParcelMeta from 'docs/notes/ParcelMeta.md'; ```flow meta: Object ``` -Returns an object containing the StaticParcels's meta data. +Returns an object containing the ParcelShapes's meta data. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md new file mode 100644 index 00000000..579c550d --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): ParcelShape +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md new file mode 100644 index 00000000..579c550d --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md @@ -0,0 +1,3 @@ +```flow +modifyShapeDown(updater: Function): ParcelShape +``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/pop.md b/packages/dataparcels-docs/src/docs/api/parcelShape/pop.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/pop.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/pop.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/push.md b/packages/dataparcels-docs/src/docs/api/parcelShape/push.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/push.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/push.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/set.md b/packages/dataparcels-docs/src/docs/api/parcelShape/set.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/set.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/set.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/setIn.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md b/packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/setMeta.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/shift.md b/packages/dataparcels-docs/src/docs/api/parcelShape/shift.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/shift.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/shift.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/size.md b/packages/dataparcels-docs/src/docs/api/parcelShape/size.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/size.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/size.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swap.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swap.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/swap.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/swap.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/swapNext.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/swapPrev.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md b/packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/toArray.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/toConsole.md b/packages/dataparcels-docs/src/docs/api/parcelShape/toConsole.md new file mode 100644 index 00000000..8fd3e1d9 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/toConsole.md @@ -0,0 +1,5 @@ +```flow +toConsole(): void +``` + +Outputs the ParcelShape's data to the console. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md b/packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/toObject.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md b/packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/unshift.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/update.md b/packages/dataparcels-docs/src/docs/api/parcelShape/update.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/update.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/update.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/updateIn.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/updateShape.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md similarity index 100% rename from packages/dataparcels-docs/src/docs/api/staticParcel/updateShapeIn.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/value.md b/packages/dataparcels-docs/src/docs/api/parcelShape/value.md similarity index 69% rename from packages/dataparcels-docs/src/docs/api/staticParcel/value.md rename to packages/dataparcels-docs/src/docs/api/parcelShape/value.md index b976c555..2f9a46c5 100644 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/value.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/value.md @@ -4,4 +4,4 @@ import IndexedKeys from 'docs/notes/IndexedKeys.md'; value: any ``` -Returns the StaticParcel's value. +Returns the ParcelShape's value. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md deleted file mode 100644 index 4fcbd829..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/StaticParcel.md +++ /dev/null @@ -1,37 +0,0 @@ -import Link from 'component/Link'; -import Param from 'component/Param'; -import ApiPageIcon from 'component/ApiPageIcon'; -import ParcelCreateReact from 'docs/notes/ParcelCreateReact.md'; -import IconParcel from 'content/parcel.gif'; - -# StaticParcel - -{IconParcel} - -StaticParcel is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter it's data. - -These exist to be used with shape updaters, to provide a safe way to alter the shape of data in a Parcel. -Its methods a subset of Parcel's methods. - -```js -import {StaticParcel} from 'dataparcels'; -import {StaticParcel} from 'react-dataparcels'; -``` - -```flow -new StaticParcel(value?: any); -``` - -* - The value you want to put in the StaticParcel. This value will be changed immutably when change methods are called on the StaticParcel. The data type of the `value` will determine the type of StaticParcel that will be created, and will determine which methods you can use to change the value. Please read Parcel types for more info. - -```js -// creates a Parcel that contains a value of 123 -let staticParcel = new StaticParcel(123); -``` - -## Example Usage - -StaticParcels are used in a very similar way to [Immutable.js Maps and Lists](https://facebook.github.io/immutable-js/docs/), by calling methods that return new and updated StaticParcels. - -TODO diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/data.md b/packages/dataparcels-docs/src/docs/api/staticParcel/data.md deleted file mode 100644 index f7f5eef4..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/data.md +++ /dev/null @@ -1,11 +0,0 @@ -import Link from 'component/Link'; - -```flow -data: Object -``` - -Returns an object containing the StaticParcel's data, which includes: -* `value` - The StaticParcel's value -* `meta` - The StaticParcel's meta object -* `key` - The StaticParcel's key -* `child` - The StaticParcel's child information, which includes any `meta`, `key` and `child` data related to the `value`s children. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/get.md b/packages/dataparcels-docs/src/docs/api/staticParcel/get.md deleted file mode 100644 index 02e0085e..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/get.md +++ /dev/null @@ -1,38 +0,0 @@ -import IndexedKeys from 'docs/notes/IndexedKeys.md'; - -```flow -get(key: string|number): StaticParcel // only on ParentParcels -get(key: string|number, notSetValue: any): StaticParcel // only on ParentParcels -``` - -Returns a StaticParcel containing the value associated with the provided key / index. -If the key / index doesn't exist, a StaticParcel with a value of `notSetValue` will be returned. -If `notSetValue` is not provided then a StaticParcel with a value of - `undefined` will be returned. - -```js -let value = { - abc: 123, - def: 456 -}; -let staticParcel = new StaticParcel(value); -staticParcel.get('abc').value; // returns 123 -staticParcel.get('xyz').value; // returns undefined -staticParcel.get('xyz', 789).value; // returns 789 -``` - -#### get() with indexed values - -When called on a StaticParcel with an indexed value, such as an array, `get()` can accept an `index` or a `key`. -- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. -- `key` (string) is used to get a specific value by its unique key within the StaticParcel. - - - -```js -let value = ['abc', 'def', 'ghi']; -let staticParcel = new StaticParcel(value); -staticParcel.get(0).value; // returns 'abc' -staticParcel.get(-1).value; // returns 'ghi' -staticParcel.get('#a').value; // returns 'abc' -``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md deleted file mode 100644 index b8f5ca63..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/isChild.md +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'component/Link'; - -```flow -isChild(): boolean -``` - -Returns true if the StaticParcels is a child parcel. Read Parcel types for more info. - -When a StaticParcel is a child parcel, it allows the use of child methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md deleted file mode 100644 index 9c883bc1..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/isElement.md +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'component/Link'; - -```flow -isElement(): boolean -``` - -Returns true if the StaticParcel is an element parcel. Read Parcel types for more info. - -When a StaticParcel is an element parcel, it allows the use of element methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md deleted file mode 100644 index 408b5036..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/isIndexed.md +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'component/Link'; - -```flow -isIndexed(): boolean -``` - -Returns true if the StaticParcel is an indexed parcel. Read Parcel types for more info. - -When a StaticParcel is an indexed parcel, it allows the use of indexed methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md deleted file mode 100644 index 19807099..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/isParent.md +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'component/Link'; - -```flow -isParent(): boolean -``` - -Returns true if the StaticParcel is a parent parcel. Read Parcel types for more info. - -When a StaticParcel is a parent parcel, it allows the use of parent methods. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md b/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md deleted file mode 100644 index d7bb94ba..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/isTopLevel.md +++ /dev/null @@ -1,7 +0,0 @@ -import Link from 'component/Link'; - -```flow -isTopLevel(): boolean -``` - -Returns true if the StaticParcel is a top level parcel. Read Parcel types for more info. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/key.md b/packages/dataparcels-docs/src/docs/api/staticParcel/key.md deleted file mode 100644 index 824e31a9..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/key.md +++ /dev/null @@ -1,7 +0,0 @@ -import Link from 'component/Link'; - -```flow -key: string -``` - -Returns the StaticParcel's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md deleted file mode 100644 index eb7160d6..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeDown.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyShapeDown(updater: Function): StaticParcel -``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md deleted file mode 100644 index eb7160d6..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/modifyShapeUp.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyShapeDown(updater: Function): StaticParcel -``` diff --git a/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md b/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md deleted file mode 100644 index 93157220..00000000 --- a/packages/dataparcels-docs/src/docs/api/staticParcel/toConsole.md +++ /dev/null @@ -1,5 +0,0 @@ -```flow -toConsole(): void -``` - -Outputs the StaticParcel's data to the console. diff --git a/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx b/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx new file mode 100644 index 00000000..2e0c70fd --- /dev/null +++ b/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx @@ -0,0 +1,134 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import ApiPage from 'component/ApiPage'; +import Markdown_ParcelShape from 'docs/api/parcelShape/ParcelShape.md'; +import Markdown_value from 'docs/api/parcelShape/value.md'; +import Markdown_meta from 'docs/api/parcelShape/meta.md'; +import Markdown_data from 'docs/api/parcelShape/data.md'; +import Markdown_key from 'docs/api/parcelShape/key.md'; +import Markdown_get from 'docs/api/parcelShape/get.md'; +import Markdown_getIn from 'docs/api/parcelShape/getIn.md'; +import Markdown_children from 'docs/api/parcelShape/children.md'; +import Markdown_toObject from 'docs/api/parcelShape/toObject.md'; +import Markdown_toArray from 'docs/api/parcelShape/toArray.md'; +import Markdown_has from 'docs/api/parcelShape/has.md'; +import Markdown_size from 'docs/api/parcelShape/size.md'; +import Markdown_set from 'docs/api/parcelShape/set.md'; +import Markdown_setIn from 'docs/api/parcelShape/setIn.md'; +import Markdown_update from 'docs/api/parcelShape/update.md'; +import Markdown_updateShape from 'docs/api/parcelShape/updateShape.md'; +import Markdown_updateIn from 'docs/api/parcelShape/updateIn.md'; +import Markdown_updateShapeIn from 'docs/api/parcelShape/updateShapeIn.md'; +import Markdown_delete from 'docs/api/parcelShape/delete.md'; +import Markdown_deleteIn from 'docs/api/parcelShape/deleteIn.md'; +import Markdown_insertAfter from 'docs/api/parcelShape/insertAfter.md'; +import Markdown_insertBefore from 'docs/api/parcelShape/insertBefore.md'; +import Markdown_pop from 'docs/api/parcelShape/pop.md'; +import Markdown_push from 'docs/api/parcelShape/push.md'; +import Markdown_shift from 'docs/api/parcelShape/shift.md'; +import Markdown_swap from 'docs/api/parcelShape/swap.md'; +import Markdown_swapNext from 'docs/api/parcelShape/swapNext.md'; +import Markdown_swapPrev from 'docs/api/parcelShape/swapPrev.md'; +import Markdown_unshift from 'docs/api/parcelShape/unshift.md'; +import Markdown_setMeta from 'docs/api/parcelShape/setMeta.md'; +import Markdown_isChild from 'docs/api/parcelShape/isChild.md'; +import Markdown_isElement from 'docs/api/parcelShape/isElement.md'; +import Markdown_isIndexed from 'docs/api/parcelShape/isIndexed.md'; +import Markdown_isParent from 'docs/api/parcelShape/isParent.md'; +import Markdown_isTopLevel from 'docs/api/parcelShape/isTopLevel.md'; +import Markdown_toConsole from 'docs/api/parcelShape/toConsole.md'; + +const md = { + _desc: Markdown_ParcelShape, + value: Markdown_value, + meta: Markdown_meta, + data: Markdown_data, + key: Markdown_key, + get: Markdown_get, + getIn: Markdown_getIn, + children: Markdown_children, + toObject: Markdown_toObject, + toArray: Markdown_toArray, + has: Markdown_has, + size: Markdown_size, + set: Markdown_set, + setIn: Markdown_setIn, + update: Markdown_update, + updateShape: Markdown_updateShape, + updateIn: Markdown_updateIn, + updateShapeIn: Markdown_updateShapeIn, + delete: Markdown_delete, + deleteIn: Markdown_deleteIn, + insertAfter: Markdown_insertAfter, + insertBefore: Markdown_insertBefore, + pop: Markdown_pop, + push: Markdown_push, + shift: Markdown_shift, + swap: Markdown_swap, + swapNext: Markdown_swapNext, + swapPrev: Markdown_swapPrev, + unshift: Markdown_unshift, + setMeta: Markdown_setMeta, + isChild: Markdown_isChild, + isElement: Markdown_isElement, + isIndexed: Markdown_isIndexed, + isParent: Markdown_isParent, + isTopLevel: Markdown_isTopLevel, + toConsole: Markdown_toConsole +} + +const api = ` +# Properties +value +meta +data +key + +# Parent methods +get() +getIn() +children() +toObject() +toArray() +has() +size() + +# Set methods +set() +setIn() +delete() +deleteIn() +update() +updateShape() +updateIn() +updateShapeIn() + +# Indexed & element change methods +insertAfter() +insertBefore() +push() +pop() +shift() +swap() +swapNext() +swapPrev() +unshift() + +# Type methods +isChild() +isElement() +isIndexed() +isParent() +isTopLevel() + +# Debug methods +toConsole() + +`; + +export default () => ; diff --git a/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx b/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx deleted file mode 100644 index 85e7e2b3..00000000 --- a/packages/dataparcels-docs/src/pages/api/StaticParcel.jsx +++ /dev/null @@ -1,134 +0,0 @@ -// @flow -import type {Node} from 'react'; -import React from 'react'; -import ApiPage from 'component/ApiPage'; -import Markdown_StaticParcel from 'docs/api/staticParcel/StaticParcel.md'; -import Markdown_value from 'docs/api/staticParcel/value.md'; -import Markdown_meta from 'docs/api/staticParcel/meta.md'; -import Markdown_data from 'docs/api/staticParcel/data.md'; -import Markdown_key from 'docs/api/staticParcel/key.md'; -import Markdown_get from 'docs/api/staticParcel/get.md'; -import Markdown_getIn from 'docs/api/staticParcel/getIn.md'; -import Markdown_children from 'docs/api/staticParcel/children.md'; -import Markdown_toObject from 'docs/api/staticParcel/toObject.md'; -import Markdown_toArray from 'docs/api/staticParcel/toArray.md'; -import Markdown_has from 'docs/api/staticParcel/has.md'; -import Markdown_size from 'docs/api/staticParcel/size.md'; -import Markdown_set from 'docs/api/staticParcel/set.md'; -import Markdown_setIn from 'docs/api/staticParcel/setIn.md'; -import Markdown_update from 'docs/api/staticParcel/update.md'; -import Markdown_updateShape from 'docs/api/staticParcel/updateShape.md'; -import Markdown_updateIn from 'docs/api/staticParcel/updateIn.md'; -import Markdown_updateShapeIn from 'docs/api/staticParcel/updateShapeIn.md'; -import Markdown_delete from 'docs/api/staticParcel/delete.md'; -import Markdown_deleteIn from 'docs/api/staticParcel/deleteIn.md'; -import Markdown_insertAfter from 'docs/api/staticParcel/insertAfter.md'; -import Markdown_insertBefore from 'docs/api/staticParcel/insertBefore.md'; -import Markdown_pop from 'docs/api/staticParcel/pop.md'; -import Markdown_push from 'docs/api/staticParcel/push.md'; -import Markdown_shift from 'docs/api/staticParcel/shift.md'; -import Markdown_swap from 'docs/api/staticParcel/swap.md'; -import Markdown_swapNext from 'docs/api/staticParcel/swapNext.md'; -import Markdown_swapPrev from 'docs/api/staticParcel/swapPrev.md'; -import Markdown_unshift from 'docs/api/staticParcel/unshift.md'; -import Markdown_setMeta from 'docs/api/staticParcel/setMeta.md'; -import Markdown_isChild from 'docs/api/staticParcel/isChild.md'; -import Markdown_isElement from 'docs/api/staticParcel/isElement.md'; -import Markdown_isIndexed from 'docs/api/staticParcel/isIndexed.md'; -import Markdown_isParent from 'docs/api/staticParcel/isParent.md'; -import Markdown_isTopLevel from 'docs/api/staticParcel/isTopLevel.md'; -import Markdown_toConsole from 'docs/api/staticParcel/toConsole.md'; - -const md = { - _desc: Markdown_StaticParcel, - value: Markdown_value, - meta: Markdown_meta, - data: Markdown_data, - key: Markdown_key, - get: Markdown_get, - getIn: Markdown_getIn, - children: Markdown_children, - toObject: Markdown_toObject, - toArray: Markdown_toArray, - has: Markdown_has, - size: Markdown_size, - set: Markdown_set, - setIn: Markdown_setIn, - update: Markdown_update, - updateShape: Markdown_updateShape, - updateIn: Markdown_updateIn, - updateShapeIn: Markdown_updateShapeIn, - delete: Markdown_delete, - deleteIn: Markdown_deleteIn, - insertAfter: Markdown_insertAfter, - insertBefore: Markdown_insertBefore, - pop: Markdown_pop, - push: Markdown_push, - shift: Markdown_shift, - swap: Markdown_swap, - swapNext: Markdown_swapNext, - swapPrev: Markdown_swapPrev, - unshift: Markdown_unshift, - setMeta: Markdown_setMeta, - isChild: Markdown_isChild, - isElement: Markdown_isElement, - isIndexed: Markdown_isIndexed, - isParent: Markdown_isParent, - isTopLevel: Markdown_isTopLevel, - toConsole: Markdown_toConsole -} - -const api = ` -# Properties -value -meta -data -key - -# Parent methods -get() -getIn() -children() -toObject() -toArray() -has() -size() - -# Set methods -set() -setIn() -delete() -deleteIn() -update() -updateShape() -updateIn() -updateShapeIn() - -# Indexed & element change methods -insertAfter() -insertBefore() -push() -pop() -shift() -swap() -swapNext() -swapPrev() -unshift() - -# Type methods -isChild() -isElement() -isIndexed() -isParent() -isTopLevel() - -# Debug methods -toConsole() - -`; - -export default () => ; diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index 7090fcbc..a1641983 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -5,4 +5,4 @@ export const ReducerInvalidActionError = (actionType: string) => new Error(`"${a export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); -export const ShapeUpdaterNonStaticChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a StaticParcel`); +export const ShapeUpdaterNonShapeChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a ParcelShape`); diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index 17f1145d..8aa03a1e 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -4,7 +4,7 @@ export default Parcel; export {default as Action} from './change/Action'; export {default as ChangeRequest} from './change/ChangeRequest'; -export {default as StaticParcel} from './staticParcel/StaticParcel'; +export {default as ParcelShape} from './parcelShape/ParcelShape'; export {default as DeletedParcelMarker} from './parcelData/DeletedParcelMarker'; // @@ -22,10 +22,10 @@ export type {ParcelMapper} from './types/Types'; export type {ParcelUpdater} from './types/Types'; export type {ParcelValueUpdater} from './types/Types'; -export type {StaticParcelSetMeta} from './types/Types'; -export type {StaticParcelUpdater} from './types/Types'; -export type {StaticParcelValueUpdater} from './types/Types'; -export type {StaticParcelConfigInternal} from './types/Types'; +export type {ParcelShapeSetMeta} from './types/Types'; +export type {ParcelShapeUpdater} from './types/Types'; +export type {ParcelShapeValueUpdater} from './types/Types'; +export type {ParcelShapeConfigInternal} from './types/Types'; export type {Key} from './types/Types'; export type {Index} from './types/Types'; diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 84cff200..27bf7108 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -13,7 +13,7 @@ import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; import type {ParentType} from '../types/Types'; -import type {StaticParcelUpdater} from '../types/Types'; +import type {ParcelShapeUpdater} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -287,12 +287,12 @@ export default class Parcel { ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); updateShape = overload({ - ["1"]: (updater: StaticParcelUpdater) => this._methods.updateSelfShape(updater), - ["2"]: (key: Key|Index, updater: StaticParcelUpdater) => this._methods.updateShape(key, updater) + ["1"]: (updater: ParcelShapeUpdater) => this._methods.updateSelfShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeUpdater) => this._methods.updateShape(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateShapeIn = (keyPath: Array, updater: StaticParcelUpdater) => this._methods.updateShapeIn(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: ParcelShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 59969638..3d88961c 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -2,7 +2,7 @@ import type ChangeRequest from '../../change/ChangeRequest'; import Parcel from '../Parcel'; -import StaticParcel from '../../staticParcel/StaticParcel'; +import ParcelShape from '../../parcelShape/ParcelShape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; test('Parcel.modifyDown() should return a new parcel with updated parcelData', () => { @@ -156,10 +156,10 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { }); }); -test('Parcel.modifyShapeDown() should be called with static parcel and return with no change', () => { +test('Parcel.modifyShapeDown() should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); - let updater = jest.fn(staticParcel => staticParcel); + let updater = jest.fn(parcelShape => parcelShape); let parcel = new Parcel({ handleChange, @@ -173,14 +173,14 @@ test('Parcel.modifyShapeDown() should be called with static parcel and return wi let expectedValue = [1,2,3]; expect(value).toEqual(expectedValue); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(updater.mock.calls[0][0].data.value).toEqual(expectedValue); }); test('Parcel.modifyShapeDown() should modify value', () => { let handleChange = jest.fn(); - let updater = jest.fn(staticParcel => staticParcel.push(4)); + let updater = jest.fn(parcelShape => parcelShape.push(4)); let parcel = new Parcel({ handleChange, @@ -195,10 +195,10 @@ test('Parcel.modifyShapeDown() should modify value', () => { expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); }); -test('Parcel.modifyShapeUp() should be called with static parcel and return with no change', () => { +test('Parcel.modifyShapeUp() should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); - let updater = jest.fn(staticParcel => staticParcel); + let updater = jest.fn(parcelShape => parcelShape); let parcel = new Parcel({ handleChange, @@ -213,14 +213,14 @@ test('Parcel.modifyShapeUp() should be called with static parcel and return with parcelWithModifier.set(456); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(updater.mock.calls[0][0].data.value).toEqual(456); }); test('Parcel.modifyShapeUp() should modify value', () => { let handleChange = jest.fn(); - let updater = jest.fn(staticParcel => staticParcel.push(5)); + let updater = jest.fn(parcelShape => parcelShape.push(5)); let parcel = new Parcel({ handleChange, @@ -235,7 +235,7 @@ test('Parcel.modifyShapeUp() should modify value', () => { parcelWithModifier.push(4); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); }); @@ -290,8 +290,8 @@ test('Sanity check: A big strange test of a big strange chain of deep updatery s handleChange, value: [1,2,3] }) - .modifyShapeDown(staticParcel => staticParcel.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) - .modifyShapeUp(staticParcel => staticParcel.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) + .modifyShapeDown(parcelShape => parcelShape.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) + .modifyShapeUp(parcelShape => parcelShape.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) .get(0) // 2. get the first element (value: 3) .modifyDown(value => value + "") // 3. cast number to string value: "3") .modifyUp(value => parseInt(value, 10)) // 5. cast string to number (value will be: 3333) diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 217de877..58a49922 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -1,7 +1,7 @@ // @flow import Parcel from '../Parcel'; import GetAction from '../../util/__test__/GetAction-testUtil'; -import StaticParcel from '../../staticParcel/StaticParcel'; +import ParcelShape from '../../parcelShape/ParcelShape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; test('Parcel.set() should call the Parcels handleChange function with the new parcelData', () => { @@ -94,14 +94,14 @@ test('Parcel.update() should validate value updater', () => { test('Parcel.updateShape() should call the Parcels handleChange function with the new parcelData', () => { let handleChange = jest.fn(); - let updater = jest.fn(staticParcel => staticParcel.push(4)); + let updater = jest.fn(parcelShape => parcelShape.push(4)); new Parcel({ value: [1,2,3], handleChange }).updateShape(updater); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); diff --git a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js index 00f3df8a..459b121e 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js @@ -1,7 +1,7 @@ // @flow import Parcel from '../Parcel'; import map from 'unmutable/lib/map'; -import StaticParcel from '../../staticParcel/StaticParcel'; +import ParcelShape from '../../parcelShape/ParcelShape'; test('ParentParcel.set(key) should call the Parcels handleChange function with the new parcelData', () => { expect.assertions(1); @@ -37,7 +37,7 @@ test('ParentParcel.update(key) should call the Parcels handleChange function wit }); test('ParentParcel.updateShape(key) should call the Parcels handleChange function with the new parcelData', () => { - let updater = jest.fn(staticParcel => staticParcel.push(4)); + let updater = jest.fn(parcelShape => parcelShape.push(4)); let handleChange = jest.fn(); new Parcel({ @@ -47,7 +47,7 @@ test('ParentParcel.updateShape(key) should call the Parcels handleChange functio handleChange }).updateShape("abc", updater); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ abc: [1,2,3,4] }); @@ -111,7 +111,7 @@ test('ParentParcel.updateIn(keyPath) should call the Parcels handleChange functi }); test('ParentParcel.updateShapeIn(keyPath) should call the Parcels handleChange function with the new parcelData', () => { - let updater = jest.fn(staticParcel => staticParcel.push(4)); + let updater = jest.fn(parcelShape => parcelShape.push(4)); let handleChange = jest.fn(); new Parcel({ @@ -123,7 +123,7 @@ test('ParentParcel.updateShapeIn(keyPath) should call the Parcels handleChange f handleChange }).updateShapeIn(["abc", "def"], updater); - expect(updater.mock.calls[0][0] instanceof StaticParcel).toBe(true); + expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ abc: { def: [1,2,3,4] diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 5ed01e1d..f48ffdba 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -5,7 +5,7 @@ import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; import Types from '../../types/Types'; -import StaticParcel from '../../staticParcel/StaticParcel'; +import ParcelShape from '../../parcelShape/ParcelShape'; import ValidateValueUpdater from '../../util/ValidateValueUpdater'; import ParcelTypes from '../ParcelTypes'; @@ -77,13 +77,13 @@ export default (_this: Parcel): Object => ({ modifyShapeDown: (updater: Function): Parcel => { Types(`modifyShapeDown()`, `updater`, `function`)(updater); - let staticUpdater = StaticParcel._updateFromData(updater); + let shapeUpdater = ParcelShape._updateFromData(updater); return _this._create({ id: _this._id.pushModifier(`md-${HashFunction(updater)}`), - parcelData: staticUpdater(_this._parcelData), + parcelData: shapeUpdater(_this._parcelData), onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPre(staticUpdater)); + _this.dispatch(changeRequest._addPre(shapeUpdater)); } }); }, @@ -91,12 +91,12 @@ export default (_this: Parcel): Object => ({ modifyShapeUp: (updater: Function): Parcel => { Types(`modifyShapeUp()`, `updater`, `function`)(updater); - let staticUpdater = StaticParcel._updateFromData(updater); + let shapeUpdater = ParcelShape._updateFromData(updater); return _this._create({ id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPost(staticUpdater)); + _this.dispatch(changeRequest._addPost(shapeUpdater)); } }); }, diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index d5c77441..5a4fa92f 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -2,12 +2,12 @@ import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {StaticParcelUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; import ActionCreators from '../../change/ActionCreators'; -import StaticParcel from '../../staticParcel/StaticParcel'; +import ParcelShape from '../../parcelShape/ParcelShape'; import ValidateValueUpdater from '../../util/ValidateValueUpdater'; export default (_this: Parcel, dispatch: Function) => ({ @@ -24,10 +24,10 @@ export default (_this: Parcel, dispatch: Function) => ({ _this.set(updatedValue); }, - updateSelfShape: (updater: StaticParcelUpdater) => { + updateSelfShape: (updater: ParcelShapeUpdater) => { Types(`updateSelfShape()`, `updater`, `function`)(updater); - let staticParcelUpdater = StaticParcel._updateFromData(updater); - let updated = staticParcelUpdater(_this._parcelData); + let parcelShapeUpdater = ParcelShape._updateFromData(updater); + let updated = parcelShapeUpdater(_this._parcelData); dispatch(ActionCreators.setData(updated)); }, diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index caff6930..92f87161 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -3,7 +3,7 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {StaticParcelUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; @@ -34,7 +34,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).update(updater); }, - updateShape: (key: Key|Index, updater: StaticParcelUpdater) => { + updateShape: (key: Key|Index, updater: ParcelShapeUpdater) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); _this.get(key).updateShape(updater); @@ -46,7 +46,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.getIn(keyPath).update(updater); }, - updateShapeIn: (keyPath: Array, updater: StaticParcelUpdater) => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater) => { Types(`updateShapeIn()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateShapeIn()`, `updater`, `function`)(updater); _this.getIn(keyPath).updateShape(updater); diff --git a/packages/dataparcels/src/staticParcel/StaticParcel.js b/packages/dataparcels/src/parcelShape/ParcelShape.js similarity index 60% rename from packages/dataparcels/src/staticParcel/StaticParcel.js rename to packages/dataparcels/src/parcelShape/ParcelShape.js index 0e730325..9e78bf77 100644 --- a/packages/dataparcels/src/staticParcel/StaticParcel.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -3,10 +3,10 @@ import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; import type {ParcelData} from '../types/Types'; import type {ParentType} from '../types/Types'; -import type {StaticParcelValueUpdater} from '../types/Types'; -import type {StaticParcelConfigInternal} from '../types/Types'; -import type {StaticParcelUpdater} from '../types/Types'; -import type {StaticParcelSetMeta} from '../types/Types'; +import type {ParcelShapeValueUpdater} from '../types/Types'; +import type {ParcelShapeConfigInternal} from '../types/Types'; +import type {ParcelShapeUpdater} from '../types/Types'; +import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -14,10 +14,10 @@ import {ReadOnlyError} from '../errors/Errors'; import ParcelTypes from '../parcel/ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; -import StaticParentGetMethods from './methods/StaticParentGetMethods'; -import StaticParentSetMethods from './methods/StaticParentSetMethods'; -import StaticSetMethods from './methods/StaticSetMethods'; -import StaticIndexedSetMethods from './methods/StaticIndexedSetMethods'; +import ParcelShapeParentGetMethods from './methods/ParcelShapeParentGetMethods'; +import ParcelShapeParentSetMethods from './methods/ParcelShapeParentSetMethods'; +import ParcelShapeSetMethods from './methods/ParcelShapeSetMethods'; +import ParcelShapeIndexedSetMethods from './methods/ParcelShapeIndexedSetMethods'; import FilterMethods from '../util/FilterMethods'; @@ -26,8 +26,8 @@ import pipeWith from 'unmutable/lib/util/pipeWith'; import prepareChildKeys from '../parcelData/prepareChildKeys'; -export default class StaticParcel { - constructor(value: any, _configInternal: ?StaticParcelConfigInternal) { +export default class ParcelShape { + constructor(value: any, _configInternal: ?ParcelShapeConfigInternal) { this._parcelData = { value }; @@ -50,13 +50,13 @@ export default class StaticParcel { // methods this._methods = { // $FlowFixMe - ...FilterMethods("Parent", StaticParentGetMethods)(this), + ...FilterMethods("Parent", ParcelShapeParentGetMethods)(this), // $FlowFixMe - ...FilterMethods("Parent", StaticParentSetMethods)(this), + ...FilterMethods("Parent", ParcelShapeParentSetMethods)(this), // $FlowFixMe - ...StaticSetMethods(this), + ...ParcelShapeSetMethods(this), // $FlowFixMe - ...FilterMethods("Indexed", StaticIndexedSetMethods)(this) + ...FilterMethods("Indexed", ParcelShapeIndexedSetMethods)(this) }; } @@ -67,28 +67,28 @@ export default class StaticParcel { // from constructor _id: ParcelId; _methods: { [key: string]: any }; - _parent: ?StaticParcel; + _parent: ?ParcelShape; _parcelData: ParcelData; _parcelTypes: ParcelTypes; - static _updateFromData(updater: StaticParcelUpdater): Function { - return (parcelData: ParcelData): ParcelData => StaticParcel + static _updateFromData(updater: ParcelShapeUpdater): Function { + return (parcelData: ParcelData): ParcelData => ParcelShape .fromData(parcelData) .updateShape(updater) .data; } - // only need this to reference static methods on StaticParcel + // only need this to reference static methods on ParcelShape // without creating circular dependencies - _instanceUpdateFromData = StaticParcel._updateFromData; + _instanceUpdateFromData = ParcelShape._updateFromData; - _pipeSelf = (fn: Function, _configInternal: ?StaticParcelConfigInternal): StaticParcel => pipeWith( + _pipeSelf = (fn: Function, _configInternal: ?ParcelShapeConfigInternal): ParcelShape => pipeWith( this._parcelData, fn, - data => StaticParcel.fromData(data, _configInternal) + data => ParcelShape.fromData(data, _configInternal) ); - _isStaticParcel = (maybe: any): boolean => maybe instanceof StaticParcel; + _isParcelShape = (maybe: any): boolean => maybe instanceof ParcelShape; _prepareChildKeys = () => { // prepare child keys only once per parcel instance @@ -148,41 +148,41 @@ export default class StaticParcel { // public methods // - static fromData(parcelData: ParcelData, _configInternal: ?StaticParcelConfigInternal): StaticParcel { - Types(`StaticParcel()`, `fromData`, `parcelData`)(parcelData); - let staticParcel = new StaticParcel(parcelData.value, _configInternal); - staticParcel._parcelData = parcelData; - return staticParcel; + static fromData(parcelData: ParcelData, _configInternal: ?ParcelShapeConfigInternal): ParcelShape { + Types(`ParcelShape()`, `fromData`, `parcelData`)(parcelData); + let parcelShape = new ParcelShape(parcelData.value, _configInternal); + parcelShape._parcelData = parcelData; + return parcelShape; } // Parent methods has = (key: Key|Index): boolean => this._methods.has(key); size = (): number => this._methods.size(); - get = (key: Key|Index, notFoundValue: ?any = undefined): StaticParcel => this._methods.get(key, notFoundValue); - getIn = (keyPath: Array, notFoundValue: ?any = undefined): StaticParcel => this._methods.getIn(keyPath, notFoundValue); - children = (): ParentType => this._methods.children(); - toObject = (): { [key: string]: StaticParcel } => this._methods.toObject(); - toArray = (): Array => this._methods.toArray(); + get = (key: Key|Index, notFoundValue: ?any = undefined): ParcelShape => this._methods.get(key, notFoundValue); + getIn = (keyPath: Array, notFoundValue: ?any = undefined): ParcelShape => this._methods.getIn(keyPath, notFoundValue); + children = (): ParentType => this._methods.children(); + toObject = (): { [key: string]: ParcelShape } => this._methods.toObject(); + toArray = (): Array => this._methods.toArray(); // Change methods set = overload({ ["1"]: (value: any) => this._methods.setSelf(value), ["2"]: (key: Key|Index, value: any) => this.setIn([key], value) }); - setMeta = (partialMeta: StaticParcelSetMeta) => this._methods.setMeta(partialMeta); + setMeta = (partialMeta: ParcelShapeSetMeta) => this._methods.setMeta(partialMeta); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); delete = (key: Key|Index) => this.deleteIn([key]); deleteIn = (keyPath: Array) => this._methods.deleteIn(keyPath); update = overload({ - ["1"]: (updater: StaticParcelValueUpdater): StaticParcel => this._methods.update(updater), - ["2"]: (key: Key|Index, updater: StaticParcelValueUpdater): StaticParcel => this.updateIn([key], updater) + ["1"]: (updater: ParcelShapeValueUpdater): ParcelShape => this._methods.update(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeValueUpdater): ParcelShape => this.updateIn([key], updater) }); updateShape = overload({ - ["1"]: (updater: StaticParcelUpdater): StaticParcel => this._methods.updateShape(updater), - ["2"]: (key: Key|Index, updater: StaticParcelUpdater): StaticParcel => this.updateShapeIn([key], updater) + ["1"]: (updater: ParcelShapeUpdater): ParcelShape => this._methods.updateShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeUpdater): ParcelShape => this.updateShapeIn([key], updater) }); - updateIn = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateShapeIn = (keyPath: Array, updater: StaticParcelValueUpdater) => this._methods.updateShapeIn(keyPath, updater); + updateIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateIn(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateShapeIn(keyPath, updater); // Indexed methods insertAfter = (key: Key|Index, value: any) => this._methods.insertAfter(key, value); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShape-test.js similarity index 58% rename from packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js rename to packages/dataparcels/src/parcelShape/__test__/ParcelShape-test.js index 5a66e1ed..deaf1e95 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticParcel-test.js +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShape-test.js @@ -1,12 +1,12 @@ // @flow -import StaticParcel from '../StaticParcel'; +import ParcelShape from '../ParcelShape'; -test('StaticParcels should accept value', () => { - let parcel = new StaticParcel(123); +test('ParcelShapes should accept value', () => { + let parcel = new ParcelShape(123); expect(parcel.value).toEqual(123); }); -test('StaticParcels.fromData should accept parcel data', () => { +test('ParcelShapes.fromData should accept parcel data', () => { let data = { value: [0,1,2], meta: { @@ -20,26 +20,26 @@ test('StaticParcels.fromData should accept parcel data', () => { ] }; - let parcel = StaticParcel.fromData(data); + let parcel = ParcelShape.fromData(data); expect(parcel.data).toEqual(data); }); -test('StaticParcels should return data', () => { - let parcel = new StaticParcel(123); +test('ParcelShapes should return data', () => { + let parcel = new ParcelShape(123); expect(parcel.data).toEqual({ value: 123 }); }); -test('StaticParcels should return empty meta object', () => { - let parcel = new StaticParcel(123); +test('ParcelShapes should return empty meta object', () => { + let parcel = new ParcelShape(123); expect(parcel.meta).toEqual({}); }); -test('StaticParcels should throw errors when attempted to set getters', () => { +test('ParcelShapes should throw errors when attempted to set getters', () => { let readOnly = 'This property is read-only'; - let parcel = new StaticParcel(123); + let parcel = new ParcelShape(123); expect(() => { parcel.data = 123; diff --git a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js new file mode 100644 index 00000000..d9a5f389 --- /dev/null +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js @@ -0,0 +1,74 @@ +// @flow +import ParcelShape from '../ParcelShape'; + +test('ParcelShapes insertAfter(key, value) should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.insertAfter(0, 3).data.value).toEqual([0,3,1,2]); +}); + +test('ParcelShapes insertBefore(key, value) should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.insertBefore(0, 3).data.value).toEqual([3,0,1,2]); +}); + +test('ParcelShapes push(value) should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.push(3).data.value).toEqual([0,1,2,3]); +}); + +test('ParcelShapes pop() should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.pop().data.value).toEqual([0,1]); +}); + +test('ParcelShapes shift() should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.shift().data.value).toEqual([1,2]); +}); + +test('ParcelShapes swap() should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.swap(0,2).data.value).toEqual([2,1,0]); +}); + +test('ParcelShapes swapNext() should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.swapNext(1).data.value).toEqual([0,2,1]); +}); + +test('ParcelShapes swapPrev() should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.swapPrev(1).data.value).toEqual([1,0,2]); +}); + +test('ParcelShapes unshift(value) should work', () => { + let parcelShape = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(parcelShape.unshift(3).data.value).toEqual([3,0,1,2]); +}); diff --git a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentGetMethods-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentGetMethods-test.js new file mode 100644 index 00000000..06678df0 --- /dev/null +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentGetMethods-test.js @@ -0,0 +1,147 @@ +// @flow +import ParcelShape from '../ParcelShape'; + +import map from 'unmutable/lib/map'; + +test('ParcelShapes getters should work', () => { + let data = { + value: [0,1,2], + meta: { + abc: 123 + }, + key: "^", + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + let parcel = ParcelShape.fromData(data); + expect(parcel.meta).toEqual(data.meta); + expect(parcel.key).toEqual(data.key); +}); + +test('ParcelShapes.get should work with objects', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: { + b: 1 + }, + key: "a" + }; + + expect(parcelShape.get('a').data).toEqual(expectedParcelData); +}); + +test('ParcelShapes.getIn should work with objects', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: 1, + key: "b" + }; + + expect(parcelShape.getIn(['a','b']).data).toEqual(expectedParcelData); +}); + +test('ParcelShapes.getIn should work with objects with non-existent keys', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: { + b: 1 + } + } + }); + + let expectedParcelData = { + value: undefined, + key: "z" + }; + + expect(parcelShape.getIn(['z']).data).toEqual(expectedParcelData); +}); + +test('ParcelShapes.getIn should return undefined if asking through a non-parent', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: 1 + } + }); + + let expectedParcelData = { + value: undefined, + key: "b" + }; + + expect(parcelShape.getIn(['a', 'b']).data).toEqual(expectedParcelData); +}); + +test('ParcelShapes.size() should return size of parcel', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: 1, + b: 4 + } + }); + + expect(parcelShape.size()).toBe(2); +}); + +test('ParcelShapes.has(key) should return a boolean indicating if key exists', () => { + let parcelShape = ParcelShape.fromData({ + value: { + a: 1, + b: 4 + } + }); + + expect(parcelShape.has('a')).toBe(true); + expect(parcelShape.has('z')).toBe(false); +}); + +test('ParcelShapes.children() should make a parent data type full of parcelShapes', () => { + let children = ParcelShape.fromData({ + value: {a:1,b:2,c:3} + }) + .children(); + + expect(map(ii => ii.value)(children)).toEqual({a:1,b:2,c:3}); +}); + +test('ParcelShapes.toObject() should make an object', () => { + let parcelShape = ParcelShape.fromData({ + value: {a:1,b:2,c:3}, + meta: { + a: {a:4,b:5,c:6} + } + }); + + var expectedValue = {a:1,b:2,c:3}; + expect(map(ii => ii.value)(parcelShape.toObject())).toEqual(expectedValue); +}); + +test('ParcelShapes.toArray() should make an array', () => { + let parcelShape = ParcelShape.fromData({ + value: {a:1,b:2,c:3}, + meta: { + a: {a:4,b:5,c:6} + } + }); + + var expectedValue = [1,2,3]; + expect(map(ii => ii.value)(parcelShape.toArray())).toEqual(expectedValue); +}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentSetMethods-test.js similarity index 63% rename from packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js rename to packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentSetMethods-test.js index ed7fa125..205f587d 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticParentSetMethods-test.js +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeParentSetMethods-test.js @@ -1,9 +1,9 @@ // @flow -import StaticParcel from '../StaticParcel'; +import ParcelShape from '../ParcelShape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; -test('StaticParcels set(key) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes set(key) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: 1, b: 4 @@ -30,11 +30,11 @@ test('StaticParcels set(key) should work', () => { } }; - expect(staticParcel.set('a', 456).data).toEqual(expectedData); + expect(parcelShape.set('a', 456).data).toEqual(expectedData); }); -test('StaticParcels setIn(keyPath) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes setIn(keyPath) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: { b: 123 @@ -66,11 +66,11 @@ test('StaticParcels setIn(keyPath) should work', () => { } }; - expect(staticParcel.setIn(['a', 'b'], 456).data).toEqual(expectedData); + expect(parcelShape.setIn(['a', 'b'], 456).data).toEqual(expectedData); }); -test('StaticParcels delete(key) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes delete(key) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: 1, b: 4 @@ -92,11 +92,11 @@ test('StaticParcels delete(key) should work', () => { } }; - expect(staticParcel.delete('a').data).toEqual(expectedData); + expect(parcelShape.delete('a').data).toEqual(expectedData); }); -test('StaticParcels deleteIn(keyPath) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes deleteIn(keyPath) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: { b: 123 @@ -121,11 +121,11 @@ test('StaticParcels deleteIn(keyPath) should work', () => { } }; - expect(staticParcel.deleteIn(['a', 'b']).data).toEqual(expectedData); + expect(parcelShape.deleteIn(['a', 'b']).data).toEqual(expectedData); }); -test('StaticParcels update(key) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes update(key) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: 1, b: 4 @@ -149,20 +149,20 @@ test('StaticParcels update(key) should work', () => { } }; - expect(staticParcel.update('a', ii => ii + 1).data).toEqual(expectedData); + expect(parcelShape.update('a', ii => ii + 1).data).toEqual(expectedData); }); -test('StaticParcels update(key) should validate value updater', () => { +test('ParcelShapes update(key) should validate value updater', () => { TestValidateValueUpdater( expect, - (value, updater) => new StaticParcel({ + (value, updater) => new ParcelShape({ abc: value }).update('abc', updater) ); }); -test('StaticParcels updateIn(keyPath) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateIn(keyPath) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: { b: 123 @@ -189,13 +189,13 @@ test('StaticParcels updateIn(keyPath) should work', () => { } }; - expect(staticParcel.updateIn(['a', 'b'], ii => ii + 1).data).toEqual(expectedData); + expect(parcelShape.updateIn(['a', 'b'], ii => ii + 1).data).toEqual(expectedData); }); -test('StaticParcels updateIn(keyPath) should validate value updater', () => { +test('ParcelShapes updateIn(keyPath) should validate value updater', () => { TestValidateValueUpdater( expect, - (value, updater) => new StaticParcel({ + (value, updater) => new ParcelShape({ a: { b: value } @@ -203,8 +203,8 @@ test('StaticParcels updateIn(keyPath) should validate value updater', () => { ); }); -test('StaticParcels updateShape(key) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape(key) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { abc: [1,2,3] } @@ -214,11 +214,11 @@ test('StaticParcels updateShape(key) should work', () => { abc: [1,2,3,4] }; - expect(staticParcel.updateShape('abc', staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); + expect(parcelShape.updateShape('abc', parcelShape => parcelShape.push(4)).value).toEqual(expectedValue); }); -test('StaticParcels updateShapeIn(keyPath) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShapeIn(keyPath) should work', () => { + let parcelShape = ParcelShape.fromData({ value: { abc: { def: [1,2,3] @@ -232,5 +232,5 @@ test('StaticParcels updateShapeIn(keyPath) should work', () => { } }; - expect(staticParcel.updateShapeIn(['abc', 'def'], staticParcel => staticParcel.push(4)).value).toEqual(expectedValue); + expect(parcelShape.updateShapeIn(['abc', 'def'], parcelShape => parcelShape.push(4)).value).toEqual(expectedValue); }); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeSetMethods-test.js similarity index 59% rename from packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js rename to packages/dataparcels/src/parcelShape/__test__/ParcelShapeSetMethods-test.js index b8d664ae..2d267680 100644 --- a/packages/dataparcels/src/staticParcel/__test__/StaticSetMethods-test.js +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeSetMethods-test.js @@ -1,9 +1,9 @@ // @flow -import StaticParcel from '../StaticParcel'; +import ParcelShape from '../ParcelShape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; -test('StaticParcels set() should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes set() should work', () => { + let parcelShape = ParcelShape.fromData({ value: { a: 1, b: 4 @@ -18,11 +18,11 @@ test('StaticParcels set() should work', () => { value: 456 }; - expect(staticParcel.set(456).data).toEqual(expectedData); + expect(parcelShape.set(456).data).toEqual(expectedData); }); -test('StaticParcels setMeta(partialMeta) should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes setMeta(partialMeta) should work', () => { + let parcelShape = ParcelShape.fromData({ value: 123, meta: { abc: 123 @@ -37,13 +37,13 @@ test('StaticParcels setMeta(partialMeta) should work', () => { } }; - expect(staticParcel.setMeta({def: 456}).data).toEqual(expectedData); + expect(parcelShape.setMeta({def: 456}).data).toEqual(expectedData); }); -test('StaticParcels setMeta(updater) should work', () => { +test('ParcelShapes setMeta(updater) should work', () => { let updater = jest.fn(meta => ({def: 456})); - let staticParcel = StaticParcel.fromData({ + let parcelShape = ParcelShape.fromData({ value: 123, meta: { abc: 123 @@ -58,7 +58,7 @@ test('StaticParcels setMeta(updater) should work', () => { } }; - let {data} = staticParcel.setMeta(updater); + let {data} = parcelShape.setMeta(updater); expect(updater.mock.calls[0][0]).toEqual({ abc: 123 @@ -67,8 +67,8 @@ test('StaticParcels setMeta(updater) should work', () => { expect(data).toEqual(expectedData); }); -test('StaticParcels update() should work', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes update() should work', () => { + let parcelShape = ParcelShape.fromData({ value: 123 }); @@ -76,18 +76,18 @@ test('StaticParcels update() should work', () => { value: 124 }; - expect(staticParcel.update(ii => ii + 1).data).toEqual(expectedData); + expect(parcelShape.update(ii => ii + 1).data).toEqual(expectedData); }); -test('StaticParcels update() should validate value updater', () => { +test('ParcelShapes update() should validate value updater', () => { TestValidateValueUpdater( expect, - (value, updater) => new StaticParcel(value).update(updater) + (value, updater) => new ParcelShape(value).update(updater) ); }); -test('StaticParcels updateShape() should work with returned StaticParcel', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should work with returned ParcelShape', () => { + let parcelShape = ParcelShape.fromData({ value: 123, meta: { abc: 789 @@ -103,11 +103,11 @@ test('StaticParcels updateShape() should work with returned StaticParcel', () => key: "z" }; - expect(staticParcel.updateShape(staticParcel => staticParcel.set(456)).data).toEqual(expectedData); + expect(parcelShape.updateShape(parcelShape => parcelShape.set(456)).data).toEqual(expectedData); }); -test('StaticParcels updateShape() should work with returned primitive', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should work with returned primitive', () => { + let parcelShape = ParcelShape.fromData({ value: 123, meta: { abc: 789 @@ -123,11 +123,11 @@ test('StaticParcels updateShape() should work with returned primitive', () => { key: "z" }; - expect(staticParcel.updateShape(() => 456).data).toEqual(expectedData); + expect(parcelShape.updateShape(() => 456).data).toEqual(expectedData); }); -test('StaticParcels updateShape() should work with returned parent value', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should work with returned parent value', () => { + let parcelShape = ParcelShape.fromData({ value: [1,2,3], meta: { abc: 789 @@ -148,8 +148,8 @@ test('StaticParcels updateShape() should work with returned parent value', () => key: "z" }; - let {data} = staticParcel.updateShape((staticParcel) => { - return staticParcel + let {data} = parcelShape.updateShape((parcelShape) => { + return parcelShape .children() .map((child => child.update(value => value + 1))) }); @@ -157,8 +157,8 @@ test('StaticParcels updateShape() should work with returned parent value', () => expect(data).toEqual(expectedData); }); -test('StaticParcels updateShape() should work with returned parent value of different type', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should work with returned parent value of different type', () => { + let parcelShape = ParcelShape.fromData({ value: { abc: 123, def: 456 @@ -184,13 +184,13 @@ test('StaticParcels updateShape() should work with returned parent value of diff key: "z" }; - let {data} = staticParcel.updateShape((staticParcel) => staticParcel.toArray()); + let {data} = parcelShape.updateShape((parcelShape) => parcelShape.toArray()); expect(data).toEqual(expectedData); }); -test('StaticParcels updateShape() should retain childs keys', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should retain childs keys', () => { + let parcelShape = ParcelShape.fromData({ value: ["a","b","c","d"], child: [ {key: "#a", child: undefined}, @@ -208,8 +208,8 @@ test('StaticParcels updateShape() should retain childs keys', () => { ] }; - let {data} = staticParcel.updateShape((staticParcel) => { - return staticParcel + let {data} = parcelShape.updateShape((parcelShape) => { + return parcelShape .toArray() .filter((value, key) => key % 2 === 1) }); @@ -217,14 +217,14 @@ test('StaticParcels updateShape() should retain childs keys', () => { expect(data).toEqual(expectedData); }); -test('StaticParcels updateShape() should throw error if non staticparcel is a child of the return value', () => { - let staticParcel = StaticParcel.fromData({ +test('ParcelShapes updateShape() should throw error if non ParcelShape is a child of the return value', () => { + let parcelShape = ParcelShape.fromData({ value: [123, 456] }); - expect(() => staticParcel.updateShape((staticParcel) => { - let arr = staticParcel.toArray(); + expect(() => parcelShape.updateShape((parcelShape) => { + let arr = parcelShape.toArray(); arr.push(789); return arr; - })).toThrow('Every child value on a collection returned from a shape updater must be a StaticParcel'); + })).toThrow('Every child value on a collection returned from a shape updater must be a ParcelShape'); }); diff --git a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js new file mode 100644 index 00000000..776f9944 --- /dev/null +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js @@ -0,0 +1,181 @@ +// @flow +import {Map, List} from 'immutable'; +import ParcelShape from '../ParcelShape'; + +test('ParcelShapeTypes should correctly identify primitive values', () => { + var value = 123; + expect(new ParcelShape(value).isParent()).toBe(false); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify date', () => { + var value = new Date(); + expect(new ParcelShape(value).isParent()).toBe(false); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify object values', () => { + var value = { + a: "A" + }; + expect(new ParcelShape(value).isParent()).toBe(true); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify class instance values', () => { + class Thing { + foo = "123" + } + var value = new Thing(); + expect(new ParcelShape(value).isParent()).toBe(false); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify unmutable compatible class instance values', () => { + class UnmutableCompatible { + __UNMUTABLE_COMPATIBLE__ = true; + foo = "123"; + } + var value = new UnmutableCompatible(); + expect(new ParcelShape(value).isParent()).toBe(true); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + + +test('ParcelShapeTypes should correctly identify Immutable.js Map values', () => { + var value = Map({ + a: "A" + }); + expect(new ParcelShape(value).isParent()).toBe(true); + expect(new ParcelShape(value).isIndexed()).toBe(false); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + + +test('ParcelShapeTypes should correctly identify array values', () => { + var value = [1,2,3]; + expect(new ParcelShape(value).isParent()).toBe(true); + expect(new ParcelShape(value).isIndexed()).toBe(true); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify Immutable.js List values', () => { + var value = List([1,2,3]); + expect(new ParcelShape(value).isParent()).toBe(true); + expect(new ParcelShape(value).isIndexed()).toBe(true); + expect(new ParcelShape(value).isChild()).toBe(false); + expect(new ParcelShape(value).isElement()).toBe(false); + expect(new ParcelShape(value).isTopLevel()).toBe(true); +}); + +test('ParcelShapeTypes should correctly identify child values', () => { + var value = { + a: "A" + }; + expect(new ParcelShape(value).get("a").isParent()).toBe(false); + expect(new ParcelShape(value).get("a").isIndexed()).toBe(false); + expect(new ParcelShape(value).get("a").isChild()).toBe(true); + expect(new ParcelShape(value).get("a").isElement()).toBe(false); + expect(new ParcelShape(value).get("a").isTopLevel()).toBe(false); +}); + +test('ParcelShapeTypes should correctly identify element values', () => { + var value = [1,2,3]; + expect(new ParcelShape(value).get(0).isParent()).toBe(false); + expect(new ParcelShape(value).get(0).isIndexed()).toBe(false); + expect(new ParcelShape(value).get(0).isChild()).toBe(true); + expect(new ParcelShape(value).get(0).isElement()).toBe(true); + expect(new ParcelShape(value).get(0).isTopLevel()).toBe(false); +}); + +test('ParcelShapeTypes should correctly identify child values with getIn', () => { + var value = { + b: { + a: "A" + } + }; + expect(new ParcelShape(value).getIn(["b","a"]).isParent()).toBe(false); + expect(new ParcelShape(value).getIn(["b","a"]).isIndexed()).toBe(false); + expect(new ParcelShape(value).getIn(["b","a"]).isChild()).toBe(true); + expect(new ParcelShape(value).getIn(["b","a"]).isElement()).toBe(false); + expect(new ParcelShape(value).getIn(["b","a"]).isTopLevel()).toBe(false); +}); + +test('ParcelShapeTypes should correctly identify element values with getIn', () => { + var value = { + b: [1,2,3] + }; + + expect(new ParcelShape(value).getIn(["b",0]).isParent()).toBe(false); + expect(new ParcelShape(value).getIn(["b",0]).isIndexed()).toBe(false); + expect(new ParcelShape(value).getIn(["b",0]).isChild()).toBe(true); + expect(new ParcelShape(value).getIn(["b",0]).isElement()).toBe(true); + expect(new ParcelShape(value).getIn(["b",0]).isTopLevel()).toBe(false); +}); + +// // method creators + +// // test('Correct methods are created for primitive values', () => { +// // var value = 123; +// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); +// // expect(() => new ParcelShape(value).has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for object values', () => { +// // var value = {a: 123}; +// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); +// // expect(() => new ParcelShape(value).has('a')).not.toThrow(); +// // expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for array values', () => { +// // var value = [1,2,3]; +// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); +// // expect(() => new ParcelShape(value).has('a')).not.toThrow(); +// // expect(() => new ParcelShape(value).pop()).not.toThrow(); +// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); +// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for object child values', () => { +// // var value = {a: 123}; +// // expect(() => new ParcelShape(value).get("a").set('A')).not.toThrow(); +// // expect(() => new ParcelShape(value).get("a").has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new ParcelShape(value).get("a").pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new ParcelShape(value).get("a").delete()).not.toThrow(); +// // expect(() => new ParcelShape(value).get("a").swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); +// // }); + +// // test('Correct methods are created for array element values', () => { +// // var value = [1,2,3]; +// // expect(() => new ParcelShape(value).get(0).set('A')).not.toThrow(); +// // expect(() => new ParcelShape(value).get(0).has('a')).toThrowError(`.has() is not a function`); +// // expect(() => new ParcelShape(value).get(0).pop()).toThrowError(`.pop() is not a function`); +// // expect(() => new ParcelShape(value).get(0).delete()).not.toThrow(); +// // expect(() => new ParcelShape(value).get(0).swapNext()).not.toThrow(); +// // }); + diff --git a/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js similarity index 74% rename from packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js rename to packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js index 3a9901d4..703d7814 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticIndexedSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js @@ -1,7 +1,7 @@ // @flow import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; -import type StaticParcel from '../StaticParcel'; +import type ParcelShape from '../ParcelShape'; import insertAfter from '../../parcelData/insertAfter'; import insertBefore from '../../parcelData/insertBefore'; @@ -13,65 +13,65 @@ import swapNext from '../../parcelData/swapNext'; import swapPrev from '../../parcelData/swapPrev'; import unshift from '../../parcelData/unshift'; -export default (_this: StaticParcel) => ({ +export default (_this: ParcelShape) => ({ - insertAfter: (key: Key|Index, value: *): StaticParcel => { + insertAfter: (key: Key|Index, value: *): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( insertAfter(key, value) ); }, - insertBefore: (key: Key|Index, value: *): StaticParcel => { + insertBefore: (key: Key|Index, value: *): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( insertBefore(key, value) ); }, - pop: (): StaticParcel => { + pop: (): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( pop() ); }, - push: (value: *): StaticParcel => { + push: (value: *): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( push(value) ); }, - shift: (): StaticParcel => { + shift: (): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( shift() ); }, - swap: (keyA: Key|Index, keyB: Key|Index): StaticParcel => { + swap: (keyA: Key|Index, keyB: Key|Index): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( swap(keyA, keyB) ); }, - swapNext: (key: Key|Index): StaticParcel => { + swapNext: (key: Key|Index): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( swapNext(key) ); }, - swapPrev: (key: Key|Index): StaticParcel => { + swapPrev: (key: Key|Index): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( swapPrev(key) ); }, - unshift: (value: *): StaticParcel => { + unshift: (value: *): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( unshift(value) diff --git a/packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentGetMethods.js similarity index 71% rename from packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js rename to packages/dataparcels/src/parcelShape/methods/ParcelShapeParentGetMethods.js index e59c030b..2f389461 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticParentGetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentGetMethods.js @@ -2,7 +2,7 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type {ParentType} from '../../types/Types'; -import type StaticParcel from '../StaticParcel'; +import type ParcelShape from '../ParcelShape'; import parcelGet from '../../parcelData/get'; import parcelHas from '../../parcelData/has'; @@ -14,7 +14,7 @@ import toArray from 'unmutable/lib/toArray'; import toObject from 'unmutable/lib/toObject'; import pipeWith from 'unmutable/lib/util/pipeWith'; -export default (_this: StaticParcel) => ({ +export default (_this: ParcelShape) => ({ has: (key: Key|Index): boolean => { _this._prepareChildKeys(); @@ -25,7 +25,7 @@ export default (_this: StaticParcel) => ({ return size()(_this._parcelData.value); }, - get: (key: Key|Index, notFoundValue: ?* = undefined): StaticParcel => { + get: (key: Key|Index, notFoundValue: ?* = undefined): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelGet(key, notFoundValue), @@ -35,38 +35,38 @@ export default (_this: StaticParcel) => ({ ); }, - getIn: (keyPath: Array, notFoundValue: ?* = undefined): StaticParcel => { - let staticParcel = _this; + getIn: (keyPath: Array, notFoundValue: ?* = undefined): ParcelShape => { + let parcelShape = _this; for(let key of keyPath) { - if(!staticParcel.isParent() || !staticParcel.has(key)) { + if(!parcelShape.isParent() || !parcelShape.has(key)) { return _this._pipeSelf( () => ({ value: notFoundValue, - key: parcelKeyOrIndexToKey(key)(staticParcel.data) + key: parcelKeyOrIndexToKey(key)(parcelShape.data) }), { parent: _this } ); } - staticParcel = staticParcel.get(key, notFoundValue); + parcelShape = parcelShape.get(key, notFoundValue); } - return staticParcel; + return parcelShape; }, - children: (): ParentType => { + children: (): ParentType => { return pipeWith( _this._parcelData.value, map((value, key) => _this.get(key)) ); }, - toObject: (): { [key: string]: StaticParcel } => { + toObject: (): { [key: string]: ParcelShape } => { return toObject()(_this.children()); }, - toArray: (): Array => { + toArray: (): Array => { return toArray()(_this.children()); } }); diff --git a/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js similarity index 72% rename from packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js rename to packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js index aad68f33..d00d8615 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticParentSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js @@ -1,9 +1,9 @@ // @flow import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; -import type {StaticParcelUpdater} from '../../types/Types'; -import type {StaticParcelValueUpdater} from '../../types/Types'; -import type StaticParcel from '../StaticParcel'; +import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeValueUpdater} from '../../types/Types'; +import type ParcelShape from '../ParcelShape'; import parcelDelete from '../../parcelData/delete'; import parcelSetSelf from '../../parcelData/setSelf'; @@ -13,16 +13,16 @@ import ValidateValueUpdater from '../../util/ValidateValueUpdater'; import butLast from 'unmutable/lib/butLast'; import last from 'unmutable/lib/last'; -export default (_this: StaticParcel) => ({ +export default (_this: ParcelShape) => ({ - setIn: (keyPath: Array, value: any): StaticParcel => { + setIn: (keyPath: Array, value: any): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn(keyPath, parcelSetSelf(value)) ); }, - deleteIn: (keyPath: Array): StaticParcel => { + deleteIn: (keyPath: Array): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( @@ -32,7 +32,7 @@ export default (_this: StaticParcel) => ({ ); }, - updateIn: (keyPath: Array, updater: StaticParcelValueUpdater): StaticParcel => { + updateIn: (keyPath: Array, updater: ParcelShapeValueUpdater): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( @@ -47,7 +47,7 @@ export default (_this: StaticParcel) => ({ ); }, - updateShapeIn: (keyPath: Array, updater: StaticParcelUpdater): StaticParcel => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( diff --git a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js similarity index 61% rename from packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js rename to packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js index 483792ca..187fd92f 100644 --- a/packages/dataparcels/src/staticParcel/methods/StaticSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js @@ -1,11 +1,11 @@ // @flow -import type StaticParcel from '../StaticParcel'; +import type ParcelShape from '../ParcelShape'; import type {ParcelDataEvaluator} from '../../types/Types'; -import type {StaticParcelValueUpdater} from '../../types/Types'; -import type {StaticParcelSetMeta} from '../../types/Types'; -import type {StaticParcelUpdater} from '../../types/Types'; +import type {ParcelShapeValueUpdater} from '../../types/Types'; +import type {ParcelShapeSetMeta} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; -import {ShapeUpdaterNonStaticChildError} from '../../errors/Errors'; +import {ShapeUpdaterNonShapeChildError} from '../../errors/Errors'; import isParentValue from '../../parcelData/isParentValue'; import parcelSetMeta from '../../parcelData/setMeta'; import parcelSetSelf from '../../parcelData/setSelf'; @@ -19,15 +19,15 @@ import set from 'unmutable/lib/set'; import pipe from 'unmutable/lib/util/pipe'; import pipeWith from 'unmutable/lib/util/pipeWith'; -export default (_this: StaticParcel) => ({ +export default (_this: ParcelShape) => ({ - setSelf: (value: *): StaticParcel => { + setSelf: (value: *): ParcelShape => { return _this._pipeSelf( parcelSetSelf(value) ); }, - setMeta: (partialMeta: StaticParcelSetMeta): StaticParcel => { + setMeta: (partialMeta: ParcelShapeSetMeta): ParcelShape => { let meta = typeof partialMeta === "function" ? partialMeta(_this._parcelData.meta || {}) : partialMeta; @@ -37,16 +37,16 @@ export default (_this: StaticParcel) => ({ ); }, - update: (updater: StaticParcelValueUpdater): StaticParcel => { + update: (updater: ParcelShapeValueUpdater): ParcelShape => { let {value} = _this; let updatedValue = updater(value, _this); ValidateValueUpdater(value, updatedValue); return _this.set(updatedValue); }, - updateShape: (updater: StaticParcelUpdater): StaticParcel => { + updateShape: (updater: ParcelShapeUpdater): ParcelShape => { let updated: any = updater(_this); - if(_this._isStaticParcel(updated)) { + if(_this._isParcelShape(updated)) { return updated; } @@ -59,11 +59,11 @@ export default (_this: StaticParcel) => ({ del('child'), ...pipeWith( updated, - map((childStaticParcel: StaticParcel, key: string|number): ParcelDataEvaluator => { - if(!_this._isStaticParcel(childStaticParcel)) { - throw ShapeUpdaterNonStaticChildError(); + map((childParcelShape: ParcelShape, key: string|number): ParcelDataEvaluator => { + if(!_this._isParcelShape(childParcelShape)) { + throw ShapeUpdaterNonShapeChildError(); } - return parcelUpdate(key, () => childStaticParcel.data); + return parcelUpdate(key, () => childParcelShape.data); }) ) )); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js deleted file mode 100644 index d2027dbf..00000000 --- a/packages/dataparcels/src/staticParcel/__test__/StaticIndexedSetMethods-test.js +++ /dev/null @@ -1,74 +0,0 @@ -// @flow -import StaticParcel from '../StaticParcel'; - -test('StaticParcels insertAfter(key, value) should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.insertAfter(0, 3).data.value).toEqual([0,3,1,2]); -}); - -test('StaticParcels insertBefore(key, value) should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.insertBefore(0, 3).data.value).toEqual([3,0,1,2]); -}); - -test('StaticParcels push(value) should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.push(3).data.value).toEqual([0,1,2,3]); -}); - -test('StaticParcels pop() should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.pop().data.value).toEqual([0,1]); -}); - -test('StaticParcels shift() should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.shift().data.value).toEqual([1,2]); -}); - -test('StaticParcels swap() should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.swap(0,2).data.value).toEqual([2,1,0]); -}); - -test('StaticParcels swapNext() should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.swapNext(1).data.value).toEqual([0,2,1]); -}); - -test('StaticParcels swapPrev() should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.swapPrev(1).data.value).toEqual([1,0,2]); -}); - -test('StaticParcels unshift(value) should work', () => { - let staticParcel = StaticParcel.fromData({ - value: [0,1,2] - }); - - expect(staticParcel.unshift(3).data.value).toEqual([3,0,1,2]); -}); diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js deleted file mode 100644 index 6733bfd0..00000000 --- a/packages/dataparcels/src/staticParcel/__test__/StaticParcelTypes-test.js +++ /dev/null @@ -1,181 +0,0 @@ -// @flow -import {Map, List} from 'immutable'; -import StaticParcel from '../StaticParcel'; - -test('StaticParcelTypes should correctly identify primitive values', () => { - var value = 123; - expect(new StaticParcel(value).isParent()).toBe(false); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify date', () => { - var value = new Date(); - expect(new StaticParcel(value).isParent()).toBe(false); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify object values', () => { - var value = { - a: "A" - }; - expect(new StaticParcel(value).isParent()).toBe(true); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify class instance values', () => { - class Thing { - foo = "123" - } - var value = new Thing(); - expect(new StaticParcel(value).isParent()).toBe(false); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify unmutable compatible class instance values', () => { - class UnmutableCompatible { - __UNMUTABLE_COMPATIBLE__ = true; - foo = "123"; - } - var value = new UnmutableCompatible(); - expect(new StaticParcel(value).isParent()).toBe(true); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - - -test('StaticParcelTypes should correctly identify Immutable.js Map values', () => { - var value = Map({ - a: "A" - }); - expect(new StaticParcel(value).isParent()).toBe(true); - expect(new StaticParcel(value).isIndexed()).toBe(false); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - - -test('StaticParcelTypes should correctly identify array values', () => { - var value = [1,2,3]; - expect(new StaticParcel(value).isParent()).toBe(true); - expect(new StaticParcel(value).isIndexed()).toBe(true); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify Immutable.js List values', () => { - var value = List([1,2,3]); - expect(new StaticParcel(value).isParent()).toBe(true); - expect(new StaticParcel(value).isIndexed()).toBe(true); - expect(new StaticParcel(value).isChild()).toBe(false); - expect(new StaticParcel(value).isElement()).toBe(false); - expect(new StaticParcel(value).isTopLevel()).toBe(true); -}); - -test('StaticParcelTypes should correctly identify child values', () => { - var value = { - a: "A" - }; - expect(new StaticParcel(value).get("a").isParent()).toBe(false); - expect(new StaticParcel(value).get("a").isIndexed()).toBe(false); - expect(new StaticParcel(value).get("a").isChild()).toBe(true); - expect(new StaticParcel(value).get("a").isElement()).toBe(false); - expect(new StaticParcel(value).get("a").isTopLevel()).toBe(false); -}); - -test('StaticParcelTypes should correctly identify element values', () => { - var value = [1,2,3]; - expect(new StaticParcel(value).get(0).isParent()).toBe(false); - expect(new StaticParcel(value).get(0).isIndexed()).toBe(false); - expect(new StaticParcel(value).get(0).isChild()).toBe(true); - expect(new StaticParcel(value).get(0).isElement()).toBe(true); - expect(new StaticParcel(value).get(0).isTopLevel()).toBe(false); -}); - -test('StaticParcelTypes should correctly identify child values with getIn', () => { - var value = { - b: { - a: "A" - } - }; - expect(new StaticParcel(value).getIn(["b","a"]).isParent()).toBe(false); - expect(new StaticParcel(value).getIn(["b","a"]).isIndexed()).toBe(false); - expect(new StaticParcel(value).getIn(["b","a"]).isChild()).toBe(true); - expect(new StaticParcel(value).getIn(["b","a"]).isElement()).toBe(false); - expect(new StaticParcel(value).getIn(["b","a"]).isTopLevel()).toBe(false); -}); - -test('StaticParcelTypes should correctly identify element values with getIn', () => { - var value = { - b: [1,2,3] - }; - - expect(new StaticParcel(value).getIn(["b",0]).isParent()).toBe(false); - expect(new StaticParcel(value).getIn(["b",0]).isIndexed()).toBe(false); - expect(new StaticParcel(value).getIn(["b",0]).isChild()).toBe(true); - expect(new StaticParcel(value).getIn(["b",0]).isElement()).toBe(true); - expect(new StaticParcel(value).getIn(["b",0]).isTopLevel()).toBe(false); -}); - -// // method creators - -// // test('Correct methods are created for primitive values', () => { -// // var value = 123; -// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); -// // expect(() => new StaticParcel(value).has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new StaticParcel(value).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for object values', () => { -// // var value = {a: 123}; -// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); -// // expect(() => new StaticParcel(value).has('a')).not.toThrow(); -// // expect(() => new StaticParcel(value).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for array values', () => { -// // var value = [1,2,3]; -// // expect(() => new StaticParcel(value).set('A')).not.toThrow(); -// // expect(() => new StaticParcel(value).has('a')).not.toThrow(); -// // expect(() => new StaticParcel(value).pop()).not.toThrow(); -// // expect(() => new StaticParcel(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new StaticParcel(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for object child values', () => { -// // var value = {a: 123}; -// // expect(() => new StaticParcel(value).get("a").set('A')).not.toThrow(); -// // expect(() => new StaticParcel(value).get("a").has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new StaticParcel(value).get("a").pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new StaticParcel(value).get("a").delete()).not.toThrow(); -// // expect(() => new StaticParcel(value).get("a").swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for array element values', () => { -// // var value = [1,2,3]; -// // expect(() => new StaticParcel(value).get(0).set('A')).not.toThrow(); -// // expect(() => new StaticParcel(value).get(0).has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new StaticParcel(value).get(0).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new StaticParcel(value).get(0).delete()).not.toThrow(); -// // expect(() => new StaticParcel(value).get(0).swapNext()).not.toThrow(); -// // }); - diff --git a/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js b/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js deleted file mode 100644 index cdaf9447..00000000 --- a/packages/dataparcels/src/staticParcel/__test__/StaticParentGetMethods-test.js +++ /dev/null @@ -1,147 +0,0 @@ -// @flow -import StaticParcel from '../StaticParcel'; - -import map from 'unmutable/lib/map'; - -test('StaticParcels getters should work', () => { - let data = { - value: [0,1,2], - meta: { - abc: 123 - }, - key: "^", - child: [ - {key: "#a"}, - {key: "#b"}, - {key: "#c"} - ] - }; - - let parcel = StaticParcel.fromData(data); - expect(parcel.meta).toEqual(data.meta); - expect(parcel.key).toEqual(data.key); -}); - -test('StaticParcels.get should work with objects', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: { - b: 1 - } - } - }); - - let expectedParcelData = { - value: { - b: 1 - }, - key: "a" - }; - - expect(staticParcel.get('a').data).toEqual(expectedParcelData); -}); - -test('StaticParcels.getIn should work with objects', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: { - b: 1 - } - } - }); - - let expectedParcelData = { - value: 1, - key: "b" - }; - - expect(staticParcel.getIn(['a','b']).data).toEqual(expectedParcelData); -}); - -test('StaticParcels.getIn should work with objects with non-existent keys', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: { - b: 1 - } - } - }); - - let expectedParcelData = { - value: undefined, - key: "z" - }; - - expect(staticParcel.getIn(['z']).data).toEqual(expectedParcelData); -}); - -test('StaticParcels.getIn should return undefined if asking through a non-parent', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: 1 - } - }); - - let expectedParcelData = { - value: undefined, - key: "b" - }; - - expect(staticParcel.getIn(['a', 'b']).data).toEqual(expectedParcelData); -}); - -test('StaticParcels.size() should return size of parcel', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: 1, - b: 4 - } - }); - - expect(staticParcel.size()).toBe(2); -}); - -test('StaticParcels.has(key) should return a boolean indicating if key exists', () => { - let staticParcel = StaticParcel.fromData({ - value: { - a: 1, - b: 4 - } - }); - - expect(staticParcel.has('a')).toBe(true); - expect(staticParcel.has('z')).toBe(false); -}); - -test('StaticParcels.children() should make a parent data type full of static parcels', () => { - let children = StaticParcel.fromData({ - value: {a:1,b:2,c:3} - }) - .children(); - - expect(map(ii => ii.value)(children)).toEqual({a:1,b:2,c:3}); -}); - -test('StaticParcels.toObject() should make an object', () => { - let staticParcel = StaticParcel.fromData({ - value: {a:1,b:2,c:3}, - meta: { - a: {a:4,b:5,c:6} - } - }); - - var expectedValue = {a:1,b:2,c:3}; - expect(map(ii => ii.value)(staticParcel.toObject())).toEqual(expectedValue); -}); - -test('StaticParcels.toArray() should make an array', () => { - let staticParcel = StaticParcel.fromData({ - value: {a:1,b:2,c:3}, - meta: { - a: {a:4,b:5,c:6} - } - }); - - var expectedValue = [1,2,3]; - expect(map(ii => ii.value)(staticParcel.toArray())).toEqual(expectedValue); -}); diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index deacce04..6a7cfd88 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -5,7 +5,7 @@ import type Treeshare from '../treeshare/Treeshare'; import Parcel from '../parcel/Parcel'; import Action from '../change/Action'; import ChangeRequest from '../change/ChangeRequest'; -import StaticParcel from '../staticParcel/StaticParcel'; +import ParcelShape from '../parcelShape/ParcelShape'; import isPlainObject from 'unmutable/lib/util/isPlainObject'; export type ParcelData = { @@ -46,12 +46,12 @@ export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) = export type ParcelUpdater = (item: Parcel) => Parcel; export type ParcelValueUpdater = (value: *, parcel: Parcel) => *; -export type StaticParcelSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; -export type StaticParcelUpdater = (item: StaticParcel) => StaticParcel; -export type StaticParcelValueUpdater = (value: *, parcel: StaticParcel) => *; +export type ParcelShapeSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; +export type ParcelShapeUpdater = (item: ParcelShape) => ParcelShape; +export type ParcelShapeValueUpdater = (value: *, parcel: ParcelShape) => *; -export type StaticParcelConfigInternal = { - parent?: ?StaticParcel +export type ParcelShapeConfigInternal = { + parent?: ?ParcelShape }; export type Key = string; @@ -115,9 +115,9 @@ const RUNTIME_TYPES = { name: "an object containing parcel data {value: *, meta?: {}, key?: *}", check: ii => isPlainObject(ii) && ii.hasOwnProperty('value') }, - ['staticParcel']: { - name: "a StaticParcel", - check: ii => ii instanceof StaticParcel + ['parcelShape']: { + name: "a ParcelShape", + check: ii => ii instanceof ParcelShape }, ['string']: { name: "a string", diff --git a/packages/dataparcels/src/util/FilterMethods.js b/packages/dataparcels/src/util/FilterMethods.js index e518b200..200f911d 100644 --- a/packages/dataparcels/src/util/FilterMethods.js +++ b/packages/dataparcels/src/util/FilterMethods.js @@ -1,11 +1,11 @@ // @flow import type Parcel from '../parcel/Parcel'; -import type StaticParcel from '../staticParcel/StaticParcel'; +import type ParcelShape from '../parcelShape/ParcelShape'; import map from 'unmutable/lib/map'; import pipeWith from 'unmutable/lib/util/pipeWith'; -export default (parcelType: string, methodCreator: Function) => (parcel: Parcel|StaticParcel, ...args: Array<*>): { [key: string]: Function } => { +export default (parcelType: string, methodCreator: Function) => (parcel: Parcel|ParcelShape, ...args: Array<*>): { [key: string]: Function } => { let methods: { [key: string]: Function } = methodCreator(parcel, ...args); // $FlowFixMe - I want to do this diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index 3d153f6f..c92fbc5c 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -9,7 +9,7 @@ export default dataparcels; export {Action} from 'dataparcels'; export {ChangeRequest} from 'dataparcels'; -export {StaticParcel} from 'dataparcels'; +export {ParcelShape} from 'dataparcels'; export {DeletedParcelMarker} from 'dataparcels'; // @@ -27,10 +27,10 @@ export type {ParcelMapper} from 'dataparcels'; export type {ParcelUpdater} from 'dataparcels'; export type {ParcelValueUpdater} from 'dataparcels'; -export type {StaticParcelSetMeta} from 'dataparcels'; -export type {StaticParcelUpdater} from 'dataparcels'; -export type {StaticParcelValueUpdater} from 'dataparcels'; -export type {StaticParcelConfigInternal} from 'dataparcels'; +export type {ParcelShapeSetMeta} from 'dataparcels'; +export type {ParcelShapeUpdater} from 'dataparcels'; +export type {ParcelShapeValueUpdater} from 'dataparcels'; +export type {ParcelShapeConfigInternal} from 'dataparcels'; export type {Key} from 'dataparcels'; export type {Index} from 'dataparcels'; From 91e6b330389ae23f39e8e159ad85ae9a121bd25a Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:46:53 +1100 Subject: [PATCH 060/120] amend: rename ParcelShapeShapeUpdater --- packages/dataparcels/src/index.js | 2 +- packages/dataparcels/src/parcel/Parcel.js | 8 ++++---- .../dataparcels/src/parcel/methods/ParcelChangeMethods.js | 4 ++-- .../dataparcels/src/parcel/methods/ParentChangeMethods.js | 6 +++--- packages/dataparcels/src/parcelShape/ParcelShape.js | 8 ++++---- .../parcelShape/methods/ParcelShapeParentSetMethods.js | 4 ++-- .../src/parcelShape/methods/ParcelShapeSetMethods.js | 4 ++-- packages/dataparcels/src/types/Types.js | 2 +- packages/react-dataparcels/src/index.js | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index 8aa03a1e..56e6e398 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -23,8 +23,8 @@ export type {ParcelUpdater} from './types/Types'; export type {ParcelValueUpdater} from './types/Types'; export type {ParcelShapeSetMeta} from './types/Types'; -export type {ParcelShapeUpdater} from './types/Types'; export type {ParcelShapeValueUpdater} from './types/Types'; +export type {ParcelShapeShapeUpdater} from './types/Types'; export type {ParcelShapeConfigInternal} from './types/Types'; export type {Key} from './types/Types'; diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 27bf7108..6d0f7bd7 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -13,7 +13,7 @@ import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; import type {ParentType} from '../types/Types'; -import type {ParcelShapeUpdater} from '../types/Types'; +import type {ParcelShapeShapeUpdater} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -287,12 +287,12 @@ export default class Parcel { ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); updateShape = overload({ - ["1"]: (updater: ParcelShapeUpdater) => this._methods.updateSelfShape(updater), - ["2"]: (key: Key|Index, updater: ParcelShapeUpdater) => this._methods.updateShape(key, updater) + ["1"]: (updater: ParcelShapeShapeUpdater) => this._methods.updateSelfShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeShapeUpdater) => this._methods.updateShape(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateShapeIn = (keyPath: Array, updater: ParcelShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: ParcelShapeShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 5a4fa92f..dc2a3d6c 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -2,7 +2,7 @@ import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; @@ -24,7 +24,7 @@ export default (_this: Parcel, dispatch: Function) => ({ _this.set(updatedValue); }, - updateSelfShape: (updater: ParcelShapeUpdater) => { + updateSelfShape: (updater: ParcelShapeShapeUpdater) => { Types(`updateSelfShape()`, `updater`, `function`)(updater); let parcelShapeUpdater = ParcelShape._updateFromData(updater); let updated = parcelShapeUpdater(_this._parcelData); diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index 92f87161..e63f22da 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -3,7 +3,7 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; @@ -34,7 +34,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).update(updater); }, - updateShape: (key: Key|Index, updater: ParcelShapeUpdater) => { + updateShape: (key: Key|Index, updater: ParcelShapeShapeUpdater) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); _this.get(key).updateShape(updater); @@ -46,7 +46,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.getIn(keyPath).update(updater); }, - updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater) => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeShapeUpdater) => { Types(`updateShapeIn()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateShapeIn()`, `updater`, `function`)(updater); _this.getIn(keyPath).updateShape(updater); diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 9e78bf77..5e94e0cc 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -5,7 +5,7 @@ import type {ParcelData} from '../types/Types'; import type {ParentType} from '../types/Types'; import type {ParcelShapeValueUpdater} from '../types/Types'; import type {ParcelShapeConfigInternal} from '../types/Types'; -import type {ParcelShapeUpdater} from '../types/Types'; +import type {ParcelShapeShapeUpdater} from '../types/Types'; import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; @@ -71,7 +71,7 @@ export default class ParcelShape { _parcelData: ParcelData; _parcelTypes: ParcelTypes; - static _updateFromData(updater: ParcelShapeUpdater): Function { + static _updateFromData(updater: ParcelShapeShapeUpdater): Function { return (parcelData: ParcelData): ParcelData => ParcelShape .fromData(parcelData) .updateShape(updater) @@ -178,8 +178,8 @@ export default class ParcelShape { ["2"]: (key: Key|Index, updater: ParcelShapeValueUpdater): ParcelShape => this.updateIn([key], updater) }); updateShape = overload({ - ["1"]: (updater: ParcelShapeUpdater): ParcelShape => this._methods.updateShape(updater), - ["2"]: (key: Key|Index, updater: ParcelShapeUpdater): ParcelShape => this.updateShapeIn([key], updater) + ["1"]: (updater: ParcelShapeShapeUpdater): ParcelShape => this._methods.updateShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeShapeUpdater): ParcelShape => this.updateShapeIn([key], updater) }); updateIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateIn(keyPath, updater); updateShapeIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateShapeIn(keyPath, updater); diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js index d00d8615..b90d8020 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js @@ -1,7 +1,7 @@ // @flow import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeShapeUpdater} from '../../types/Types'; import type {ParcelShapeValueUpdater} from '../../types/Types'; import type ParcelShape from '../ParcelShape'; @@ -47,7 +47,7 @@ export default (_this: ParcelShape) => ({ ); }, - updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater): ParcelShape => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeShapeUpdater): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js index 187fd92f..94beacd6 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js @@ -3,7 +3,7 @@ import type ParcelShape from '../ParcelShape'; import type {ParcelDataEvaluator} from '../../types/Types'; import type {ParcelShapeValueUpdater} from '../../types/Types'; import type {ParcelShapeSetMeta} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeShapeUpdater} from '../../types/Types'; import {ShapeUpdaterNonShapeChildError} from '../../errors/Errors'; import isParentValue from '../../parcelData/isParentValue'; @@ -44,7 +44,7 @@ export default (_this: ParcelShape) => ({ return _this.set(updatedValue); }, - updateShape: (updater: ParcelShapeUpdater): ParcelShape => { + updateShape: (updater: ParcelShapeShapeUpdater): ParcelShape => { let updated: any = updater(_this); if(_this._isParcelShape(updated)) { return updated; diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index 6a7cfd88..fb0bd705 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -47,8 +47,8 @@ export type ParcelUpdater = (item: Parcel) => Parcel; export type ParcelValueUpdater = (value: *, parcel: Parcel) => *; export type ParcelShapeSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; -export type ParcelShapeUpdater = (item: ParcelShape) => ParcelShape; export type ParcelShapeValueUpdater = (value: *, parcel: ParcelShape) => *; +export type ParcelShapeShapeUpdater = (item: ParcelShape) => ParcelShape; export type ParcelShapeConfigInternal = { parent?: ?ParcelShape diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index c92fbc5c..6a54590e 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -28,8 +28,8 @@ export type {ParcelUpdater} from 'dataparcels'; export type {ParcelValueUpdater} from 'dataparcels'; export type {ParcelShapeSetMeta} from 'dataparcels'; -export type {ParcelShapeUpdater} from 'dataparcels'; export type {ParcelShapeValueUpdater} from 'dataparcels'; +export type {ParcelShapeShapeUpdater} from 'dataparcels'; export type {ParcelShapeConfigInternal} from 'dataparcels'; export type {Key} from 'dataparcels'; From ca6fe361311d902d792bf8d0097a59636adf1715 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:53:44 +1100 Subject: [PATCH 061/120] amend: revert parcel shape shape --- packages/dataparcels/src/index.js | 2 +- packages/dataparcels/src/parcel/Parcel.js | 8 ++++---- .../dataparcels/src/parcel/methods/ParcelChangeMethods.js | 4 ++-- .../dataparcels/src/parcel/methods/ParentChangeMethods.js | 6 +++--- packages/dataparcels/src/parcelShape/ParcelShape.js | 8 ++++---- .../parcelShape/methods/ParcelShapeParentSetMethods.js | 4 ++-- .../src/parcelShape/methods/ParcelShapeSetMethods.js | 4 ++-- packages/react-dataparcels/src/index.js | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index 56e6e398..a816f006 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -21,10 +21,10 @@ export type {ParcelBatcher} from './types/Types'; export type {ParcelMapper} from './types/Types'; export type {ParcelUpdater} from './types/Types'; export type {ParcelValueUpdater} from './types/Types'; +export type {ParcelShapeUpdater} from './types/Types'; export type {ParcelShapeSetMeta} from './types/Types'; export type {ParcelShapeValueUpdater} from './types/Types'; -export type {ParcelShapeShapeUpdater} from './types/Types'; export type {ParcelShapeConfigInternal} from './types/Types'; export type {Key} from './types/Types'; diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 6d0f7bd7..27bf7108 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -13,7 +13,7 @@ import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; import type {ParentType} from '../types/Types'; -import type {ParcelShapeShapeUpdater} from '../types/Types'; +import type {ParcelShapeUpdater} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -287,12 +287,12 @@ export default class Parcel { ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) }); updateShape = overload({ - ["1"]: (updater: ParcelShapeShapeUpdater) => this._methods.updateSelfShape(updater), - ["2"]: (key: Key|Index, updater: ParcelShapeShapeUpdater) => this._methods.updateShape(key, updater) + ["1"]: (updater: ParcelShapeUpdater) => this._methods.updateSelfShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeUpdater) => this._methods.updateShape(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateShapeIn = (keyPath: Array, updater: ParcelShapeShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); + updateShapeIn = (keyPath: Array, updater: ParcelShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index dc2a3d6c..5a4fa92f 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -2,7 +2,7 @@ import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; @@ -24,7 +24,7 @@ export default (_this: Parcel, dispatch: Function) => ({ _this.set(updatedValue); }, - updateSelfShape: (updater: ParcelShapeShapeUpdater) => { + updateSelfShape: (updater: ParcelShapeUpdater) => { Types(`updateSelfShape()`, `updater`, `function`)(updater); let parcelShapeUpdater = ParcelShape._updateFromData(updater); let updated = parcelShapeUpdater(_this._parcelData); diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index e63f22da..92f87161 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -3,7 +3,7 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; @@ -34,7 +34,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.get(key).update(updater); }, - updateShape: (key: Key|Index, updater: ParcelShapeShapeUpdater) => { + updateShape: (key: Key|Index, updater: ParcelShapeUpdater) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); _this.get(key).updateShape(updater); @@ -46,7 +46,7 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.getIn(keyPath).update(updater); }, - updateShapeIn: (keyPath: Array, updater: ParcelShapeShapeUpdater) => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater) => { Types(`updateShapeIn()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateShapeIn()`, `updater`, `function`)(updater); _this.getIn(keyPath).updateShape(updater); diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 5e94e0cc..9e78bf77 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -5,7 +5,7 @@ import type {ParcelData} from '../types/Types'; import type {ParentType} from '../types/Types'; import type {ParcelShapeValueUpdater} from '../types/Types'; import type {ParcelShapeConfigInternal} from '../types/Types'; -import type {ParcelShapeShapeUpdater} from '../types/Types'; +import type {ParcelShapeUpdater} from '../types/Types'; import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; @@ -71,7 +71,7 @@ export default class ParcelShape { _parcelData: ParcelData; _parcelTypes: ParcelTypes; - static _updateFromData(updater: ParcelShapeShapeUpdater): Function { + static _updateFromData(updater: ParcelShapeUpdater): Function { return (parcelData: ParcelData): ParcelData => ParcelShape .fromData(parcelData) .updateShape(updater) @@ -178,8 +178,8 @@ export default class ParcelShape { ["2"]: (key: Key|Index, updater: ParcelShapeValueUpdater): ParcelShape => this.updateIn([key], updater) }); updateShape = overload({ - ["1"]: (updater: ParcelShapeShapeUpdater): ParcelShape => this._methods.updateShape(updater), - ["2"]: (key: Key|Index, updater: ParcelShapeShapeUpdater): ParcelShape => this.updateShapeIn([key], updater) + ["1"]: (updater: ParcelShapeUpdater): ParcelShape => this._methods.updateShape(updater), + ["2"]: (key: Key|Index, updater: ParcelShapeUpdater): ParcelShape => this.updateShapeIn([key], updater) }); updateIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateIn(keyPath, updater); updateShapeIn = (keyPath: Array, updater: ParcelShapeValueUpdater) => this._methods.updateShapeIn(keyPath, updater); diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js index b90d8020..d00d8615 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js @@ -1,7 +1,7 @@ // @flow import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; -import type {ParcelShapeShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import type {ParcelShapeValueUpdater} from '../../types/Types'; import type ParcelShape from '../ParcelShape'; @@ -47,7 +47,7 @@ export default (_this: ParcelShape) => ({ ); }, - updateShapeIn: (keyPath: Array, updater: ParcelShapeShapeUpdater): ParcelShape => { + updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( parcelUpdateIn( diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js index 94beacd6..187fd92f 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeSetMethods.js @@ -3,7 +3,7 @@ import type ParcelShape from '../ParcelShape'; import type {ParcelDataEvaluator} from '../../types/Types'; import type {ParcelShapeValueUpdater} from '../../types/Types'; import type {ParcelShapeSetMeta} from '../../types/Types'; -import type {ParcelShapeShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import {ShapeUpdaterNonShapeChildError} from '../../errors/Errors'; import isParentValue from '../../parcelData/isParentValue'; @@ -44,7 +44,7 @@ export default (_this: ParcelShape) => ({ return _this.set(updatedValue); }, - updateShape: (updater: ParcelShapeShapeUpdater): ParcelShape => { + updateShape: (updater: ParcelShapeUpdater): ParcelShape => { let updated: any = updater(_this); if(_this._isParcelShape(updated)) { return updated; diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index 6a54590e..b4e432a3 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -26,10 +26,10 @@ export type {ParcelBatcher} from 'dataparcels'; export type {ParcelMapper} from 'dataparcels'; export type {ParcelUpdater} from 'dataparcels'; export type {ParcelValueUpdater} from 'dataparcels'; +export type {ParcelShapeUpdater} from 'dataparcels'; export type {ParcelShapeSetMeta} from 'dataparcels'; export type {ParcelShapeValueUpdater} from 'dataparcels'; -export type {ParcelShapeShapeUpdater} from 'dataparcels'; export type {ParcelShapeConfigInternal} from 'dataparcels'; export type {Key} from 'dataparcels'; From 9226944e5554b41233b34a3395719c08806c396d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:54:06 +1100 Subject: [PATCH 062/120] amend: better flow types --- packages/dataparcels/src/parcel/methods/ModifyMethods.js | 5 +++-- packages/dataparcels/src/types/Types.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index f48ffdba..1aee4e73 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -3,6 +3,7 @@ import type ChangeRequest from '../../change/ChangeRequest'; import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; +import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ParcelShape from '../../parcelShape/ParcelShape'; @@ -74,7 +75,7 @@ export default (_this: Parcel): Object => ({ }); }, - modifyShapeDown: (updater: Function): Parcel => { + modifyShapeDown: (updater: ParcelShapeUpdater): Parcel => { Types(`modifyShapeDown()`, `updater`, `function`)(updater); let shapeUpdater = ParcelShape._updateFromData(updater); @@ -88,7 +89,7 @@ export default (_this: Parcel): Object => ({ }); }, - modifyShapeUp: (updater: Function): Parcel => { + modifyShapeUp: (updater: ParcelShapeUpdater): Parcel => { Types(`modifyShapeUp()`, `updater`, `function`)(updater); let shapeUpdater = ParcelShape._updateFromData(updater); diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index fb0bd705..a45eab8d 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -44,11 +44,11 @@ export type ParcelMeta = {[key: string]: *}; export type ParcelBatcher = (item: Parcel) => void; export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) => *; export type ParcelUpdater = (item: Parcel) => Parcel; -export type ParcelValueUpdater = (value: *, parcel: Parcel) => *; +export type ParcelValueUpdater = (value: *, parcel: Parcel) => any; +export type ParcelShapeUpdater = (item: ParcelShape) => any; export type ParcelShapeSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; -export type ParcelShapeValueUpdater = (value: *, parcel: ParcelShape) => *; -export type ParcelShapeShapeUpdater = (item: ParcelShape) => ParcelShape; +export type ParcelShapeValueUpdater = (value: *, parcel: ParcelShape) => any; export type ParcelShapeConfigInternal = { parent?: ?ParcelShape From e722e6b3b44825982eb468675ed6e8371864dc4c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 00:55:37 +1100 Subject: [PATCH 063/120] docs: typo --- packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md b/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md index 438c96d4..3a7c4e6d 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/isChild.md @@ -4,6 +4,6 @@ import Link from 'component/Link'; isChild(): boolean ``` -Returns true if the ParcelShapes is a child parcel. Read Parcel types for more info. +Returns true if the ParcelShape is a child parcel. Read Parcel types for more info. When a ParcelShape is a child parcel, it allows the use of child methods. From eddf89fae01ad16d28e4b602631dced93fc7a017 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 10:43:52 +1100 Subject: [PATCH 064/120] test: improve initialMeta tests --- .../src/parcel/__test__/ModifyMethods-test.js | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index d8096921..0f41de20 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -307,24 +307,14 @@ test('Parcel.initialMeta() should merge', () => { }); test('Parcel.initialMeta() should do nothing to data if all meta keys are already set', () => { - let handleChange = jest.fn(); let parcel = new Parcel({ - value: 123, - handleChange - }) - .initialMeta({a:1, b:2}) - .initialMeta({a:1, b:2}) // do nothing to data + value: 123 + }).initialMeta({a:1, b:2}); - expect(parcel.data).toEqual({ - value: 123, - meta: { - a: 1, - b: 2 - }, - child: undefined, - key: "^" - }); + let parcel2 = parcel.initialMeta({a:1, b:2}); + + expect(parcel2.data).toEqual(parcel.data); }); test('Sanity check: A big strange test of a big strange chain of deep updatery stuff', () => { From 7a760a51f3b20a0b91ca6822c895a0580f057415 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 12:44:02 +1100 Subject: [PATCH 065/120] v0.18.0-0 --- lerna.json | 2 +- packages/dataparcels-docs/package.json | 2 +- packages/dataparcels/package.json | 2 +- packages/react-dataparcels/package.json | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lerna.json b/lerna.json index 41b1896e..24f2e77f 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "lerna": "2.9.0", "npmClient": "yarn", "useWorkspaces": true, - "version": "0.17.0" + "version": "0.18.0-0" } diff --git a/packages/dataparcels-docs/package.json b/packages/dataparcels-docs/package.json index aba2a175..971f4b3f 100644 --- a/packages/dataparcels-docs/package.json +++ b/packages/dataparcels-docs/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels-docs", - "version": "0.17.0", + "version": "0.18.0-0", "description": "Dataparcels Documentation", "author": "Damien Clarke", "license": "MIT", diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index 9405a9d9..e155156b 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels", - "version": "0.17.0", + "version": "0.18.0-0", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index c71f44e5..af4321d9 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "react-dataparcels", - "version": "0.17.0", + "version": "0.18.0-0", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", @@ -23,7 +23,7 @@ }, "dependencies": { "babel-runtime": "6.23.0", - "dataparcels": "^0.17.0", + "dataparcels": "^0.18.0-0", "unmutable": "^0.39.0" } } From b0fd93bb795b7f619fd1fdc4536b7c7288ab2776 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 12:46:42 +1100 Subject: [PATCH 066/120] v0.18.0-1 --- lerna.json | 2 +- packages/dataparcels-docs/package.json | 2 +- packages/dataparcels/package.json | 2 +- packages/react-dataparcels/package.json | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lerna.json b/lerna.json index 24f2e77f..726c40ba 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "lerna": "2.9.0", "npmClient": "yarn", "useWorkspaces": true, - "version": "0.18.0-0" + "version": "0.18.0-1" } diff --git a/packages/dataparcels-docs/package.json b/packages/dataparcels-docs/package.json index 971f4b3f..5170b093 100644 --- a/packages/dataparcels-docs/package.json +++ b/packages/dataparcels-docs/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels-docs", - "version": "0.18.0-0", + "version": "0.18.0-1", "description": "Dataparcels Documentation", "author": "Damien Clarke", "license": "MIT", diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index e155156b..16946fd2 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels", - "version": "0.18.0-0", + "version": "0.18.0-1", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index af4321d9..ff1b885d 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "react-dataparcels", - "version": "0.18.0-0", + "version": "0.18.0-1", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", @@ -23,7 +23,7 @@ }, "dependencies": { "babel-runtime": "6.23.0", - "dataparcels": "^0.18.0-0", + "dataparcels": "^0.18.0-1", "unmutable": "^0.39.0" } } From 53f99d7ad114336d536cc6f31747aed0b0ad49b3 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 15 Jan 2019 12:48:18 +1100 Subject: [PATCH 067/120] v0.18.0-2 --- lerna.json | 2 +- packages/dataparcels-docs/package.json | 2 +- packages/dataparcels/package.json | 2 +- packages/react-dataparcels/package.json | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lerna.json b/lerna.json index 726c40ba..55ba91a5 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "lerna": "2.9.0", "npmClient": "yarn", "useWorkspaces": true, - "version": "0.18.0-1" + "version": "0.18.0-2" } diff --git a/packages/dataparcels-docs/package.json b/packages/dataparcels-docs/package.json index 5170b093..90d2640a 100644 --- a/packages/dataparcels-docs/package.json +++ b/packages/dataparcels-docs/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels-docs", - "version": "0.18.0-1", + "version": "0.18.0-2", "description": "Dataparcels Documentation", "author": "Damien Clarke", "license": "MIT", diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index 16946fd2..021793c5 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "dataparcels", - "version": "0.18.0-1", + "version": "0.18.0-2", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index ff1b885d..6777e90d 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -1,6 +1,6 @@ { "name": "react-dataparcels", - "version": "0.18.0-1", + "version": "0.18.0-2", "description": "A library for editing data structures that works really well with React.", "main": "lib/index.js", "license": "UNLICENSED", @@ -23,7 +23,7 @@ }, "dependencies": { "babel-runtime": "6.23.0", - "dataparcels": "^0.18.0-1", + "dataparcels": "^0.18.0-2", "unmutable": "^0.39.0" } } From 62beb40133779f28a234bbfcf3272f517672345d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 16 Jan 2019 01:13:12 +1100 Subject: [PATCH 068/120] add: Parcel.move() --- .../dataparcels/src/change/ActionCreators.js | 21 ++++++++++ .../src/change/ChangeRequestReducer.js | 11 ++--- .../ChangeRequestReducerIndexed-test.js | 27 ++++++++---- packages/dataparcels/src/errors/Errors.js | 1 - packages/dataparcels/src/parcel/Parcel.js | 4 ++ .../__test__/ElementParcelMethods-test.js | 42 +++++++++++++++++++ .../__test__/IndexedParcelMethods-test.js | 40 ++++++++++++++++++ .../parcel/methods/ElementChangeMethods.js | 5 +++ .../parcel/methods/IndexedChangeMethods.js | 6 +++ packages/dataparcels/src/parcelData/move.js | 3 ++ packages/dataparcels/src/parcelData/swap.js | 30 +------------ .../dataparcels/src/parcelData/swapOrMove.js | 33 +++++++++++++++ 12 files changed, 178 insertions(+), 45 deletions(-) create mode 100644 packages/dataparcels/src/parcelData/move.js create mode 100644 packages/dataparcels/src/parcelData/swapOrMove.js diff --git a/packages/dataparcels/src/change/ActionCreators.js b/packages/dataparcels/src/change/ActionCreators.js index 383b3884..852f33d5 100644 --- a/packages/dataparcels/src/change/ActionCreators.js +++ b/packages/dataparcels/src/change/ActionCreators.js @@ -49,6 +49,25 @@ const insertBeforeSelf: Function = (value: *): Action => { }); }; +const move: Function = (keyA: Key|Index, keyB: Key|Index): Action => { + return new Action({ + type: "move", + keyPath: [keyA], + payload: { + moveKey: keyB + } + }); +}; + +const moveSelf: Function = (keyB: Key|Index): Action => { + return new Action({ + type: "move", + payload: { + moveKey: keyB + } + }); +}; + const push: Function = (values: Array<*>): Action => { return new Action({ type: "push", @@ -155,6 +174,8 @@ export default { insertAfterSelf, insertBefore, insertBeforeSelf, + move, + moveSelf, push, pop, setData, diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index e3782d49..267e4bd7 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -10,12 +10,12 @@ import pipe from 'unmutable/lib/util/pipe'; import composeWith from 'unmutable/lib/util/composeWith'; import {ReducerInvalidActionError} from '../errors/Errors'; -import {ReducerSwapKeyError} from '../errors/Errors'; import del from '../parcelData/delete'; import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; import insertAfter from '../parcelData/insertAfter'; import insertBefore from '../parcelData/insertBefore'; +import move from '../parcelData/move'; import pop from '../parcelData/pop'; import push from '../parcelData/push'; import setMeta from '../parcelData/setMeta'; @@ -31,18 +31,14 @@ const actionMap = { delete: ({lastKey}) => del(lastKey), insertAfter: ({lastKey, value}) => insertAfter(lastKey, value), insertBefore: ({lastKey, value}) => insertBefore(lastKey, value), + move: ({lastKey, moveKey}) => move(lastKey, moveKey), pop: () => pop(), push: ({values}) => push(...values), setData: parcelData => () => parcelData, setMeta: ({meta}) => setMeta(meta), set: ({value}) => setSelf(value), shift: () => shift(), - swap: ({lastKey, swapKey}: any): ParcelDataEvaluator => { - if(typeof swapKey === "undefined") { - throw ReducerSwapKeyError(); - } - return swap(lastKey, swapKey); - }, + swap: ({lastKey, swapKey}) => swap(lastKey, swapKey), swapNext: ({lastKey}) => swapNext(lastKey), swapPrev: ({lastKey}) => swapPrev(lastKey), unshift: ({values}) => unshift(...values) @@ -52,6 +48,7 @@ const parentActionMap = { delete: true, insertAfter: true, insertBefore: true, + move: true, swap: true, swapNext: true, swapPrev: true diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js index ac8dbc7b..dd80a70d 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducerIndexed-test.js @@ -23,6 +23,7 @@ let EXPECTED_KEY_AND_META = { [ "insertAfter", "insertBefore", + "move", "swap", "swapNext", "swapPrev" @@ -32,15 +33,6 @@ let EXPECTED_KEY_AND_META = { }); }); -test('Reducer swap action should throw error if payload.swapKey doesnt exist', () => { - let action = new Action({ - type: "swap", - keyPath: [0] - }); - - expect(() => makeReducer(action)(data)).toThrowError(`swap actions must have a swapKey in their payload`); -}); - const TestIndex = (arr) => arr.map(({action, expectedData}) => { test(`Reducer ${action.type} action should ${action.type} with keyPath ${JSON.stringify(action.keyPath)}`, () => { expect(makeReducer(new Action(action))(data)).toEqual(expectedData); @@ -239,6 +231,23 @@ TestIndex([ } ]); +TestIndex([ + { + action: { + type: "move", + payload: { + moveKey: 0 + }, + keyPath: [2] + }, + expectedData: { + value: [2,0,1], + child: [{key: "#c"},{key: "#a"}, {key: "#b"}], + ...EXPECTED_KEY_AND_META + } + } +]); + TestIndex([ { action: { diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index a1641983..c9055bf1 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -2,7 +2,6 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); -export const ReducerSwapKeyError = () => new Error(`swap actions must have a swapKey in their payload`); export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); export const ShapeUpdaterNonShapeChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a ParcelShape`); diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 2637995c..2038b9ce 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -315,6 +315,10 @@ export default class Parcel { ["1"]: (value: any) => this._methods.insertBeforeSelf(value), ["2"]: (key: Key|Index, value: any) => this._methods.insertBefore(key, value) }); + move = overload({ + ["1"]: (key: Key|Index) => this._methods.moveSelf(key), + ["2"]: (keyA: Key|Index, keyB: Key|Index) => this._methods.move(keyA, keyB) + }); push = (...values: Array) => this._methods.push(...values); pop = () => this._methods.pop(); shift = () => this._methods.shift(); diff --git a/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js b/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js index 13bcf938..d429299c 100644 --- a/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ElementParcelMethods-test.js @@ -109,6 +109,48 @@ test('ElementParcel.insertAfter() should insert', () => { .insertAfter(4); }); +test('ElementParcel.move() should move', () => { + expect.assertions(2); + + var data = { + value: [1,2,3], + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + var expectedData = { + meta: {}, + value: [3,1,2], + key: '^', + child: [ + {key: "#c"}, + {key: "#a"}, + {key: "#b"} + ] + }; + + var expectedAction = { + type: "move", + keyPath: ["#c"], + payload: { + moveKey: 0 + } + }; + + new Parcel({ + ...data, + handleChange: (parcel, changeRequest) => { + expect(expectedData).toEqual(parcel.data); + expect(expectedAction).toEqual(GetAction(changeRequest)); + } + }) + .get(2) + .move(0); +}); + test('ElementParcel.swap() should swap', () => { expect.assertions(2); diff --git a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js index 724c66fe..1a8818c6 100644 --- a/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/IndexedParcelMethods-test.js @@ -190,6 +190,46 @@ test('IndexedParcel.insertAfter() should insertAfter', () => { expect(GetAction(keyedHandleChange.mock.calls[0][1])).toEqual(expectedActionWithKey); }); +test('IndexedParcel.move() should move', () => { + expect.assertions(2); + + var data = { + value: [1,2,3], + child: [ + {key: "#a"}, + {key: "#b"}, + {key: "#c"} + ] + }; + + var expectedData = { + meta: {}, + value: [3,1,2], + key: '^', + child: [ + {key: "#c"}, + {key: "#a"}, + {key: "#b"} + ] + }; + + var expectedAction = { + type: "move", + keyPath: [2], + payload: { + moveKey: 0 + } + }; + + new Parcel({ + ...data, + handleChange: (parcel, changeRequest) => { + expect(expectedData).toEqual(parcel.data); + expect(expectedAction).toEqual(GetAction(changeRequest)); + } + }).move(2,0); +}); + test('IndexedParcel.push() should push', () => { expect.assertions(2); diff --git a/packages/dataparcels/src/parcel/methods/ElementChangeMethods.js b/packages/dataparcels/src/parcel/methods/ElementChangeMethods.js index 972bb2c8..f1cfafd3 100644 --- a/packages/dataparcels/src/parcel/methods/ElementChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ElementChangeMethods.js @@ -16,6 +16,11 @@ export default (_this: Parcel, dispatch: Function): Object => ({ dispatch(ActionCreators.insertBeforeSelf(value)); }, + moveSelf: (key: Key|Index) => { + Types(`moveSelf()`, `key`, `keyIndex`)(key); + dispatch(ActionCreators.moveSelf(key)); + }, + swapNextSelf: () => { dispatch(ActionCreators.swapNextSelf()); }, diff --git a/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js b/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js index f1b00f83..56552d11 100644 --- a/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/IndexedChangeMethods.js @@ -18,6 +18,12 @@ export default (_this: Parcel, dispatch: Function): Object => ({ dispatch(ActionCreators.insertBefore(key, value)); }, + move: (keyA: Key|Index, keyB: Key|Index) => { + Types(`move()`, `keyA`, `keyIndex`)(keyA); + Types(`move()`, `keyB`, `keyIndex`)(keyB); + dispatch(ActionCreators.move(keyA, keyB)); + }, + push: (...values: Array<*>) => { dispatch(ActionCreators.push(values)); }, diff --git a/packages/dataparcels/src/parcelData/move.js b/packages/dataparcels/src/parcelData/move.js new file mode 100644 index 00000000..a448c0e4 --- /dev/null +++ b/packages/dataparcels/src/parcelData/move.js @@ -0,0 +1,3 @@ +// @flow +import swapOrMove from './swapOrMove'; +export default swapOrMove('move'); diff --git a/packages/dataparcels/src/parcelData/swap.js b/packages/dataparcels/src/parcelData/swap.js index 9f4123a9..cac3c883 100644 --- a/packages/dataparcels/src/parcelData/swap.js +++ b/packages/dataparcels/src/parcelData/swap.js @@ -1,29 +1,3 @@ // @flow -import type {Index} from '../types/Types'; -import type {Key} from '../types/Types'; -import type {ParcelData} from '../types/Types'; - -import prepareChildKeys from './prepareChildKeys'; -import keyOrIndexToIndex from './keyOrIndexToIndex'; - -import swap from 'unmutable/lib/swap'; - -export default (keyA: Key|Index, keyB: Key|Index) => (parcelData: ParcelData): ParcelData => { - - let parcelDataWithChildKeys = prepareChildKeys()(parcelData); - - let indexA: ?Index = keyOrIndexToIndex(keyA)(parcelDataWithChildKeys); - let indexB: ?Index = keyOrIndexToIndex(keyB)(parcelDataWithChildKeys); - - if(typeof indexA === "undefined" || typeof indexB === "undefined") { - return parcelData; - } - - let {value, child} = parcelDataWithChildKeys; - - return { - ...parcelDataWithChildKeys, - value: swap(indexA, indexB)(value), - child: swap(indexA, indexB)(child) - }; -}; +import swapOrMove from './swapOrMove'; +export default swapOrMove('swap'); diff --git a/packages/dataparcels/src/parcelData/swapOrMove.js b/packages/dataparcels/src/parcelData/swapOrMove.js new file mode 100644 index 00000000..f15e048c --- /dev/null +++ b/packages/dataparcels/src/parcelData/swapOrMove.js @@ -0,0 +1,33 @@ +// @flow +import type {Index} from '../types/Types'; +import type {Key} from '../types/Types'; +import type {ParcelData} from '../types/Types'; + +import prepareChildKeys from './prepareChildKeys'; +import keyOrIndexToIndex from './keyOrIndexToIndex'; + +import move from 'unmutable/lib/move'; +import swap from 'unmutable/lib/swap'; + +export default (swapOrMove: string): Function => { + let fn = swapOrMove === 'swap' ? swap : move; + return (keyA: Key|Index, keyB: Key|Index) => (parcelData: ParcelData): ParcelData => { + + let parcelDataWithChildKeys = prepareChildKeys()(parcelData); + + let indexA: ?Index = keyOrIndexToIndex(keyA)(parcelDataWithChildKeys); + let indexB: ?Index = keyOrIndexToIndex(keyB)(parcelDataWithChildKeys); + + if(typeof indexA === "undefined" || typeof indexB === "undefined") { + return parcelData; + } + + let {value, child} = parcelDataWithChildKeys; + + return { + ...parcelDataWithChildKeys, + value: fn(indexA, indexB)(value), + child: fn(indexA, indexB)(child) + }; + }; +}; From 9fe45efd454dc483a6c9c547f98d6140d1330907 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 16 Jan 2019 01:13:25 +1100 Subject: [PATCH 069/120] add: ParcelShape.move() --- packages/dataparcels/src/parcelShape/ParcelShape.js | 1 + .../__test__/ParcelShapeIndexedSetMethods-test.js | 8 ++++++++ .../parcelShape/methods/ParcelShapeIndexedSetMethods.js | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 1d137f77..2f7e5a90 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -187,6 +187,7 @@ export default class ParcelShape { // Indexed methods insertAfter = (key: Key|Index, value: any) => this._methods.insertAfter(key, value); insertBefore = (key: Key|Index, value: any) => this._methods.insertBefore(key, value); + move = (keyA: Key|Index, keyB: Key|Index) => this._methods.move(keyA, keyB); push = (...values: Array) => this._methods.push(...values); pop = () => this._methods.pop(); shift = () => this._methods.shift(); diff --git a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js index 4a37d8fb..37db1ed7 100644 --- a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeIndexedSetMethods-test.js @@ -17,6 +17,14 @@ test('ParcelShapes insertBefore(key, value) should work', () => { expect(staticParcel.insertBefore(0, 3).data.value).toEqual([3,0,1,2]); }); +test('ParcelShapes move() should work', () => { + let staticParcel = ParcelShape.fromData({ + value: [0,1,2] + }); + + expect(staticParcel.move(2,0).data.value).toEqual([2,0,1]); +}); + test('ParcelShapes push(value) should work', () => { let staticParcel = ParcelShape.fromData({ value: [0,1,2] diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js index b48912b3..e0cf569c 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeIndexedSetMethods.js @@ -5,6 +5,7 @@ import type ParcelShape from '../ParcelShape'; import insertAfter from '../../parcelData/insertAfter'; import insertBefore from '../../parcelData/insertBefore'; +import move from '../../parcelData/move'; import pop from '../../parcelData/pop'; import push from '../../parcelData/push'; import shift from '../../parcelData/shift'; @@ -29,6 +30,13 @@ export default (_this: ParcelShape) => ({ ); }, + move: (keyA: Key|Index, keyB: Key|Index): ParcelShape => { + _this._prepareChildKeys(); + return _this._pipeSelf( + move(keyA, keyB) + ); + }, + pop: (): ParcelShape => { _this._prepareChildKeys(); return _this._pipeSelf( From a0e0933f4b749064b6c07f0e6b9a7bab5eafc337 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 16 Jan 2019 01:14:07 +1100 Subject: [PATCH 070/120] docs: add move() to docs --- packages/dataparcels-docs/src/docs/api/parcel/move.md | 4 ++++ packages/dataparcels-docs/src/docs/api/parcelShape/move.md | 4 ++++ packages/dataparcels-docs/src/pages/api/Parcel.jsx | 3 +++ packages/dataparcels-docs/src/pages/api/ParcelShape.jsx | 3 +++ 4 files changed, 14 insertions(+) create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/move.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/move.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/move.md b/packages/dataparcels-docs/src/docs/api/parcel/move.md new file mode 100644 index 00000000..9ba86475 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/move.md @@ -0,0 +1,4 @@ +```flow +move(key: string|number): void // only on ElementParcels, will move with sibling +move(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will move children +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/move.md b/packages/dataparcels-docs/src/docs/api/parcelShape/move.md new file mode 100644 index 00000000..9ba86475 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/move.md @@ -0,0 +1,4 @@ +```flow +move(key: string|number): void // only on ElementParcels, will move with sibling +move(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will move children +``` diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 443a9c54..24e14d8d 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -33,6 +33,7 @@ import Markdown_delete from 'docs/api/parcel/delete.md'; import Markdown_deleteIn from 'docs/api/parcel/deleteIn.md'; import Markdown_insertAfter from 'docs/api/parcel/insertAfter.md'; import Markdown_insertBefore from 'docs/api/parcel/insertBefore.md'; +import Markdown_move from 'docs/api/parcel/move.md'; import Markdown_pop from 'docs/api/parcel/pop.md'; import Markdown_push from 'docs/api/parcel/push.md'; import Markdown_shift from 'docs/api/parcel/shift.md'; @@ -95,6 +96,7 @@ const md = { deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, insertBefore: Markdown_insertBefore, + move: Markdown_move, pop: Markdown_pop, push: Markdown_push, shift: Markdown_shift, @@ -165,6 +167,7 @@ updateShapeIn() # Indexed & element change methods insertAfter() insertBefore() +move() push() pop() shift() diff --git a/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx b/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx index 2e0c70fd..093a92dc 100644 --- a/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx +++ b/packages/dataparcels-docs/src/pages/api/ParcelShape.jsx @@ -24,6 +24,7 @@ import Markdown_delete from 'docs/api/parcelShape/delete.md'; import Markdown_deleteIn from 'docs/api/parcelShape/deleteIn.md'; import Markdown_insertAfter from 'docs/api/parcelShape/insertAfter.md'; import Markdown_insertBefore from 'docs/api/parcelShape/insertBefore.md'; +import Markdown_move from 'docs/api/parcelShape/move.md'; import Markdown_pop from 'docs/api/parcelShape/pop.md'; import Markdown_push from 'docs/api/parcelShape/push.md'; import Markdown_shift from 'docs/api/parcelShape/shift.md'; @@ -62,6 +63,7 @@ const md = { deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, insertBefore: Markdown_insertBefore, + move: Markdown_move, pop: Markdown_pop, push: Markdown_push, shift: Markdown_shift, @@ -107,6 +109,7 @@ updateShapeIn() # Indexed & element change methods insertAfter() insertBefore() +move() push() pop() shift() From 222ad0a9ea8453abc61dbe1118057f3a278f7533 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 16 Jan 2019 01:17:24 +1100 Subject: [PATCH 071/120] docs: add react-sortable-hoc example --- packages/dataparcels-docs/package.json | 1 + .../src/examples/EditingArraysSortableHoc.jsx | 48 +++++++++++++++ .../dataparcels-docs/src/layouts/index.scss | 45 +++++++++++++- .../src/pages/examples/editing-arrays.md | 59 ++++++++++++++++++- yarn.lock | 18 ++++++ 5 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx diff --git a/packages/dataparcels-docs/package.json b/packages/dataparcels-docs/package.json index 90d2640a..970a39e4 100644 --- a/packages/dataparcels-docs/package.json +++ b/packages/dataparcels-docs/package.json @@ -31,6 +31,7 @@ "react-flip-move": "^3.0.2", "react-helmet": "^5.2.0", "react-lifecycles-compat": "^3.0.4", + "react-sortable-hoc": "^1.4.0", "stampy": "^0.41.0", "unmutable": "^0.29.2" } diff --git a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx new file mode 100644 index 00000000..510e33cc --- /dev/null +++ b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx @@ -0,0 +1,48 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import {SortableContainer, SortableElement} from 'react-sortable-hoc'; +import ExampleHoc from 'component/ExampleHoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const SortableFruitItem = SortableElement(({fruitParcel}) => { + return + {(parcel) =>
+ + + +
} +
; +}); + +const SortableFruitList = SortableContainer(({fruitListParcel}) => { + return
+ {fruitListParcel.toArray((fruitParcel, index) => { + return ; + })} +
; +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ fruitListParcel.move(oldIndex, newIndex)} + /> + +
; +}; + +export default FruitListParcelHoc(ExampleHoc(FruitListEditor)); diff --git a/packages/dataparcels-docs/src/layouts/index.scss b/packages/dataparcels-docs/src/layouts/index.scss index 9a8b98c7..907824f4 100644 --- a/packages/dataparcels-docs/src/layouts/index.scss +++ b/packages/dataparcels-docs/src/layouts/index.scss @@ -6,6 +6,23 @@ @include DcmeBase; @include DcmeBox { + &-draggable { + cursor: move; + padding-left: 1rem; + position: relative; + + &:after { + color: grey(70); + content: '.. .. .. ..'; + display: block; + font-size: 1.2rem; + left: 0; + line-height: 5px; + position: absolute; + top: 0; + width: 1rem; + } + } &-example { margin-left: -2rem; margin-right: -2rem; @@ -63,5 +80,31 @@ -12px 12px 0px lighten(color('primary'), 30) } } -@include DcmeTypography; +@include DcmeTypography { + input { + background: #FFF; + } +} @include DcmeWrapper; + +// .DragHandle { +// content: '....'; +// width: 10px; +// height: 20px; +// display: inline-block; +// overflow: hidden; +// line-height: 5px; +// padding: 3px 4px; +// cursor: move; +// vertical-align: middle; +// margin-top: -.7em; +// margin-right: .3em; +// font-size: 12px; +// font-family: sans-serif; +// letter-spacing: 2px; +// color: #cccccc; +// text-shadow: 1px 0 1px black; +// } +// .DragHandle::after { +// content: '.. .. .. ..'; +// } diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index c56d16aa..f6ce776d 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -1,6 +1,7 @@ import Link from 'gatsby-link'; import EditingArrays from 'examples/EditingArrays'; import EditingArraysFlipMove from 'examples/EditingArraysFlipMove'; +import EditingArraysSortableHoc from 'examples/EditingArraysSortableHoc'; Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. @@ -50,9 +51,65 @@ export default FruitListParcelHoc(FruitListEditor); For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. +## With react-sortable-hoc + +Dataparcels' `move()` method plays nicely with [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). + + + +```js +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import {SortableContainer, SortableElement} from 'react-sortable-hoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const SortableFruitItem = SortableElement(({fruitParcel}) => { + return + {(parcel) =>
+ + + +
} +
; +}); + +const SortableFruitList = SortableContainer(({fruitListParcel}) => { + return
+ {fruitListParcel.toArray((fruitParcel, index) => { + return ; + })} +
; +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ fruitListParcel.move(oldIndex, newIndex)} + /> + +
; +}; + +export default FruitListParcelHoc(FruitListEditor); +``` + ## With react-flip-move -Dataparcels automatic keying plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move). +Dataparcels' automatic keying also plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move). diff --git a/yarn.lock b/yarn.lock index 0534f183..7c2cbccb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -96,6 +96,12 @@ esutils "^2.0.2" js-tokens "^3.0.0" +"@babel/runtime@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.2.0.tgz#b03e42eeddf5898e00646e4c840fa07ba8dcad7f" + dependencies: + regenerator-runtime "^0.12.0" + "@babel/template@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" @@ -11184,6 +11190,14 @@ react-side-effect@^1.1.0: exenv "^1.2.1" shallowequal "^1.0.1" +react-sortable-hoc@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-1.4.0.tgz#b477ce700ba755754200a1dabd36e588e2f5608d" + dependencies: + "@babel/runtime" "^7.2.0" + invariant "^2.2.4" + prop-types "^15.5.7" + react-spruce@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/react-spruce/-/react-spruce-0.1.0.tgz#e1b048e5e5c445b867215be2c48fff034a38f667" @@ -11427,6 +11441,10 @@ regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" From 8840af8955fa04468f3bc1e8fa02363af7d7d62b Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 16 Jan 2019 08:48:15 +1100 Subject: [PATCH 072/120] docs: update editing arrays text --- .../dataparcels-docs/src/pages/examples/editing-arrays.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index f6ce776d..8cf26eeb 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -51,9 +51,9 @@ export default FruitListParcelHoc(FruitListEditor); For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. -## With react-sortable-hoc +## Drag and drop with react-sortable-hoc -Dataparcels' `move()` method plays nicely with [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). +Dataparcels' plays nicely with [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. @@ -107,9 +107,9 @@ const FruitListEditor = (props) => { export default FruitListParcelHoc(FruitListEditor); ``` -## With react-flip-move +## Animations with react-flip-move -Dataparcels' automatic keying also plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move). +Dataparcels' also plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move) because of its automatic keying. Add, remove and move items to see. From d0be342ed5ca77b4cfc82085e6d201defddfb497 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 22 Jan 2019 13:43:41 +1100 Subject: [PATCH 073/120] add: ShapeUpdaterUndefinedError error and ParcelShape._updateFromDataUnlessUndefined --- packages/dataparcels/src/errors/Errors.js | 1 + .../dataparcels/src/parcelShape/ParcelShape.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index c9055bf1..a25b29b0 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -5,3 +5,4 @@ export const ReducerInvalidActionError = (actionType: string) => new Error(`"${a export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); export const ShapeUpdaterNonShapeChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a ParcelShape`); +export const ShapeUpdaterUndefinedError = () => new Error(`ShapeUpdaterUndefinedError`); diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 2f7e5a90..2ee47d1d 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -10,6 +10,7 @@ import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; +import {ShapeUpdaterUndefinedError} from '../errors/Errors'; import ParcelTypes from '../parcel/ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; @@ -78,6 +79,21 @@ export default class ParcelShape { .data; } + static _updateFromDataUnlessUndefined(updater: ParcelShapeUpdater): Function { + return (parcelData: ParcelData): ParcelData => { + let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); + + let updated: any = updater(parcelShape); + if(updated === undefined) { + throw ShapeUpdaterUndefinedError(); + } + + return parcelShape + .updateShape(() => updated) + .data; + }; + } + // only need this to reference static methods on ParcelShape // without creating circular dependencies _instanceUpdateFromData = ParcelShape._updateFromData; From 94f923954d311911d56490b7881c7f769043bd10 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 22 Jan 2019 13:44:24 +1100 Subject: [PATCH 074/120] add: ability for modifyShapeUp to halt change propagation if undefined is returned --- .../dataparcels/src/parcel/methods/ModifyMethods.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index b6eb5311..4445d7a3 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -8,6 +8,7 @@ import type {ParcelShapeUpdater} from '../../types/Types'; import Types from '../../types/Types'; import ParcelShape from '../../parcelShape/ParcelShape'; import ValidateValueUpdater from '../../util/ValidateValueUpdater'; +import {ShapeUpdaterUndefinedError} from '../../errors/Errors'; import ParcelTypes from '../ParcelTypes'; import HashString from '../../util/HashString'; @@ -90,12 +91,20 @@ export default (_this: Parcel): Object => ({ modifyShapeUp: (updater: ParcelShapeUpdater): Parcel => { Types(`modifyShapeUp()`, `updater`, `function`)(updater); - let shapeUpdater = ParcelShape._updateFromData(updater); + let shapeUpdater = ParcelShape._updateFromDataUnlessUndefined(updater); return _this._create({ id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPost(shapeUpdater)); + let changeRequestWithBase = changeRequest._setBaseParcel(_this); + try { + shapeUpdater(changeRequestWithBase.nextData); + _this.dispatch(changeRequest._addPost(shapeUpdater)); + } catch(e) { + if(e.message !== ShapeUpdaterUndefinedError().message) { + throw e; + } + } } }); }, From 9ff4a30ae7c4134c14403e33c01e9a5ee5ebf7a1 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 22 Jan 2019 13:45:01 +1100 Subject: [PATCH 075/120] test: improve parcel shape updater tests, and test modifyShapeUp undefined --- .../src/parcel/__test__/ModifyMethods-test.js | 150 ++++++++++++++++-- .../__test__/ParcelChangeMethods-test.js | 26 +++ 2 files changed, 160 insertions(+), 16 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index d903e8e3..5ad2684f 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -37,6 +37,16 @@ test('Parcel.modifyDown() should allow non-parent types to be returned', () => { expect(updatedValue).toEqual(124); }); +test('Parcel.modifyDown() should allow undefined to be returned (unlike modifyShapeUp)', () => { + let updatedValue = new Parcel({ + value: 123 + }) + .modifyDown(() => {}) + .value; + + expect(updatedValue).toEqual(undefined); +}); + test('Parcel.modifyDown() should validate value updater', () => { TestValidateValueUpdater( expect, @@ -126,6 +136,17 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc expect(handleChange.mock.calls[0][0].value).toBe(457); }); +test('Parcel.modifyUp() should allow you to change the payload of a changed parcel to undefined (unlike modifyShapeUp)', () => { + var handleChange = jest.fn(); + new Parcel({ + value: 123, + handleChange + }) + .modifyUp(() => {}) + .onChange(456); + + expect(handleChange.mock.calls[0][0].value).toBe(undefined); +}); test('Parcel.modifyUp() should validate value updater', () => { TestValidateValueUpdater( @@ -166,15 +187,13 @@ test('Parcel.modifyShapeDown() should be called with parcelShape and return with value: [1,2,3] }); - let {value} = parcel - .modifyShapeDown(updater) - .data; - - let expectedValue = [1,2,3]; + let modifiedParcel = parcel.modifyShapeDown(updater); + modifiedParcel.push(4); - expect(value).toEqual(expectedValue); + expect(modifiedParcel.value).toEqual([1,2,3]); expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); - expect(updater.mock.calls[0][0].data.value).toEqual(expectedValue); + expect(updater.mock.calls[0][0].data.value).toEqual([1,2,3]); + expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); test('Parcel.modifyShapeDown() should modify value', () => { @@ -187,12 +206,67 @@ test('Parcel.modifyShapeDown() should modify value', () => { value: [1,2,3] }); - let parcelWithModifier = parcel.modifyShapeDown(updater); - let {value} = parcelWithModifier.data; - parcelWithModifier.push(5); + let modifiedParcel = parcel.modifyShapeDown(updater); + modifiedParcel.push(5); - expect(value).toEqual([1,2,3,4]); + expect(modifiedParcel.value).toEqual([1,2,3,4]); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); + +}); + +test('Parcel.modifyShapeDown() should work with a returned primitive', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => "!!!"); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let modifiedParcel = parcel.modifyShapeDown(updater); + modifiedParcel.set(456) + + expect(modifiedParcel.value).toEqual("!!!"); + expect(handleChange.mock.calls[0][0].data.value).toEqual(456); +}); + +test('Parcel.modifyShapeDown() should work with a returned undefined (unlike modifyShapeUp)', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => {}); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let modifiedParcel = parcel.modifyShapeDown(updater); + modifiedParcel.set(456) + + let expectedValue = undefined; + + expect(modifiedParcel.value).toEqual(expectedValue); + expect(handleChange.mock.calls[0][0].data.value).toEqual(456); +}); + +test('Parcel.modifyShapeDown() should work with a returned collection containing parcels for children', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(parcelShape => parcelShape.children().reverse()); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let modifiedParcel = parcel.modifyShapeDown(updater); + modifiedParcel.push(4); + + let expectedValue = [3,2,1]; + + expect(modifiedParcel.value).toEqual(expectedValue); + expect(handleChange.mock.calls[0][0].data.value).toEqual([3,2,1,4]); }); test('Parcel.modifyShapeUp() should be called with parcelShape and return with no change', () => { @@ -215,6 +289,7 @@ test('Parcel.modifyShapeUp() should be called with parcelShape and return with n expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(updater.mock.calls[0][0].data.value).toEqual(456); + expect(handleChange.mock.calls[0][0].data.value).toEqual(456); }); test('Parcel.modifyShapeUp() should modify value', () => { @@ -228,17 +303,60 @@ test('Parcel.modifyShapeUp() should modify value', () => { }); let parcelWithModifier = parcel.modifyShapeUp(updater); - let {value} = parcelWithModifier.data; + parcelWithModifier.push(4); - expect(value).toEqual([1,2,3]); - expect(updater).not.toHaveBeenCalled(); + expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); +}); + +test('Parcel.modifyShapeUp() should work with a returned primitive', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => 123); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + let parcelWithModifier = parcel.modifyShapeUp(updater); parcelWithModifier.push(4); - expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); - expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); + expect(handleChange.mock.calls[0][0].data.value).toEqual(123); +}); + +test('Parcel.modifyShapeUp() should work with a returned collection containing parcels for children', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(parcelShape => parcelShape.children().reverse()); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyShapeUp(updater); + parcelWithModifier.push(4); + + expect(handleChange.mock.calls[0][0].data.value).toEqual([4,3,2,1]); +}); + +test('Parcel.modifyShapeUp() should STOP propagating a change if undefined is returned', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => {}); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyShapeUp(updater); + parcelWithModifier.push(4); + + expect(handleChange).not.toHaveBeenCalled(); }); + test('Parcel.initialMeta() should work', () => { let handleChange = jest.fn(); diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 58a49922..4df43bfe 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -105,6 +105,32 @@ test('Parcel.updateShape() should call the Parcels handleChange function with th expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); +test('Parcel.updateShape() should work with a returned primitive', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => 123); + + new Parcel({ + value: [1,2,3], + handleChange + }).updateShape(updater); + + expect(handleChange.mock.calls[0][0].data.value).toEqual(123); +}); + +test('Parcel.updateShape() should work with a returned collection containing parcels for children', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(parcelShape => parcelShape.children().reverse()); + + new Parcel({ + value: [1,2,3], + handleChange + }).updateShape(updater); + + expect(handleChange.mock.calls[0][0].data.value).toEqual([3,2,1]); +}); + test('Parcel.onChange() should work like set that only accepts a single argument', () => { expect.assertions(2); From 54248a26deb2ff5e265df410deeee23863a7400d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:00:29 +1100 Subject: [PATCH 076/120] build: misc project setup improvements --- .flowconfig | 1 + flow-typed/brokenModules.js | 3 +++ package.json | 4 ++-- packages/dataparcels/package.json | 2 +- packages/react-dataparcels/package.json | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 flow-typed/brokenModules.js diff --git a/.flowconfig b/.flowconfig index 52d3b64d..0c3749f9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -12,3 +12,4 @@ module.system.node.resolve_dirname=src /.*/gatsby-node.js /packages/dataparcels-docs/.* /node_modules/react-flip-move/src/.* +/node_modules/immutable/.* diff --git a/flow-typed/brokenModules.js b/flow-typed/brokenModules.js new file mode 100644 index 00000000..e24e7a69 --- /dev/null +++ b/flow-typed/brokenModules.js @@ -0,0 +1,3 @@ +declare module "immutable" { + declare module.exports: any +} diff --git a/package.json b/package.json index 685dab6b..c7926557 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "flow": "blueflag-test flow", "flow-coverage": "blueflag-test flow-coverage -M", "lint": "blueflag-test lint --monorepo", - "test": "yarn jest --maxWorkers=4", - "test-all": "yarn lint && yarn flow && yarn test --maxWorkers=4 && yarn flow-coverage && yarn size-limit", + "test": "yarn build && yarn jest --maxWorkers=1", + "test-all": "yarn build && yarn test --maxWorkers=1 && yarn flow && yarn lint && yarn flow-coverage && yarn size-limit", "deploy-docs": "yarn lerna --scope dataparcels-docs run deploy", "view-coverage": "open ./coverage/lcov-report/index.html", "watch": "lerna run watch --parallel --" diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index 021793c5..6b40436c 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -17,7 +17,7 @@ }, "private": false, "scripts": { - "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore **/*-test.js", + "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore '**/__test__/*.js'", "build-all": "yarn build", "size": "size-limit", "watch": "yarn run build -w" diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index 6777e90d..58115fd8 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -17,7 +17,7 @@ }, "private": false, "scripts": { - "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore **/*-test.js", + "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore '**/__test__/*.js'", "build-all": "yarn build", "watch": "yarn run build -w" }, From 43da4b66b1b285b15b25c711f70b79eb3801d0ed Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:02:46 +1100 Subject: [PATCH 077/120] BREAK: move from named exports to slash exports --- packages/dataparcels/Action.js | 2 + packages/dataparcels/ChangeRequest.js | 2 + packages/dataparcels/DeletedParcelMarker.js | 2 + packages/dataparcels/ParcelShape.js | 2 + packages/dataparcels/__test__/Exports-test.js | 43 +++++++++++++ packages/dataparcels/src/index.js | 6 -- packages/react-dataparcels/Action.js | 2 + packages/react-dataparcels/ChangeRequest.js | 2 + .../react-dataparcels/DeletedParcelMarker.js | 2 + packages/react-dataparcels/ParcelBoundary.js | 2 + .../react-dataparcels/ParcelBoundaryHoc.js | 2 + packages/react-dataparcels/ParcelHoc.js | 2 + packages/react-dataparcels/ParcelShape.js | 2 + .../__test__/Exports-test.js | 63 +++++++++++++++++++ packages/react-dataparcels/src/index.js | 14 ----- 15 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 packages/dataparcels/Action.js create mode 100644 packages/dataparcels/ChangeRequest.js create mode 100644 packages/dataparcels/DeletedParcelMarker.js create mode 100644 packages/dataparcels/ParcelShape.js create mode 100644 packages/dataparcels/__test__/Exports-test.js create mode 100644 packages/react-dataparcels/Action.js create mode 100644 packages/react-dataparcels/ChangeRequest.js create mode 100644 packages/react-dataparcels/DeletedParcelMarker.js create mode 100644 packages/react-dataparcels/ParcelBoundary.js create mode 100644 packages/react-dataparcels/ParcelBoundaryHoc.js create mode 100644 packages/react-dataparcels/ParcelHoc.js create mode 100644 packages/react-dataparcels/ParcelShape.js create mode 100644 packages/react-dataparcels/__test__/Exports-test.js diff --git a/packages/dataparcels/Action.js b/packages/dataparcels/Action.js new file mode 100644 index 00000000..7da07dc3 --- /dev/null +++ b/packages/dataparcels/Action.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/change/Action.js').default; diff --git a/packages/dataparcels/ChangeRequest.js b/packages/dataparcels/ChangeRequest.js new file mode 100644 index 00000000..048aa28c --- /dev/null +++ b/packages/dataparcels/ChangeRequest.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/change/ChangeRequest.js').default; diff --git a/packages/dataparcels/DeletedParcelMarker.js b/packages/dataparcels/DeletedParcelMarker.js new file mode 100644 index 00000000..4bbc19cf --- /dev/null +++ b/packages/dataparcels/DeletedParcelMarker.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/parcelData/DeletedParcelMarker.js').default; diff --git a/packages/dataparcels/ParcelShape.js b/packages/dataparcels/ParcelShape.js new file mode 100644 index 00000000..0e77735e --- /dev/null +++ b/packages/dataparcels/ParcelShape.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/parcelShape/ParcelShape.js').default; diff --git a/packages/dataparcels/__test__/Exports-test.js b/packages/dataparcels/__test__/Exports-test.js new file mode 100644 index 00000000..7fa55ef6 --- /dev/null +++ b/packages/dataparcels/__test__/Exports-test.js @@ -0,0 +1,43 @@ +// @flow + +// exports +import Parcel from '../src/index'; +import Action from '../Action'; +import ChangeRequest from '../ChangeRequest'; +import DeletedParcelMarker from '../DeletedParcelMarker'; +import ParcelShape from '../ParcelShape'; +import shape from '../shape'; + +// internal files +import InternalParcel from '../src/parcel/Parcel'; + +// internal lib files +import InternalAction from '../lib/change/Action'; +import InternalChangeRequest from '../lib/change/ChangeRequest'; +import InternalDeletedParcelMarker from '../lib/parcelData/DeletedParcelMarker'; +import InternalParcelShape from '../lib/parcelShape/ParcelShape'; +import InternalShape from '../lib/parcelShape/shape'; + +test('index should export Parcel', () => { + expect(Parcel).toBe(InternalParcel); +}); + +test('/Action should export Action', () => { + expect(Action).toBe(InternalAction); +}); + +test('/ChangeRequest should export ChangeRequest', () => { + expect(ChangeRequest).toBe(InternalChangeRequest); +}); + +test('/DeletedParcelMarker should export DeletedParcelMarker', () => { + expect(DeletedParcelMarker).toBe(InternalDeletedParcelMarker); +}); + +test('/ParcelShape should export ParcelShape', () => { + expect(ParcelShape).toBe(InternalParcelShape); +}); + +test('/shape should export shape', () => { + expect(shape).toBe(InternalShape); +}); diff --git a/packages/dataparcels/src/index.js b/packages/dataparcels/src/index.js index a816f006..a3f36020 100644 --- a/packages/dataparcels/src/index.js +++ b/packages/dataparcels/src/index.js @@ -2,11 +2,6 @@ import Parcel from './parcel/Parcel'; export default Parcel; -export {default as Action} from './change/Action'; -export {default as ChangeRequest} from './change/ChangeRequest'; -export {default as ParcelShape} from './parcelShape/ParcelShape'; -export {default as DeletedParcelMarker} from './parcelData/DeletedParcelMarker'; - // // types // @@ -17,7 +12,6 @@ export type {ParcelConfigInternal} from './types/Types'; export type {ParcelCreateConfigType} from './types/Types'; export type {ParcelMeta} from './types/Types'; -export type {ParcelBatcher} from './types/Types'; export type {ParcelMapper} from './types/Types'; export type {ParcelUpdater} from './types/Types'; export type {ParcelValueUpdater} from './types/Types'; diff --git a/packages/react-dataparcels/Action.js b/packages/react-dataparcels/Action.js new file mode 100644 index 00000000..9168ca7c --- /dev/null +++ b/packages/react-dataparcels/Action.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/Action.js').default; diff --git a/packages/react-dataparcels/ChangeRequest.js b/packages/react-dataparcels/ChangeRequest.js new file mode 100644 index 00000000..770fab1e --- /dev/null +++ b/packages/react-dataparcels/ChangeRequest.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/ChangeRequest.js').default; diff --git a/packages/react-dataparcels/DeletedParcelMarker.js b/packages/react-dataparcels/DeletedParcelMarker.js new file mode 100644 index 00000000..ac5e7729 --- /dev/null +++ b/packages/react-dataparcels/DeletedParcelMarker.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/DeletedParcelMarker.js').default; diff --git a/packages/react-dataparcels/ParcelBoundary.js b/packages/react-dataparcels/ParcelBoundary.js new file mode 100644 index 00000000..e52d78fa --- /dev/null +++ b/packages/react-dataparcels/ParcelBoundary.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/ParcelBoundary.js').default; diff --git a/packages/react-dataparcels/ParcelBoundaryHoc.js b/packages/react-dataparcels/ParcelBoundaryHoc.js new file mode 100644 index 00000000..88864deb --- /dev/null +++ b/packages/react-dataparcels/ParcelBoundaryHoc.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/ParcelBoundaryHoc.js').default; diff --git a/packages/react-dataparcels/ParcelHoc.js b/packages/react-dataparcels/ParcelHoc.js new file mode 100644 index 00000000..20d5fd79 --- /dev/null +++ b/packages/react-dataparcels/ParcelHoc.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/ParcelHoc.js').default; diff --git a/packages/react-dataparcels/ParcelShape.js b/packages/react-dataparcels/ParcelShape.js new file mode 100644 index 00000000..f51b4791 --- /dev/null +++ b/packages/react-dataparcels/ParcelShape.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/ParcelShape.js').default; diff --git a/packages/react-dataparcels/__test__/Exports-test.js b/packages/react-dataparcels/__test__/Exports-test.js new file mode 100644 index 00000000..edb5864e --- /dev/null +++ b/packages/react-dataparcels/__test__/Exports-test.js @@ -0,0 +1,63 @@ +// @flow + +// dataparcels exports +import Parcel from '../src/index'; +import Action from '../Action'; +import ChangeRequest from '../ChangeRequest'; +import DeletedParcelMarker from '../DeletedParcelMarker'; +import ParcelShape from '../ParcelShape'; +import shape from '../shape'; + +// react-dataparcels +import ParcelHoc from '../ParcelHoc'; +import ParcelBoundary from '../ParcelBoundary'; +import ParcelBoundaryHoc from '../ParcelBoundaryHoc'; + +// internal dataparcels files +import InternalParcel from 'dataparcels'; +import InternalAction from 'dataparcels/Action'; +import InternalChangeRequest from 'dataparcels/ChangeRequest'; +import InternalDeletedParcelMarker from 'dataparcels/DeletedParcelMarker'; +import InternalParcelShape from 'dataparcels/ParcelShape'; +import InternalShape from 'dataparcels/shape'; + +// internal react-dataparcels +import InternalParcelHoc from '../lib/ParcelHoc'; +import InternalParcelBoundary from '../lib/ParcelBoundary'; +import InternalParcelBoundaryHoc from '../lib/ParcelBoundaryHoc'; + +test('index should export Parcel', () => { + expect(Parcel).toBe(InternalParcel); +}); + +// test('/Action should export Action', () => { +// expect(Action).toBe(InternalAction); +// }); + +// test('/ChangeRequest should export ChangeRequest', () => { +// expect(ChangeRequest).toBe(InternalChangeRequest); +// }); + +// test('/DeletedParcelMarker should export DeletedParcelMarker', () => { +// expect(DeletedParcelMarker).toBe(InternalDeletedParcelMarker); +// }); + +// test('/ParcelShape should export ParcelShape', () => { +// expect(ParcelShape).toBe(InternalParcelShape); +// }); + +// test('/shape should export shape', () => { +// expect(shape).toBe(InternalShape); +// }); + +test('/ParcelHoc should export ParcelHoc', () => { + expect(ParcelHoc).toBe(InternalParcelHoc); +}); + +test('/ParcelBoundary should export ParcelBoundary', () => { + expect(ParcelBoundary).toBe(InternalParcelBoundary); +}); + +test('/ParcelBoundaryHoc should export ParcelBoundaryHoc', () => { + expect(ParcelBoundaryHoc).toBe(InternalParcelBoundaryHoc); +}); diff --git a/packages/react-dataparcels/src/index.js b/packages/react-dataparcels/src/index.js index b4e432a3..c1583bf8 100644 --- a/packages/react-dataparcels/src/index.js +++ b/packages/react-dataparcels/src/index.js @@ -7,11 +7,6 @@ import dataparcels from 'dataparcels'; export default dataparcels; -export {Action} from 'dataparcels'; -export {ChangeRequest} from 'dataparcels'; -export {ParcelShape} from 'dataparcels'; -export {DeletedParcelMarker} from 'dataparcels'; - // // dataparcels types // @@ -22,7 +17,6 @@ export type {ParcelConfigInternal} from 'dataparcels'; export type {ParcelCreateConfigType} from 'dataparcels'; export type {ParcelMeta} from 'dataparcels'; -export type {ParcelBatcher} from 'dataparcels'; export type {ParcelMapper} from 'dataparcels'; export type {ParcelUpdater} from 'dataparcels'; export type {ParcelValueUpdater} from 'dataparcels'; @@ -36,11 +30,3 @@ export type {Key} from 'dataparcels'; export type {Index} from 'dataparcels'; export type {Property} from 'dataparcels'; export type {ParentType} from 'dataparcels'; - -// -// react-dataparcels -// - -export {default as ParcelHoc} from './ParcelHoc'; -export {default as ParcelBoundary} from './ParcelBoundary'; -export {default as ParcelBoundaryHoc} from './ParcelBoundaryHoc'; From 14234a356c148ad18a81c2fc3bac10ba5b1686aa Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:12:36 +1100 Subject: [PATCH 078/120] BREAK: split out parcel shape updaters and finalise modify method api --- .size-limit | 6 +- packages/dataparcels/shape.js | 2 + .../src/parcel/__test__/ModifyMethods-test.js | 144 +++++++--------- .../__test__/ParcelChangeMethods-test.js | 28 +--- .../__test__/ParentChangeMethods-test.js | 8 +- .../src/parcel/methods/ModifyMethods.js | 155 +++++------------- .../src/parcel/methods/ParcelChangeMethods.js | 20 +-- .../src/parcel/methods/ParentChangeMethods.js | 18 +- .../src/parcelShape/ParcelShape.js | 56 ++++--- .../methods/ParcelShapeParentSetMethods.js | 2 +- packages/dataparcels/src/parcelShape/shape.js | 3 + packages/react-dataparcels/shape.js | 2 + 12 files changed, 170 insertions(+), 274 deletions(-) create mode 100644 packages/dataparcels/shape.js create mode 100644 packages/dataparcels/src/parcelShape/shape.js create mode 100644 packages/react-dataparcels/shape.js diff --git a/.size-limit b/.size-limit index 254ccea1..7a3bbb2a 100644 --- a/.size-limit +++ b/.size-limit @@ -4,7 +4,11 @@ path: "packages/dataparcels/lib/index.js" }, { - limit: "30 KB", + limit: "25 KB", + path: "packages/dataparcels/ParcelShape.js" + }, + { + limit: "25 KB", path: "packages/react-dataparcels/lib/index.js" } ] diff --git a/packages/dataparcels/shape.js b/packages/dataparcels/shape.js new file mode 100644 index 00000000..29aa9d1d --- /dev/null +++ b/packages/dataparcels/shape.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/parcelShape/shape.js').default; diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 5ad2684f..2d789b54 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -3,6 +3,7 @@ import type ChangeRequest from '../../change/ChangeRequest'; import Parcel from '../Parcel'; import ParcelShape from '../../parcelShape/ParcelShape'; +import shape from '../../parcelShape/shape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; test('Parcel.modifyDown() should return a new parcel with updated parcelData', () => { @@ -37,7 +38,7 @@ test('Parcel.modifyDown() should allow non-parent types to be returned', () => { expect(updatedValue).toEqual(124); }); -test('Parcel.modifyDown() should allow undefined to be returned (unlike modifyShapeUp)', () => { +test('Parcel.modifyDown() should allow undefined to be returned (unlike modifyUp(parcelShapeUpdater))', () => { let updatedValue = new Parcel({ value: 123 }) @@ -69,59 +70,34 @@ test('Parcel.modifyDown() should recognise if value changes types, and set value test('Parcel.modifyDown() should have id which is unique to updater', () => { let updater = value => []; - let parcel = new Parcel().modifyDown(updater); - let parcel2 = new Parcel().modifyDown(updater); - let parcel3 = new Parcel().modifyDown(a => 1 + 2); - - expect(parcel.id).toBe("^.~mv-643198612"); - expect(parcel2.id).toBe("^.~mv-643198612"); // same updater should produce the same hash - expect(parcel3.id).not.toBe("^.~mv-643198612"); // different updater should produce different hash -}); - -test('Parcel.modifyChange() should allow you to change the payload of a changed parcel', () => { - expect.assertions(1); - - var data = { - value: 123, - handleChange: (parcel: Parcel) => { - let {value} = parcel.data; - expect(457).toBe(value); - } - }; - - new Parcel(data) - .modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { - parcel.set(changeRequest.nextData.value + 1); - }) - .onChange(456); + let sameA1 = new Parcel().modifyDown(updater); + let sameA2 = new Parcel().modifyDown(updater); + let differentA = new Parcel().modifyDown(a => 1 + 2); + + let sameB1 = new Parcel().modifyDown(shape(updater)); + let sameB2 = new Parcel().modifyDown(shape(updater)); + let differentB = new Parcel().modifyDown(shape(a => 1 + 2)); + + expect(sameA1.id).toBe(sameA2.id); + expect(sameA1.id).not.toBe(differentA.id); + expect(sameB1.id).toBe(sameB2.id); + expect(sameB1.id).not.toBe(differentB.id); }); -test('Parcel.modifyChange() should allow you to stop a change by not calling dispatch', () => { - var handleChange = jest.fn(); - - var data = { - value: 123, - handleChange - }; - - new Parcel(data) - .modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { - // nothing here - }) - .onChange(456); - - expect(handleChange).toHaveBeenCalledTimes(0); -}); - -test('Parcel.modifyChange() should have id which is unique to updater', () => { +test('Parcel.modifyUp() should have id which is unique to updater', () => { let updater = value => []; - let parcel = new Parcel().modifyChange(updater); - let parcel2 = new Parcel().modifyChange(updater); - let parcel3 = new Parcel().modifyChange(a => "woop"); - - expect(parcel.id).toBe("^.~mcb-643198612"); - expect(parcel2.id).toBe("^.~mcb-643198612"); // same updater should produce the same hash - expect(parcel3.id).not.toBe("^.~mcb-643198612"); // different updater should produce different hash + let sameA1 = new Parcel().modifyUp(updater); + let sameA2 = new Parcel().modifyUp(updater); + let differentA = new Parcel().modifyUp(a => 1 + 2); + + let sameB1 = new Parcel().modifyUp(shape(updater)); + let sameB2 = new Parcel().modifyUp(shape(updater)); + let differentB = new Parcel().modifyUp(shape(a => 1 + 2)); + + expect(sameA1.id).toBe(sameA2.id); + expect(sameA1.id).not.toBe(differentA.id); + expect(sameB1.id).toBe(sameB2.id); + expect(sameB1.id).not.toBe(differentB.id); }); test('Parcel.modifyUp() should allow you to change the payload of a changed parcel with an updater (and should allow non-parent types to be returned)', () => { @@ -136,7 +112,7 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc expect(handleChange.mock.calls[0][0].value).toBe(457); }); -test('Parcel.modifyUp() should allow you to change the payload of a changed parcel to undefined (unlike modifyShapeUp)', () => { +test('Parcel.modifyUp() should allow you to change the payload of a changed parcel to undefined (unlike modifyUp(parcelShapeUpdater))', () => { var handleChange = jest.fn(); new Parcel({ value: 123, @@ -149,9 +125,16 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc }); test('Parcel.modifyUp() should validate value updater', () => { + let handleChange = () => {}; + TestValidateValueUpdater( expect, - (value, updater) => new Parcel({value: undefined}).modifyUp(updater).onChange(value) + (value, updater) => new Parcel({ + value: undefined, + handleChange + }) + .modifyUp(updater) + .onChange(value) ); }); @@ -169,15 +152,15 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { new Parcel(data) .modifyUp(value => value + 1) - .batch(parcel => { - parcel.onChange(456); - parcel.setMeta({ + .update(shape(parcelShape => parcelShape + .set(456) + .setMeta({ abc: 123 - }); - }); + }) + )); }); -test('Parcel.modifyShapeDown() should be called with parcelShape and return with no change', () => { +test('Parcel.modifyDown(parcelShapeUpdater) should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape); @@ -187,7 +170,7 @@ test('Parcel.modifyShapeDown() should be called with parcelShape and return with value: [1,2,3] }); - let modifiedParcel = parcel.modifyShapeDown(updater); + let modifiedParcel = parcel.modifyDown(shape(updater)); modifiedParcel.push(4); expect(modifiedParcel.value).toEqual([1,2,3]); @@ -196,7 +179,7 @@ test('Parcel.modifyShapeDown() should be called with parcelShape and return with expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); -test('Parcel.modifyShapeDown() should modify value', () => { +test('Parcel.modifyDown(parcelShapeUpdater) should modify value', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.push(4)); @@ -206,7 +189,7 @@ test('Parcel.modifyShapeDown() should modify value', () => { value: [1,2,3] }); - let modifiedParcel = parcel.modifyShapeDown(updater); + let modifiedParcel = parcel.modifyDown(shape(updater)); modifiedParcel.push(5); expect(modifiedParcel.value).toEqual([1,2,3,4]); @@ -214,7 +197,7 @@ test('Parcel.modifyShapeDown() should modify value', () => { }); -test('Parcel.modifyShapeDown() should work with a returned primitive', () => { +test('Parcel.modifyDown(parcelShapeUpdater) should work with a returned primitive', () => { let handleChange = jest.fn(); let updater = jest.fn(() => "!!!"); @@ -224,14 +207,14 @@ test('Parcel.modifyShapeDown() should work with a returned primitive', () => { value: [1,2,3] }); - let modifiedParcel = parcel.modifyShapeDown(updater); + let modifiedParcel = parcel.modifyDown(shape(updater)); modifiedParcel.set(456) expect(modifiedParcel.value).toEqual("!!!"); expect(handleChange.mock.calls[0][0].data.value).toEqual(456); }); -test('Parcel.modifyShapeDown() should work with a returned undefined (unlike modifyShapeUp)', () => { +test('Parcel.modifyDown(parcelShapeUpdater) should work with a returned undefined (unlike modifyUp(parcelShapeUpdater))', () => { let handleChange = jest.fn(); let updater = jest.fn(() => {}); @@ -241,7 +224,7 @@ test('Parcel.modifyShapeDown() should work with a returned undefined (unlike mod value: [1,2,3] }); - let modifiedParcel = parcel.modifyShapeDown(updater); + let modifiedParcel = parcel.modifyDown(shape(updater)); modifiedParcel.set(456) let expectedValue = undefined; @@ -250,7 +233,7 @@ test('Parcel.modifyShapeDown() should work with a returned undefined (unlike mod expect(handleChange.mock.calls[0][0].data.value).toEqual(456); }); -test('Parcel.modifyShapeDown() should work with a returned collection containing parcels for children', () => { +test('Parcel.modifyDown(parcelShapeUpdater) should work with a returned collection containing parcels for children', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.children().reverse()); @@ -260,7 +243,7 @@ test('Parcel.modifyShapeDown() should work with a returned collection containing value: [1,2,3] }); - let modifiedParcel = parcel.modifyShapeDown(updater); + let modifiedParcel = parcel.modifyDown(shape(updater)); modifiedParcel.push(4); let expectedValue = [3,2,1]; @@ -269,7 +252,7 @@ test('Parcel.modifyShapeDown() should work with a returned collection containing expect(handleChange.mock.calls[0][0].data.value).toEqual([3,2,1,4]); }); -test('Parcel.modifyShapeUp() should be called with parcelShape and return with no change', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape); @@ -279,7 +262,7 @@ test('Parcel.modifyShapeUp() should be called with parcelShape and return with n value: 123 }); - let parcelWithModifier = parcel.modifyShapeUp(updater); + let parcelWithModifier = parcel.modifyUp(shape(updater)); let {value} = parcelWithModifier.data; expect(value).toEqual(123); @@ -292,7 +275,7 @@ test('Parcel.modifyShapeUp() should be called with parcelShape and return with n expect(handleChange.mock.calls[0][0].data.value).toEqual(456); }); -test('Parcel.modifyShapeUp() should modify value', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should modify value', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.push(5)); @@ -302,13 +285,13 @@ test('Parcel.modifyShapeUp() should modify value', () => { value: [1,2,3] }); - let parcelWithModifier = parcel.modifyShapeUp(updater); + let parcelWithModifier = parcel.modifyUp(shape(updater)); parcelWithModifier.push(4); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4,5]); }); -test('Parcel.modifyShapeUp() should work with a returned primitive', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should work with a returned primitive', () => { let handleChange = jest.fn(); let updater = jest.fn(() => 123); @@ -318,13 +301,13 @@ test('Parcel.modifyShapeUp() should work with a returned primitive', () => { value: [1,2,3] }); - let parcelWithModifier = parcel.modifyShapeUp(updater); + let parcelWithModifier = parcel.modifyUp(shape(updater)); parcelWithModifier.push(4); expect(handleChange.mock.calls[0][0].data.value).toEqual(123); }); -test('Parcel.modifyShapeUp() should work with a returned collection containing parcels for children', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should work with a returned collection containing parcels for children', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.children().reverse()); @@ -334,13 +317,13 @@ test('Parcel.modifyShapeUp() should work with a returned collection containing p value: [1,2,3] }); - let parcelWithModifier = parcel.modifyShapeUp(updater); + let parcelWithModifier = parcel.modifyUp(shape(updater)); parcelWithModifier.push(4); expect(handleChange.mock.calls[0][0].data.value).toEqual([4,3,2,1]); }); -test('Parcel.modifyShapeUp() should STOP propagating a change if undefined is returned', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if undefined is returned', () => { let handleChange = jest.fn(); let updater = jest.fn(() => {}); @@ -350,13 +333,12 @@ test('Parcel.modifyShapeUp() should STOP propagating a change if undefined is re value: [1,2,3] }); - let parcelWithModifier = parcel.modifyShapeUp(updater); + let parcelWithModifier = parcel.modifyUp(shape(updater)); parcelWithModifier.push(4); expect(handleChange).not.toHaveBeenCalled(); }); - test('Parcel.initialMeta() should work', () => { let handleChange = jest.fn(); @@ -444,8 +426,8 @@ test('Sanity check: A big strange test of a big strange chain of deep updatery s handleChange, value: [1,2,3] }) - .modifyShapeDown(parcelShape => parcelShape.children().reverse()) // 1. reverse the elements in the parcel (value: [3,2,1]) - .modifyShapeUp(parcelShape => parcelShape.children().reverse()) // 6. reverse the elements in the parcel (value: [3333,2,1]) + .modifyDown(shape(parcelShape => parcelShape.children().reverse())) // 1. reverse the elements in the parcel (value: [3,2,1]) + .modifyUp(shape(parcelShape => parcelShape.children().reverse())) // 6. reverse the elements in the parcel (value: [3333,2,1]) .get(0) // 2. get the first element (value: 3) .modifyDown(value => value + "") // 3. cast number to string value: "3") .modifyUp(value => parseInt(value, 10)) // 5. cast string to number (value will be: 3333) diff --git a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js index 4df43bfe..2de367d0 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelChangeMethods-test.js @@ -91,7 +91,7 @@ test('Parcel.update() should validate value updater', () => { ); }); -test('Parcel.updateShape() should call the Parcels handleChange function with the new parcelData', () => { +test('Parcel.update(parcelShape) should call the Parcels handleChange function with the new parcelData', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.push(4)); @@ -99,13 +99,13 @@ test('Parcel.updateShape() should call the Parcels handleChange function with th new Parcel({ value: [1,2,3], handleChange - }).updateShape(updater); + }).update(ParcelShape.update(updater)); expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual([1,2,3,4]); }); -test('Parcel.updateShape() should work with a returned primitive', () => { +test('Parcel.update(parcelShape) should work with a returned primitive', () => { let handleChange = jest.fn(); let updater = jest.fn(() => 123); @@ -113,12 +113,12 @@ test('Parcel.updateShape() should work with a returned primitive', () => { new Parcel({ value: [1,2,3], handleChange - }).updateShape(updater); + }).update(ParcelShape.update(updater)); expect(handleChange.mock.calls[0][0].data.value).toEqual(123); }); -test('Parcel.updateShape() should work with a returned collection containing parcels for children', () => { +test('Parcel.update(parcelShape) should work with a returned collection containing parcels for children', () => { let handleChange = jest.fn(); let updater = jest.fn(parcelShape => parcelShape.children().reverse()); @@ -126,7 +126,7 @@ test('Parcel.updateShape() should work with a returned collection containing par new Parcel({ value: [1,2,3], handleChange - }).updateShape(updater); + }).update(ParcelShape.update(updater)); expect(handleChange.mock.calls[0][0].data.value).toEqual([3,2,1]); }); @@ -245,19 +245,3 @@ test('Parcel.setMeta() should call the Parcels handleChange function with the ne abc: 123 }); }); - -test('Parcel.setChangeRequestMeta() should set change request meta', () => { - var data = { - value: 123, - handleChange: (parcel, changeRequest) => { - expect({a: 3, b: 2}).toEqual(changeRequest.changeRequestMeta); - } - }; - - var parcel = new Parcel(data).batch(parcel => { - parcel.setChangeRequestMeta({a: 1}); - parcel.onChange(456); - parcel.setChangeRequestMeta({b: 2}); - parcel.setChangeRequestMeta({a: 3}); - }); -}); diff --git a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js index 459b121e..b4ecf8da 100644 --- a/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParentChangeMethods-test.js @@ -36,7 +36,7 @@ test('ParentParcel.update(key) should call the Parcels handleChange function wit }); }); -test('ParentParcel.updateShape(key) should call the Parcels handleChange function with the new parcelData', () => { +test('ParentParcel.update(key, parcelShapeUpdater) should call the Parcels handleChange function with the new parcelData', () => { let updater = jest.fn(parcelShape => parcelShape.push(4)); let handleChange = jest.fn(); @@ -45,7 +45,7 @@ test('ParentParcel.updateShape(key) should call the Parcels handleChange functio abc: [1,2,3] }, handleChange - }).updateShape("abc", updater); + }).update("abc", ParcelShape.update(updater)); expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ @@ -110,7 +110,7 @@ test('ParentParcel.updateIn(keyPath) should call the Parcels handleChange functi }); }); -test('ParentParcel.updateShapeIn(keyPath) should call the Parcels handleChange function with the new parcelData', () => { +test('ParentParcel.updateIn(keyPath, parcelShapeUpdater) should call the Parcels handleChange function with the new parcelData', () => { let updater = jest.fn(parcelShape => parcelShape.push(4)); let handleChange = jest.fn(); @@ -121,7 +121,7 @@ test('ParentParcel.updateShapeIn(keyPath) should call the Parcels handleChange f } }, handleChange - }).updateShapeIn(["abc", "def"], updater); + }).updateIn(["abc", "def"], ParcelShape.update(updater)); expect(updater.mock.calls[0][0] instanceof ParcelShape).toBe(true); expect(handleChange.mock.calls[0][0].data.value).toEqual({ diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index 4445d7a3..ac05ace4 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -1,123 +1,76 @@ // @flow import type ChangeRequest from '../../change/ChangeRequest'; import type Parcel from '../Parcel'; +import type {ParcelData} from '../../types/Types'; +import type {ParcelDataEvaluator} from '../../types/Types'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdateFunction} from '../../types/Types'; import Types from '../../types/Types'; -import ParcelShape from '../../parcelShape/ParcelShape'; +import setSelf from '../../parcelData/setSelf'; +import setMetaDefault from '../../parcelData/setMetaDefault'; import ValidateValueUpdater from '../../util/ValidateValueUpdater'; -import {ShapeUpdaterUndefinedError} from '../../errors/Errors'; -import ParcelTypes from '../ParcelTypes'; import HashString from '../../util/HashString'; import filterNot from 'unmutable/lib/filterNot'; import has from 'unmutable/lib/has'; -import isEmpty from 'unmutable/lib/isEmpty'; -import merge from 'unmutable/lib/merge'; -import update from 'unmutable/lib/update'; import pipeWith from 'unmutable/lib/util/pipeWith'; let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; export default (_this: Parcel): Object => ({ - modifyDown: (updater: ParcelValueUpdater): Parcel => { - Types(`modifyDown()`, `updater`, `function`)(updater); - - let {value} = _this._parcelData; - let updatedValue = updater(value, _this); - ValidateValueUpdater(value, updatedValue); - - let updatedType = new ParcelTypes(updatedValue); - let updatedTypeChanged: boolean = updatedType.isParent() !== _this._parcelTypes.isParent() - || updatedType.isIndexed() !== _this._parcelTypes.isIndexed(); - - let onDispatch; - if(updatedTypeChanged) { - onDispatch = (changeRequest: ChangeRequest) => { - _this.batch( - (parcel: Parcel) => { - parcel.set(updatedValue); - parcel.dispatch(changeRequest); - }, - changeRequest - ); - }; - } + _pushModifierId: (prefix: string, updater: Function): string => { + let id = updater._isParcelUpdater + ? `s${HashFunction(updater._updater)}` + : HashFunction(updater); - return _this._create({ - id: _this._id.pushModifier(`mv-${HashFunction(updater)}`), - parcelData: { - ..._this._parcelData, - value: updatedValue - }, - onDispatch - }); + return _this._id.pushModifier(`${prefix}-${id}`); }, - modifyUp: (updater: ParcelValueUpdater): Parcel => { - Types(`modifyUp()`, `updater`, `function`)(updater); - return _this.modifyChange((parcel: Parcel, changeRequest: ChangeRequest) => { - - let {value} = changeRequest.nextData; - let updatedValue = updater(value, _this); - ValidateValueUpdater(value, updatedValue); - - // dispatch all non-value actions in this change request - let valueActionFilter = actions => actions.filter(action => !action.isValueAction()); - parcel.dispatch(changeRequest.updateActions(valueActionFilter)); - - parcel.set(updatedValue); - }); + _getModifierUpdater: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction, errorOnUndefined: ?boolean = false): ParcelDataEvaluator => { + // $FlowFixMe - flow just cant make the connection between updater._isParcelUpdater and the choice between ParcelValueUpdater or ParcelShapeUpdateFunction + return updater._isParcelUpdater + // $FlowFixMe - this branch should only be hit with ParcelShapeUpdateFunction + ? (parcelData: ParcelData): ParcelData => updater(parcelData, errorOnUndefined) + : (parcelData: ParcelData): ParcelData => { + let {value} = parcelData; + let updatedValue = updater(value, _this); + ValidateValueUpdater(value, updatedValue); + return setSelf(updatedValue)(parcelData); + }; }, - modifyShapeDown: (updater: ParcelShapeUpdater): Parcel => { - Types(`modifyShapeDown()`, `updater`, `function`)(updater); - - let shapeUpdater = ParcelShape._updateFromData(updater); - + _boundarySplit: ({handleChange}: *): Parcel => { return _this._create({ - id: _this._id.pushModifier(`md-${HashFunction(updater)}`), - parcelData: shapeUpdater(_this._parcelData), - onDispatch: (changeRequest: ChangeRequest) => { - _this.dispatch(changeRequest._addPre(shapeUpdater)); - } + id: _this._id.pushModifier('bs'), + parent: _this._parent, + handleChange, + treeshare: _this._treeshare.boundarySplit() }); }, - modifyShapeUp: (updater: ParcelShapeUpdater): Parcel => { - Types(`modifyShapeUp()`, `updater`, `function`)(updater); - - let shapeUpdater = ParcelShape._updateFromDataUnlessUndefined(updater); - + modifyDown: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => { + Types(`modifyDown()`, `updater`, `function`)(updater); + let parcelDataUpdater: ParcelDataEvaluator = _this._methods._getModifierUpdater(updater); return _this._create({ - id: _this._id.pushModifier(`mu-${HashFunction(updater)}`), + id: _this._methods._pushModifierId('md', updater), + parcelData: parcelDataUpdater(_this._parcelData), onDispatch: (changeRequest: ChangeRequest) => { - let changeRequestWithBase = changeRequest._setBaseParcel(_this); - try { - shapeUpdater(changeRequestWithBase.nextData); - _this.dispatch(changeRequest._addPost(shapeUpdater)); - } catch(e) { - if(e.message !== ShapeUpdaterUndefinedError().message) { - throw e; - } - } + _this.dispatch(changeRequest._addPre(parcelDataUpdater)); } }); }, - modifyChange: (batcher: Function): Parcel => { - Types(`modifyChange()`, `batcher`, `function`)(batcher); + modifyUp: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => { + Types(`modifyUp()`, `updater`, `function`)(updater); + let parcelDataUpdater: ParcelDataEvaluator = _this._methods._getModifierUpdater(updater, true); return _this._create({ - id: _this._id.pushModifier(`mcb-${HashFunction(batcher)}`), + id: _this._methods._pushModifierId('mu', updater), onDispatch: (changeRequest: ChangeRequest) => { - _this.batch( - (parcel: Parcel) => batcher(parcel, changeRequest._setBaseParcel(parcel)), - changeRequest - ); + _this.dispatch(changeRequest._addPost(parcelDataUpdater)); } }); }, @@ -126,40 +79,18 @@ export default (_this: Parcel): Object => ({ Types(`initialMeta()`, `initialMeta`, `object`)(initialMeta); let {meta} = _this._parcelData; - let partialMetaToSet: {[key: string]: any} = pipeWith( + let parcelDataUpdater = pipeWith( initialMeta, - filterNot((value, key) => has(key)(meta)) + filterNot((value, key) => has(key)(meta)), + setMetaDefault ); - let create = (other = {}) => _this._create({ + return _this._create({ id: _this._id.pushModifier('im'), - ...other - }); - - if(isEmpty()(partialMetaToSet)) { - return create(); - } - - return create({ - parcelData: pipeWith( - _this._parcelData, - update('meta', merge(partialMetaToSet)) - ), + parcelData: parcelDataUpdater(_this._parcelData), onDispatch: (changeRequest: ChangeRequest) => { - _this.batch((parcel: Parcel) => { - parcel.setMeta(partialMetaToSet); - parcel.dispatch(changeRequest); - }); + _this.dispatch(changeRequest._addPost(parcelDataUpdater)); } }); - }, - - _boundarySplit: ({handleChange}: *): Parcel => { - return _this._create({ - id: _this._id.pushModifier('bs'), - parent: _this._parent, - handleChange, - treeshare: _this._treeshare.boundarySplit() - }); } }); diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index 5a4fa92f..d4aaaff3 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -2,12 +2,10 @@ import type Parcel from '../Parcel'; import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdateFunction} from '../../types/Types'; import Types from '../../types/Types'; -import ChangeRequest from '../../change/ChangeRequest'; import ActionCreators from '../../change/ActionCreators'; -import ParcelShape from '../../parcelShape/ParcelShape'; import ValidateValueUpdater from '../../util/ValidateValueUpdater'; export default (_this: Parcel, dispatch: Function) => ({ @@ -16,21 +14,21 @@ export default (_this: Parcel, dispatch: Function) => ({ dispatch(ActionCreators.setSelf(value)); }, - updateSelf: (updater: ParcelValueUpdater) => { + updateSelf: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction) => { Types(`updateSelf()`, `updater`, `function`)(updater); + if(updater._isParcelUpdater) { + // $FlowFixMe - this branch should only be hit with ParcelShapeUpdateFunction + let updated = updater(_this._parcelData); + dispatch(ActionCreators.setData(updated)); + return; + } + let {value} = _this; let updatedValue = updater(value, _this); ValidateValueUpdater(value, updatedValue); _this.set(updatedValue); }, - updateSelfShape: (updater: ParcelShapeUpdater) => { - Types(`updateSelfShape()`, `updater`, `function`)(updater); - let parcelShapeUpdater = ParcelShape._updateFromData(updater); - let updated = parcelShapeUpdater(_this._parcelData); - dispatch(ActionCreators.setData(updated)); - }, - onChange: _this.set, onChangeDOM: (event: Object) => { diff --git a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js index 92f87161..0cf2276b 100644 --- a/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParentChangeMethods.js @@ -3,7 +3,7 @@ import type {Index} from '../../types/Types'; import type {Key} from '../../types/Types'; import type Parcel from '../Parcel'; import type {ParcelValueUpdater} from '../../types/Types'; -import type {ParcelShapeUpdater} from '../../types/Types'; +import type {ParcelShapeUpdateFunction} from '../../types/Types'; import Types from '../../types/Types'; @@ -28,27 +28,15 @@ export default (_this: Parcel /*, dispatch: Function*/): Object => ({ _this.getIn(keyPath).delete(); }, - update: (key: Key|Index, updater: ParcelValueUpdater) => { + update: (key: Key|Index, updater: ParcelValueUpdater|ParcelShapeUpdateFunction) => { Types(`update()`, `key`, `keyIndex`)(key); Types(`update()`, `updater`, `function`)(updater); _this.get(key).update(updater); }, - updateShape: (key: Key|Index, updater: ParcelShapeUpdater) => { - Types(`update()`, `key`, `keyIndex`)(key); - Types(`update()`, `updater`, `function`)(updater); - _this.get(key).updateShape(updater); - }, - - updateIn: (keyPath: Array, updater: ParcelValueUpdater) => { + updateIn: (keyPath: Array, updater: ParcelValueUpdater|ParcelShapeUpdateFunction) => { Types(`updateIn()`, `keyPath`, `keyIndexPath`)(keyPath); Types(`updateIn()`, `updater`, `function`)(updater); _this.getIn(keyPath).update(updater); - }, - - updateShapeIn: (keyPath: Array, updater: ParcelShapeUpdater) => { - Types(`updateShapeIn()`, `keyPath`, `keyIndexPath`)(keyPath); - Types(`updateShapeIn()`, `updater`, `function`)(updater); - _this.getIn(keyPath).updateShape(updater); } }); diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 2ee47d1d..6d751aae 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -6,11 +6,12 @@ import type {ParentType} from '../types/Types'; import type {ParcelShapeValueUpdater} from '../types/Types'; import type {ParcelShapeConfigInternal} from '../types/Types'; import type {ParcelShapeUpdater} from '../types/Types'; +import type {ParcelShapeUpdateFunction} from '../types/Types'; import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; -import {ShapeUpdaterUndefinedError} from '../errors/Errors'; +import ReducerCancelAction from '../change/ReducerCancelAction'; import ParcelTypes from '../parcel/ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; @@ -72,32 +73,6 @@ export default class ParcelShape { _parcelData: ParcelData; _parcelTypes: ParcelTypes; - static _updateFromData(updater: ParcelShapeUpdater): Function { - return (parcelData: ParcelData): ParcelData => ParcelShape - .fromData(parcelData) - .updateShape(updater) - .data; - } - - static _updateFromDataUnlessUndefined(updater: ParcelShapeUpdater): Function { - return (parcelData: ParcelData): ParcelData => { - let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); - - let updated: any = updater(parcelShape); - if(updated === undefined) { - throw ShapeUpdaterUndefinedError(); - } - - return parcelShape - .updateShape(() => updated) - .data; - }; - } - - // only need this to reference static methods on ParcelShape - // without creating circular dependencies - _instanceUpdateFromData = ParcelShape._updateFromData; - _pipeSelf = (fn: Function, _configInternal: ?ParcelShapeConfigInternal): ParcelShape => pipeWith( this._parcelData, fn, @@ -171,6 +146,33 @@ export default class ParcelShape { return parcelShape; } + static update(updater: ParcelShapeUpdater): ParcelShapeUpdateFunction { + let fn = (parcelData: ParcelData, errorOnUndefined: ?boolean): ParcelData => { + let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); + + if(errorOnUndefined) { + // $FlowFixMe why flow why + let updated: any = updater(parcelShape); + if(updated === undefined) { + ReducerCancelAction(); + } + updater = () => updated; + } + + return parcelShape + .updateShape(updater) + .data; + }; + + fn._isParcelUpdater = true; + fn._updater = updater; + return fn; + } + + // only need this to reference static methods on ParcelShape + // without creating circular dependencies + _parcelShapeUpdate = ParcelShape.update; + // Parent methods has = (key: Key|Index): boolean => this._methods.has(key); size = (): number => this._methods.size(); diff --git a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js index d00d8615..a0b3d5ca 100644 --- a/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js +++ b/packages/dataparcels/src/parcelShape/methods/ParcelShapeParentSetMethods.js @@ -52,7 +52,7 @@ export default (_this: ParcelShape) => ({ return _this._pipeSelf( parcelUpdateIn( keyPath, - (parcelData) => _this._instanceUpdateFromData(updater)(parcelData) + (parcelData) => _this._parcelShapeUpdate(updater)(parcelData) ) ); } diff --git a/packages/dataparcels/src/parcelShape/shape.js b/packages/dataparcels/src/parcelShape/shape.js new file mode 100644 index 00000000..8495e2c8 --- /dev/null +++ b/packages/dataparcels/src/parcelShape/shape.js @@ -0,0 +1,3 @@ +// @flow +import ParcelShape from './ParcelShape'; +export default ParcelShape.update; diff --git a/packages/react-dataparcels/shape.js b/packages/react-dataparcels/shape.js new file mode 100644 index 00000000..78aa9538 --- /dev/null +++ b/packages/react-dataparcels/shape.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/shape.js').default; From deffe3caace11c24770fe36fe99630bd405e05c8 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:14:27 +1100 Subject: [PATCH 079/120] BREAK: make reducer able to cancel action during execution --- .../dataparcels/src/change/ChangeRequest.js | 4 +-- .../src/change/ChangeRequestReducer.js | 32 ++++++++++++++++--- .../src/change/ReducerCancelAction.js | 11 +++++++ 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 packages/dataparcels/src/change/ReducerCancelAction.js diff --git a/packages/dataparcels/src/change/ChangeRequest.js b/packages/dataparcels/src/change/ChangeRequest.js index cd0f3045..40f4ed78 100644 --- a/packages/dataparcels/src/change/ChangeRequest.js +++ b/packages/dataparcels/src/change/ChangeRequest.js @@ -62,7 +62,7 @@ export default class ChangeRequest { }; // $FlowFixMe - this doesn't have side effects - get nextData(): * { + get nextData(): ?ParcelData { if(!this._baseParcel) { throw ChangeRequestUnbasedError(); } @@ -89,7 +89,7 @@ export default class ChangeRequest { } // $FlowFixMe - this doesn't have side effects - get prevData(): * { + get prevData(): ParcelData { if(!this._baseParcel) { throw ChangeRequestUnbasedError(); } diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 267e4bd7..4b7a99a2 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -1,16 +1,20 @@ // @flow import type ChangeRequest from './ChangeRequest'; import type Action from './Action'; +import type {ParcelData} from '../types/Types'; import type {ParcelDataEvaluator} from '../types/Types'; import butLast from 'unmutable/lib/butLast'; import identity from 'unmutable/lib/identity'; import last from 'unmutable/lib/last'; import pipe from 'unmutable/lib/util/pipe'; +import pipeWith from 'unmutable/lib/util/pipeWith'; import composeWith from 'unmutable/lib/util/composeWith'; import {ReducerInvalidActionError} from '../errors/Errors'; +import {IsReducerCancelAction} from './ReducerCancelAction'; + import del from '../parcelData/delete'; import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; import insertAfter from '../parcelData/insertAfter'; @@ -86,8 +90,26 @@ const doDeepAction = (action: Action): ParcelDataEvaluator => { ); }; -export default (changeRequest: ChangeRequest): ParcelDataEvaluator => pipe( - ...changeRequest - .actions() - .map(doDeepAction) -); +export default (changeRequest: ChangeRequest) => (parcelData: ParcelData): ?ParcelData => { + let cancelled = 0; + let actions = changeRequest.actions(); + + let newParcelData = pipeWith( + parcelData, + ...actions.map((action): ParcelDataEvaluator => (parcelData: ParcelData): ParcelData => { + try { + return doDeepAction(action)(parcelData); + } catch(e) { + if(IsReducerCancelAction(e)) { + cancelled++; + return parcelData; + } + throw e; + } + }) + ); + + return cancelled > 0 && cancelled === actions.length + ? undefined + : newParcelData; +}; diff --git a/packages/dataparcels/src/change/ReducerCancelAction.js b/packages/dataparcels/src/change/ReducerCancelAction.js new file mode 100644 index 00000000..dfe487f3 --- /dev/null +++ b/packages/dataparcels/src/change/ReducerCancelAction.js @@ -0,0 +1,11 @@ +// @flow + +const MESSAGE = 'CancelAction'; + +export default () => { + throw new Error(MESSAGE); +}; + +export const IsReducerCancelAction = (e: Error): boolean => { + return e.message === MESSAGE; +}; From fd52cd545ebeb42b6c882cd445fec09c0650c2a0 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:14:56 +1100 Subject: [PATCH 080/120] refactor: add setMetaDefault --- packages/dataparcels/src/parcelData/setMetaDefault.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 packages/dataparcels/src/parcelData/setMetaDefault.js diff --git a/packages/dataparcels/src/parcelData/setMetaDefault.js b/packages/dataparcels/src/parcelData/setMetaDefault.js new file mode 100644 index 00000000..03038953 --- /dev/null +++ b/packages/dataparcels/src/parcelData/setMetaDefault.js @@ -0,0 +1,10 @@ +// @flow +import type {ParcelData} from '../types/Types'; + +export default (newMeta: *) => ({meta = {}, ...rest}: ParcelData): ParcelData => ({ /* eslint-disable-line no-unused-vars */ + ...rest, + meta: { + ...newMeta, + ...meta + } +}); From 27fb9f2357a63b7d2cd25802d17829c719d70a37 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:16:00 +1100 Subject: [PATCH 081/120] refactor: remove unneeded error --- packages/dataparcels/src/errors/Errors.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index a25b29b0..7175ad88 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -2,7 +2,6 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); -export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a deep updater method (e.g. Deep()) for updating collections.`); +export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a shape updater method (e.g. Shape()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); export const ShapeUpdaterNonShapeChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a ParcelShape`); -export const ShapeUpdaterUndefinedError = () => new Error(`ShapeUpdaterUndefinedError`); From ef992cde0c2f0867edf50394579b6ba0809e3728 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:17:03 +1100 Subject: [PATCH 082/120] BREAK: remove batch and all batch related methods --- .../src/change/__test__/ChangeRequest-test.js | 57 -------- .../src/parcel/__test__/ActionMethods-test.js | 124 ------------------ .../parcel/__test__/TopLevelMethods-test.js | 22 ---- .../src/parcel/methods/ActionMethods.js | 45 +------ .../src/parcel/methods/TopLevelMethods.js | 26 ---- packages/dataparcels/src/types/Types.js | 4 +- packages/react-dataparcels/src/ParcelHoc.jsx | 7 +- 7 files changed, 11 insertions(+), 274 deletions(-) delete mode 100644 packages/dataparcels/src/parcel/__test__/TopLevelMethods-test.js delete mode 100644 packages/dataparcels/src/parcel/methods/TopLevelMethods.js diff --git a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js index 70a7b97c..79cd10a8 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequest-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequest-test.js @@ -198,30 +198,6 @@ test('ChangeRequest should keep originId and originPath', () => { .onChange(456); }); - -test('ChangeRequest should keep originId and originPath even when going through a batch() where another change is fired before the original one', () => { - expect.assertions(2); - - var data = { - value: { - abc: 123, - def: 456 - }, - handleChange: (parcel: Parcel, changeRequest: ChangeRequest) => { - expect(['abc']).toEqual(changeRequest.originPath); - expect('^.~mcb-1049856033.abc').toEqual(changeRequest.originId); - } - }; - - new Parcel(data) - .modifyChange((parcel, changeRequest) => { - parcel.set('def', 789); - parcel.dispatch(changeRequest); - }) - .get('abc') - .onChange(456); -}); - test('ChangeRequest should cache its data after its calculated, so subsequent calls are faster', () => { let amount = 1000; @@ -307,39 +283,6 @@ test('ChangeRequest should cache its data after its calculated, so subsequent ca expect(ms2).toBeLessThan(ms / 100); // expect amazing performance boosts from having cached }); -test('ChangeRequest data chache should be invalidated correctly', () => { - expect.assertions(6); - - var parcel = new Parcel({ - value: { - a: { - b: 123 - } - } - }); - - parcel - .get('a') - .modifyChange((parcel, changeRequest) => { - expect(changeRequest.nextData).toEqual({key: 'a', meta: {abc: 123}, value: {b: 456}, child: {b:{key: "b"}}}); - expect(changeRequest.nextData).toEqual({key: 'a', meta: {abc: 123}, value: {b: 456}, child: {b:{key: "b"}}}); // get cached - parcel.dispatch(changeRequest); - }) - .modifyChange((parcel, changeRequest) => { - expect(changeRequest.nextData).toEqual({key: 'a', meta: {}, value: {b: 456}, child: {b:{key: "b"}}}); - expect(changeRequest.nextData).toEqual({key: 'a', meta: {}, value: {b: 456}, child: {b:{key: "b"}}}); // get cached - parcel.dispatch(changeRequest); - parcel.setMeta({abc: 123}); - }) - .get('b') - .modifyChange((parcel, changeRequest) => { - expect(changeRequest.nextData).toEqual({key: 'b', meta: {}, value: 456}); - expect(changeRequest.nextData).toEqual({key: 'b', meta: {}, value: 456}); // get cached - parcel.dispatch(changeRequest); - }) - .onChange(456); -}); - test('ChangeRequest getDataIn should return previous and next value at keyPath', () => { var action = new Action({ type: "set", diff --git a/packages/dataparcels/src/parcel/__test__/ActionMethods-test.js b/packages/dataparcels/src/parcel/__test__/ActionMethods-test.js index 000c41e7..a1e8d74e 100644 --- a/packages/dataparcels/src/parcel/__test__/ActionMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ActionMethods-test.js @@ -25,127 +25,3 @@ test('Parcel.dispatch() should pass handleChange to newly created parcel', () => expect(changeRequest2.nextData.value).toBe(789); expect(changeRequest2.prevData.value).toBe(456); }); - -test('Parcel.batch() should batch actions', () => { - expect.assertions(4); - - var functionCalls = []; - var expectedFunctionCalls = [ - 'batch', - 'onChange(456)', - 'onChange(789)', - 'handleChange' - ]; - - - var data = { - value: 123, - handleChange: (parcel) => { - let {value} = parcel; - expect(value).toBe(789); - functionCalls.push("handleChange"); - } - }; - - new Parcel(data).batch((parcel) => { - functionCalls.push("batch"); - parcel.onChange(456); - expect(parcel.value).toBe(456); - functionCalls.push("onChange(456)"); - parcel.onChange(789); - expect(parcel.value).toBe(789); - functionCalls.push("onChange(789)"); - }); - - expect(expectedFunctionCalls).toEqual(functionCalls); -}); - -test('Parcel.batch() should batch correctly with non-idempotent actions', () => { - expect.assertions(4); - - var functionCalls = []; - var expectedFunctionCalls = [ - 'batch', - 'push(456)', - 'push(789)', - 'handleChange' - ]; - - var data = { - value: [], - handleChange: (parcel) => { - let {value} = parcel; - expect(value).toEqual([456,789]); - functionCalls.push("handleChange"); - } - }; - - new Parcel(data).batch((parcel) => { - functionCalls.push("batch"); - parcel.push(456); - expect(parcel.value).toEqual([456]); - functionCalls.push("push(456)"); - parcel.push(789); - expect(parcel.value).toEqual([456, 789]); - functionCalls.push("push(789)"); - }); - - expect(expectedFunctionCalls).toEqual(functionCalls); -}); - -test('Parcel.batch() should not fire handleChange if no actions called within batch', () => { - var handleChangeCalled = false; - - var data = { - value: 123, - handleChange: (parcel) => { - handleChangeCalled = true; - } - }; - - new Parcel(data).batch((parcel) => {}); - expect(handleChangeCalled).toBe(false); -}); - -test('Parcel.batch() should be nestable', () => { - expect.assertions(5); - - var functionCalls = []; - var expectedFunctionCalls = [ - 'batch', - 'onChange(123)', - 'batch again', - 'onChange(456)', - 'out again', - 'onChange(789)', - 'handleChange' - ]; - - var data = { - value: 123, - handleChange: (parcel) => { - let {value} = parcel; - expect(value).toBe(789); - functionCalls.push("handleChange"); - } - }; - - new Parcel(data).batch((parcel) => { - functionCalls.push("batch"); - parcel.onChange(123); - expect(parcel.value).toBe(123); - functionCalls.push("onChange(123)"); - parcel.batch((parcel) => { - functionCalls.push("batch again"); - parcel.onChange(456); - expect(parcel.value).toBe(456); - functionCalls.push("onChange(456)"); - }); - functionCalls.push("out again"); - parcel.onChange(789); - expect(parcel.value).toBe(789); - functionCalls.push("onChange(789)"); - }); - - expect(expectedFunctionCalls).toEqual(functionCalls); -}); diff --git a/packages/dataparcels/src/parcel/__test__/TopLevelMethods-test.js b/packages/dataparcels/src/parcel/__test__/TopLevelMethods-test.js deleted file mode 100644 index bea9bb21..00000000 --- a/packages/dataparcels/src/parcel/__test__/TopLevelMethods-test.js +++ /dev/null @@ -1,22 +0,0 @@ -// @flow -import Parcel from '../Parcel'; - -test('Parcel.batchAndReturn() should batch actions and return parcel', () => { - let handleChange = jest.fn(); - let newParcel = new Parcel({ - value: { - abc: 123, - def: 456 - }, - handleChange - }).batchAndReturn((parcel) => { - parcel.get('abc').onChange(789); - }); - - expect(newParcel.value).toEqual({ - abc: 789, - def: 456 - }); - - expect(handleChange).toHaveBeenCalledTimes(0); -}); diff --git a/packages/dataparcels/src/parcel/methods/ActionMethods.js b/packages/dataparcels/src/parcel/methods/ActionMethods.js index 412708a1..084aa90f 100644 --- a/packages/dataparcels/src/parcel/methods/ActionMethods.js +++ b/packages/dataparcels/src/parcel/methods/ActionMethods.js @@ -1,14 +1,11 @@ // @flow import type Action from '../../change/Action'; import type Parcel from '../Parcel'; -import type {ParcelData} from '../../types/Types'; -import type {ParcelBatcher} from '../../types/Types'; import Types from '../../types/Types'; import ChangeRequest from '../../change/ChangeRequest'; export default (_this: Parcel): Object => ({ - dispatch: (dispatchable: Action|Action[]|ChangeRequest) => { Types(`dispatch()`, `dispatchable`, `dispatchable`)(dispatchable); @@ -17,8 +14,6 @@ export default (_this: Parcel): Object => ({ _onHandleChange } = _this; - _this._treeshare.dispatch.markPathAsDispatched(_this.path); - let changeRequest: ChangeRequest = dispatchable instanceof ChangeRequest ? dispatchable : new ChangeRequest(dispatchable); @@ -33,48 +28,22 @@ export default (_this: Parcel): Object => ({ changeRequest.toConsole(); } - if(_this._dispatchBuffer) { - _this._dispatchBuffer(changeRequest); - return; - } - if(_onHandleChange) { let changeRequestWithBase = changeRequest._setBaseParcel(_this); + let parcelData = changeRequestWithBase.nextData; + + if(!parcelData) { + return; + } + let parcelWithChangedData = _this._create({ handleChange: _onHandleChange, - parcelData: changeRequestWithBase.nextData + parcelData }); _onHandleChange(parcelWithChangedData, changeRequestWithBase); return; } _onDispatch && _onDispatch(changeRequest); - }, - - batch: (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => { - Types(`batch()`, `batcher`, `function`)(batcher); - - let parcelData: ParcelData = _this._parcelData; - let lastBuffer = _this._dispatchBuffer; - - let buffer = changeRequest - ? changeRequest.updateActions(() => []) - : new ChangeRequest(); - - _this._dispatchBuffer = (changeRequest: ChangeRequest) => { - buffer = buffer.merge(changeRequest); - _this._parcelData = changeRequest - ._setBaseParcel(_this) - .nextData; - }; - - batcher(_this); - _this._dispatchBuffer = lastBuffer; - if(buffer.actions().length === 0) { - return; - } - - _this._parcelData = parcelData; - _this.dispatch(buffer); } }); diff --git a/packages/dataparcels/src/parcel/methods/TopLevelMethods.js b/packages/dataparcels/src/parcel/methods/TopLevelMethods.js deleted file mode 100644 index 0f00ec2c..00000000 --- a/packages/dataparcels/src/parcel/methods/TopLevelMethods.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow -import type Parcel from '../Parcel'; -import type {ParcelBatcher} from '../../types/Types'; -import Types from '../../types/Types'; - -import ChangeRequest from '../../change/ChangeRequest'; - -export default (_this: Parcel): Object => ({ - - batchAndReturn: (batcher: ParcelBatcher, changeRequest: ?ChangeRequest): ?Parcel => { - Types(`batchAndReturn()`, `batcher`, `function`)(batcher); - - let newParcel; - - // swap out the parcels real _onHandleChange with a spy - let handleChange = _this._onHandleChange; - _this._onHandleChange = (parcel: Parcel) => { - newParcel = parcel; - newParcel._onHandleChange = handleChange; - }; - _this.batch(batcher, changeRequest); - _this._onHandleChange = handleChange; - - return newParcel; - } -}); diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index a45eab8d..bfba2e66 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -41,10 +41,10 @@ export type ParcelCreateConfigType = { }; export type ParcelMeta = {[key: string]: *}; -export type ParcelBatcher = (item: Parcel) => void; -export type ParcelMapper = (item: Parcel, index: string|number, _this: Parcel) => *; +export type ParcelMapper = (item: Parcel, property: string|number, parent: Parcel) => *; export type ParcelUpdater = (item: Parcel) => Parcel; export type ParcelValueUpdater = (value: *, parcel: Parcel) => any; +export type ParcelShapeUpdateFunction = Function; export type ParcelShapeUpdater = (item: ParcelShape) => any; export type ParcelShapeSetMeta = ParcelMeta | (meta: ParcelMeta) => ParcelMeta; diff --git a/packages/react-dataparcels/src/ParcelHoc.jsx b/packages/react-dataparcels/src/ParcelHoc.jsx index efe4c8a2..4aa16b83 100644 --- a/packages/react-dataparcels/src/ParcelHoc.jsx +++ b/packages/react-dataparcels/src/ParcelHoc.jsx @@ -1,7 +1,7 @@ // @flow import type {ComponentType} from 'react'; import type {Node} from 'react'; -import type {ChangeRequest} from 'dataparcels'; +import type ChangeRequest from 'dataparcels/ChangeRequest'; import React from 'react'; import Parcel from 'dataparcels'; @@ -94,10 +94,7 @@ export default (config: ParcelHocConfig): Function => { if(parcel && shouldParcelUpdateFromProps && shouldParcelUpdateFromProps(state.prevProps, props, valueFromProps)) { // $FlowFixMe - parcel cant possibly be undefined here - newState.parcel = parcel.batchAndReturn((parcel: Parcel) => { - // $FlowFixMe - newValueFromProps cant possibly be undefined here - parcel.set(valueFromProps(props)); - }); + newState.parcel = parcel._setAndReturn(valueFromProps(props)); if(debugParcel) { log(`Parcel updated from props:`); From 54b1cb3f5642add6ae7bc760e63fb7af2cb35581 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:17:40 +1100 Subject: [PATCH 083/120] BREAK: remove hasDispatched and dispatch registry --- .../parcel/__test__/ParcelGetMethods-test.js | 22 ------------------- .../dataparcels/src/treeshare/Treeshare.js | 17 -------------- 2 files changed, 39 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js index 6b9e994d..5d1e2c39 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetMethods-test.js @@ -78,28 +78,6 @@ test('Parcel.spreadDOM(notFoundValue) returns an object with notFoundValue', () expect(parcel3.spreadDOM("???").value).toBe("123"); }); -test('Parcel.hasDispatched() should say if a parcel has dispatched from the current parcels path location', () => { - expect.assertions(6); - - let p = new Parcel({ - value: { - abc: 123, - def: 456 - }, - handleChange: (p2) => { - expect(p2.hasDispatched()).toBe(true); - expect(p2.get('abc').hasDispatched()).toBe(true); - expect(p2.get('def').hasDispatched()).toBe(false); - } - }); - - expect(p.hasDispatched()).toBe(false); - expect(p.get('abc').hasDispatched()).toBe(false); - expect(p.get('def').hasDispatched()).toBe(false); - - p.get('abc').onChange(789); -}); - test('Parcel.setInternalLocationShareData() and Parcel.getInternalLocationShareData should store data per location', () => { let p = new Parcel({ diff --git a/packages/dataparcels/src/treeshare/Treeshare.js b/packages/dataparcels/src/treeshare/Treeshare.js index 943baa2f..3ad59cd2 100644 --- a/packages/dataparcels/src/treeshare/Treeshare.js +++ b/packages/dataparcels/src/treeshare/Treeshare.js @@ -12,18 +12,6 @@ class ParcelRegistry { }; } -class DispatchRegistry { - _dispatchedPaths: Object = {}; - - hasPathDispatched = (path: string[]): boolean => { - return !!this._dispatchedPaths[stringifyPath(path)]; - }; - - markPathAsDispatched = (path: string[]) => { - this._dispatchedPaths[stringifyPath(path)] = true; - }; -} - class LocationShareRegistry { _locationShareData: Object = {}; @@ -41,31 +29,26 @@ class LocationShareRegistry { type Config = { registry?: ParcelRegistry, - dispatch?: DispatchRegistry, locationShare?: LocationShareRegistry }; export default class Treeshare { registry: ParcelRegistry; - dispatch: DispatchRegistry; locationShare: LocationShareRegistry; constructor(config: Config = {}) { let { registry, - dispatch, locationShare } = config; this.registry = registry || new ParcelRegistry(); - this.dispatch = dispatch || new DispatchRegistry(); this.locationShare = locationShare || new LocationShareRegistry(); } boundarySplit: Function = (): Treeshare => { return new Treeshare({ // do not pass in registry - dispatch: this.dispatch, locationShare: this.locationShare }); } From 381d92107f44b8b035c3dc36157258c8c181e472 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:18:11 +1100 Subject: [PATCH 084/120] BREAK: remove setChangeRequestMeta --- .../dataparcels/src/parcel/methods/ParcelChangeMethods.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js index d4aaaff3..38a1392b 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelChangeMethods.js @@ -39,10 +39,5 @@ export default (_this: Parcel, dispatch: Function) => ({ setMeta: (partialMeta: ParcelMeta) => { Types(`setMeta()`, `partialMeta`, `object`)(partialMeta); dispatch(ActionCreators.setMeta(partialMeta)); - }, - - setChangeRequestMeta: (partialMeta: ParcelMeta) => { - Types(`setChangeRequestMeta()`, `partialMeta`, `object`)(partialMeta); - dispatch(new ChangeRequest().setChangeRequestMeta(partialMeta)); } }); From 83c8b4833979734797626bfe6636afd49061a74c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:18:34 +1100 Subject: [PATCH 085/120] refactor: import from new slash imports --- packages/react-dataparcels/src/ParcelBoundary.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-dataparcels/src/ParcelBoundary.jsx b/packages/react-dataparcels/src/ParcelBoundary.jsx index 4b2ac8a3..e28f28b0 100644 --- a/packages/react-dataparcels/src/ParcelBoundary.jsx +++ b/packages/react-dataparcels/src/ParcelBoundary.jsx @@ -1,8 +1,9 @@ // @flow -import React from 'react'; import type {Node} from 'react'; +import type ChangeRequest from 'dataparcels/ChangeRequest'; + +import React from 'react'; import Parcel from 'dataparcels'; -import type {ChangeRequest} from 'dataparcels'; import ParcelBoundaryEquals from './util/ParcelBoundaryEquals'; import shallowEquals from 'unmutable/lib/shallowEquals'; From 3fdf3d52232b672865508a266b116b10768599e0 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:18:58 +1100 Subject: [PATCH 086/120] test: improve tests --- .../src/parcel/__test__/ParcelGetters-test.js | 55 ++++++++++--- .../__test__/ParcelShapeTypes-test.js | 82 ++++++++----------- 2 files changed, 79 insertions(+), 58 deletions(-) diff --git a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js index f40ca157..722fb058 100644 --- a/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js +++ b/packages/dataparcels/src/parcel/__test__/ParcelGetters-test.js @@ -73,12 +73,12 @@ test('Parcel.id should return the Parcels id', () => { ['something.:@']: 123 } }; - expect("^").toBe(new Parcel(data).id); - expect("^.a").toBe(new Parcel(data).get("a").id); - expect("^.~mv-364997092.a").toBe(new Parcel(data).modifyDown(ii => ii).get("a").id); - expect("^.a.#a").toBe(new Parcel(data).getIn(["a",0]).id); - expect("^.something%.%:%@").toBe(new Parcel(data).get("something.:@").id); - expect("^.b").toBe(new Parcel(data).get("b").id); + expect(new Parcel(data).id).toBe("^"); + expect(new Parcel(data).get("a").id).toBe("^.a"); + expect(new Parcel(data).modifyDown(ii => ii).get("a").id).toBe("^.~md-364997092.a"); + expect(new Parcel(data).getIn(["a",0]).id).toBe("^.a.#a"); + expect(new Parcel(data).get("something.:@").id).toBe("^.something%.%:%@"); + expect(new Parcel(data).get("b").id).toBe("^.b"); // t.is("#a", new Parcel(data).getIn(["a",?????]).id); TODO }); @@ -89,11 +89,42 @@ test('Parcel.path should return the Parcels path', () => { ['something.:@']: 123 } }; - expect([]).toEqual(new Parcel(data).path); - expect(["a"]).toEqual(new Parcel(data).get("a").path); - expect(["a"]).toEqual(new Parcel(data).modifyDown(ii => ii).get("a").path); - expect(["a","#a"]).toEqual(new Parcel(data).getIn(["a",0]).path); - expect(["something.:@"]).toEqual(new Parcel(data).get("something.:@").path); - expect(["b"]).toEqual(new Parcel(data).get("b").path); + expect(new Parcel(data).path).toEqual([]); + expect(new Parcel(data).get("a").path).toEqual(["a"]); + expect(new Parcel(data).modifyDown(ii => ii).get("a").path).toEqual(["a"]); + expect(new Parcel(data).getIn(["a",0]).path).toEqual(["a","#a"]); + expect(new Parcel(data).get("something.:@").path).toEqual(["something.:@"]); + expect(new Parcel(data).get("b").path).toEqual(["b"]); // t.is("#a", new Parcel(data).getIn(["a",?????]).path); TODO }); + + +test('Parcel should throw errors when attempted to set getters', () => { + let readOnly = 'This property is read-only'; + + let parcel = new Parcel(); + + expect(() => { + parcel.data = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.value = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.meta = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.key = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.id = 123; + }).toThrow(readOnly); + + expect(() => { + parcel.path = 123; + }).toThrow(readOnly); +}); diff --git a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js index 776f9944..dd176513 100644 --- a/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js +++ b/packages/dataparcels/src/parcelShape/__test__/ParcelShapeTypes-test.js @@ -132,50 +132,40 @@ test('ParcelShapeTypes should correctly identify element values with getIn', () expect(new ParcelShape(value).getIn(["b",0]).isTopLevel()).toBe(false); }); -// // method creators - -// // test('Correct methods are created for primitive values', () => { -// // var value = 123; -// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); -// // expect(() => new ParcelShape(value).has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for object values', () => { -// // var value = {a: 123}; -// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); -// // expect(() => new ParcelShape(value).has('a')).not.toThrow(); -// // expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for array values', () => { -// // var value = [1,2,3]; -// // expect(() => new ParcelShape(value).set('A')).not.toThrow(); -// // expect(() => new ParcelShape(value).has('a')).not.toThrow(); -// // expect(() => new ParcelShape(value).pop()).not.toThrow(); -// // expect(() => new ParcelShape(value).delete()).toThrowError(`.delete() cannot be called with 0 arguments`); -// // expect(() => new ParcelShape(value).swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for object child values', () => { -// // var value = {a: 123}; -// // expect(() => new ParcelShape(value).get("a").set('A')).not.toThrow(); -// // expect(() => new ParcelShape(value).get("a").has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new ParcelShape(value).get("a").pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new ParcelShape(value).get("a").delete()).not.toThrow(); -// // expect(() => new ParcelShape(value).get("a").swapNext()).toThrowError(`.swapNext() cannot be called with 0 arguments`); -// // }); - -// // test('Correct methods are created for array element values', () => { -// // var value = [1,2,3]; -// // expect(() => new ParcelShape(value).get(0).set('A')).not.toThrow(); -// // expect(() => new ParcelShape(value).get(0).has('a')).toThrowError(`.has() is not a function`); -// // expect(() => new ParcelShape(value).get(0).pop()).toThrowError(`.pop() is not a function`); -// // expect(() => new ParcelShape(value).get(0).delete()).not.toThrow(); -// // expect(() => new ParcelShape(value).get(0).swapNext()).not.toThrow(); -// // }); +// method creators + +test('Correct methods are created for primitive values', () => { + var value = 123; + expect(() => new ParcelShape(value).set('A')).not.toThrow(); + expect(() => new ParcelShape(value).has('a')).toThrowError(`.has() is not a function`); + expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); +}); + +test('Correct methods are created for object values', () => { + var value = {a: 123}; + expect(() => new ParcelShape(value).set('A')).not.toThrow(); + expect(() => new ParcelShape(value).has('a')).not.toThrow(); + expect(() => new ParcelShape(value).pop()).toThrowError(`.pop() is not a function`); +}); + +test('Correct methods are created for array values', () => { + var value = [1,2,3]; + expect(() => new ParcelShape(value).set('A')).not.toThrow(); + expect(() => new ParcelShape(value).has('a')).not.toThrow(); + expect(() => new ParcelShape(value).pop()).not.toThrow(); +}); + +test('Correct methods are created for object child values', () => { + var value = {a: 123}; + expect(() => new ParcelShape(value).get("a").set('A')).not.toThrow(); + expect(() => new ParcelShape(value).get("a").has('a')).toThrowError(`.has() is not a function`); + expect(() => new ParcelShape(value).get("a").pop()).toThrowError(`.pop() is not a function`); +}); + +test('Correct methods are created for array element values', () => { + var value = [1,2,3]; + expect(() => new ParcelShape(value).get(0).set('A')).not.toThrow(); + expect(() => new ParcelShape(value).get(0).has('a')).toThrowError(`.has() is not a function`); + expect(() => new ParcelShape(value).get(0).pop()).toThrowError(`.pop() is not a function`); +}); From 44a2e1de57dcd7bbc26367e7ca68dbb9483639af Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:21:00 +1100 Subject: [PATCH 087/120] BREAK: remove hasDispatched, batch, batchAndReturn, modifyChange, setChangeRequestMeta and all unreleased Shape methods --- packages/dataparcels/src/parcel/Parcel.js | 40 +++++++++-------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 2038b9ce..06836f56 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -4,7 +4,6 @@ import type ChangeRequest from '../change/ChangeRequest'; import type {ParcelCreateConfigType} from '../types/Types'; import type {Index} from '../types/Types'; import type {Key} from '../types/Types'; -import type {ParcelBatcher} from '../types/Types'; import type {ParcelConfigInternal} from '../types/Types'; import type {ParcelConfig} from '../types/Types'; import type {ParcelData} from '../types/Types'; @@ -13,7 +12,7 @@ import type {ParcelMeta} from '../types/Types'; import type {ParcelUpdater} from '../types/Types'; import type {ParcelValueUpdater} from '../types/Types'; import type {ParentType} from '../types/Types'; -import type {ParcelShapeUpdater} from '../types/Types'; +import type {ParcelShapeUpdateFunction} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; @@ -29,12 +28,12 @@ import ChildChangeMethods from './methods/ChildChangeMethods'; import ElementChangeMethods from './methods/ElementChangeMethods'; import ModifyMethods from './methods/ModifyMethods'; import AdvancedMethods from './methods/AdvancedMethods'; -import TopLevelMethods from './methods/TopLevelMethods'; import FilterMethods from '../util/FilterMethods'; import ParcelTypes from './ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; import Treeshare from '../treeshare/Treeshare'; +import setSelf from '../parcelData/setSelf'; import overload from 'unmutable/lib/util/overload'; @@ -122,9 +121,7 @@ export default class Parcel { // $FlowFixMe ...ModifyMethods(this), // $FlowFixMe - ...AdvancedMethods(this), - // $FlowFixMe - ...FilterMethods("TopLevel", TopLevelMethods)(this, dispatch) + ...AdvancedMethods(this) }; } @@ -143,7 +140,6 @@ export default class Parcel { _treeshare: Treeshare; // from methods - _dispatchBuffer: ?Function; // used by batch() _log: boolean = false; // used by log() _logName: string = ""; // used by log() @@ -179,6 +175,14 @@ export default class Parcel { ); }; + _setAndReturn = (value: any): Parcel => { + // $FlowFixMe whyyyyyyyyyyyyyyyyyy + return this._create({ + handleChange: this._onHandleChange, + parcelData: setSelf(value)(this._parcelData) + }); + }; + // // getters // @@ -267,9 +271,6 @@ export default class Parcel { isFirst = (): boolean => this._methods.isFirst(); isLast = (): boolean => this._methods.isLast(); - // Status methods - hasDispatched = (): boolean => this._methods.hasDispatched(); - // Side-effect methods log = (name: string = ""): Parcel => this._methods.log(name); spy = (sideEffect: Function): Parcel => this._methods.spy(sideEffect); @@ -283,16 +284,11 @@ export default class Parcel { ["2"]: (key: Key|Index, value: any) => this._methods.set(key, value) }); update = overload({ - ["1"]: (updater: ParcelValueUpdater) => this._methods.updateSelf(updater), - ["2"]: (key: Key|Index, updater: ParcelValueUpdater) => this._methods.update(key, updater) - }); - updateShape = overload({ - ["1"]: (updater: ParcelShapeUpdater) => this._methods.updateSelfShape(updater), - ["2"]: (key: Key|Index, updater: ParcelShapeUpdater) => this._methods.updateShape(key, updater) + ["1"]: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction) => this._methods.updateSelf(updater), + ["2"]: (key: Key|Index, updater: ParcelValueUpdater|ParcelShapeUpdateFunction) => this._methods.update(key, updater) }); setIn = (keyPath: Array, value: any) => this._methods.setIn(keyPath, value); updateIn = (keyPath: Array, updater: ParcelValueUpdater) => this._methods.updateIn(keyPath, updater); - updateShapeIn = (keyPath: Array, updater: ParcelShapeUpdater) => this._methods.updateShapeIn(keyPath, updater); delete = overload({ ["0"]: () => this._methods.deleteSelf(), ["1"]: (key: Key|Index) => this._methods.delete(key) @@ -301,10 +297,7 @@ export default class Parcel { // Advanced change methods setMeta = (partialMeta: ParcelMeta) => this._methods.setMeta(partialMeta); - setChangeRequestMeta = (partialMeta: ParcelMeta) => this._methods.setChangeRequestMeta(partialMeta); dispatch = (dispatchable: Action|Action[]|ChangeRequest) => this._methods.dispatch(dispatchable); - batch = (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => this._methods.batch(batcher, changeRequest); - batchAndReturn = (batcher: ParcelBatcher, changeRequest: ?ChangeRequest) => this._methods.batchAndReturn(batcher, changeRequest); // Indexed methods insertAfter = overload({ @@ -337,11 +330,8 @@ export default class Parcel { unshift = (...values: Array) => this._methods.unshift(...values); // Modify methods - modifyDown = (updater: Function): Parcel => this._methods.modifyDown(updater); - modifyUp = (updater: Function): Parcel => this._methods.modifyUp(updater); - modifyShapeDown = (updater: Function): Parcel => this._methods.modifyShapeDown(updater); - modifyShapeUp = (updater: Function): Parcel => this._methods.modifyShapeUp(updater); - modifyChange = (batcher: ParcelBatcher): Parcel => this._methods.modifyChange(batcher); + modifyDown = (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => this._methods.modifyDown(updater); + modifyUp = (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => this._methods.modifyUp(updater); initialMeta = (initialMeta: ParcelMeta): Parcel => this._methods.initialMeta(initialMeta); _boundarySplit = (config: *): Parcel => this._methods._boundarySplit(config); From 72c5e26e4ea71ef171ac7a606ccc90706899758d Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:39:13 +1100 Subject: [PATCH 088/120] refactor: fix flow --- packages/dataparcels/src/parcel/Parcel.js | 2 +- packages/dataparcels/src/parcelShape/ParcelShape.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 06836f56..9b15182e 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -176,7 +176,7 @@ export default class Parcel { }; _setAndReturn = (value: any): Parcel => { - // $FlowFixMe whyyyyyyyyyyyyyyyyyy + // $FlowFixMe return this._create({ handleChange: this._onHandleChange, parcelData: setSelf(value)(this._parcelData) diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index 6d751aae..d3a412e4 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -151,7 +151,7 @@ export default class ParcelShape { let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); if(errorOnUndefined) { - // $FlowFixMe why flow why + // $FlowFixMe - this is passed a ParcelShape, but flow thinks that is incompatible with the argument of ParcelShapeUpdater let updated: any = updater(parcelShape); if(updated === undefined) { ReducerCancelAction(); From 32cceac1f2022b395f19529a15a85e5eb82a3a31 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:39:53 +1100 Subject: [PATCH 089/120] BREAK: remove Parcel.hasDispatched() --- packages/dataparcels/src/parcel/methods/ParcelGetMethods.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js b/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js index d5775ddb..49df2bdd 100644 --- a/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js +++ b/packages/dataparcels/src/parcel/methods/ParcelGetMethods.js @@ -47,12 +47,6 @@ export default (_this: Parcel) => ({ ); }, - // Status methods - - hasDispatched: (): boolean => { - return _this._treeshare.dispatch.hasPathDispatched(_this.path); - }, - // Side-effect methods log: (name: string): Parcel => { From 387b3f3d8ec63c4cb5c44e88666ba75f20069243 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 28 Jan 2019 23:45:45 +1100 Subject: [PATCH 090/120] wip --- .../src/content/APIExamples.md | 3 +- .../dataparcels-docs/src/content/Examples.md | 6 +- .../src/content/parcelshape.gif | Bin 0 -> 3018 bytes .../src/docs/api/action/Action.md | 4 +- .../docs/api/changeRequest/ChangeRequest.md | 6 +- .../src/docs/api/parcel/batch.md | 3 - .../src/docs/api/parcel/batchAndReturn.md | 3 - .../src/docs/api/parcel/children.md | 28 ++- .../src/docs/api/parcel/delete.md | 23 ++- .../src/docs/api/parcel/deleteIn.md | 17 ++ .../src/docs/api/parcel/dispatch.md | 5 + .../src/docs/api/parcel/get.md | 4 - .../src/docs/api/parcel/getIn.md | 12 +- .../src/docs/api/parcel/has.md | 2 +- .../src/docs/api/parcel/hasDispatched.md | 3 - .../src/docs/api/parcel/initialMeta.md | 19 +- .../src/docs/api/parcel/insertAfter.md | 22 ++- .../src/docs/api/parcel/insertBefore.md | 21 +- .../src/docs/api/parcel/key.md | 2 +- .../src/docs/api/parcel/modifyChange.md | 3 - .../src/docs/api/parcel/modifyDown.md | 23 ++- .../src/docs/api/parcel/modifyShapeDown.md | 12 +- .../src/docs/api/parcel/modifyShapeUp.md | 15 +- .../src/docs/api/parcel/modifyUp.md | 30 ++- .../src/docs/api/parcel/move.md | 19 ++ .../src/docs/api/parcel/onChange.md | 4 +- .../src/docs/api/parcel/onChangeDOM.md | 2 +- .../src/docs/api/parcel/pop.md | 9 + .../src/docs/api/parcel/push.md | 9 + .../src/docs/api/parcel/set.md | 32 +++- .../docs/api/parcel/setChangeRequestMeta.md | 3 - .../src/docs/api/parcel/setIn.md | 20 +- .../src/docs/api/parcel/setMeta.md | 23 +++ .../src/docs/api/parcel/shift.md | 9 + .../src/docs/api/parcel/size.md | 2 +- .../src/docs/api/parcel/spread.md | 6 +- .../src/docs/api/parcel/spreadDOM.md | 6 +- .../src/docs/api/parcel/swap.md | 18 ++ .../src/docs/api/parcel/swapNext.md | 18 ++ .../src/docs/api/parcel/swapPrev.md | 18 ++ .../src/docs/api/parcel/toArray.md | 28 ++- .../src/docs/api/parcel/toObject.md | 28 ++- .../src/docs/api/parcel/unshift.md | 9 + .../src/docs/api/parcel/update.md | 33 +++- .../src/docs/api/parcel/updateIn.md | 20 +- .../src/docs/api/parcel/updateInShape.md | 3 - .../src/docs/api/parcel/updateShape.md | 14 +- .../src/docs/api/parcel/updateShapeIn.md | 13 ++ .../src/docs/api/parcel/value.md | 2 - .../src/docs/api/parcelShape/ParcelShape.md | 6 +- .../src/docs/api/parcelShape/children.md | 20 +- .../src/docs/api/parcelShape/delete.md | 4 +- .../src/docs/api/parcelShape/deleteIn.md | 2 +- .../src/docs/api/parcelShape/get.md | 4 - .../src/docs/api/parcelShape/getIn.md | 24 +-- .../src/docs/api/parcelShape/has.md | 2 +- .../src/docs/api/parcelShape/insertAfter.md | 4 +- .../src/docs/api/parcelShape/insertBefore.md | 4 +- .../docs/api/parcelShape/modifyShapeDown.md | 3 - .../src/docs/api/parcelShape/modifyShapeUp.md | 3 - .../src/docs/api/parcelShape/move.md | 4 +- .../src/docs/api/parcelShape/pop.md | 2 +- .../src/docs/api/parcelShape/push.md | 2 +- .../src/docs/api/parcelShape/set.md | 30 ++- .../src/docs/api/parcelShape/setIn.md | 20 +- .../src/docs/api/parcelShape/setMeta.md | 2 +- .../src/docs/api/parcelShape/shift.md | 2 +- .../src/docs/api/parcelShape/size.md | 2 +- .../src/docs/api/parcelShape/swap.md | 4 +- .../src/docs/api/parcelShape/swapNext.md | 4 +- .../src/docs/api/parcelShape/swapPrev.md | 4 +- .../src/docs/api/parcelShape/toArray.md | 20 +- .../src/docs/api/parcelShape/toObject.md | 20 +- .../src/docs/api/parcelShape/unshift.md | 2 +- .../src/docs/api/parcelShape/update.md | 4 +- .../src/docs/api/parcelShape/updateIn.md | 2 +- .../src/docs/api/parcelShape/updateShape.md | 4 +- .../src/docs/api/parcelShape/updateShapeIn.md | 2 +- .../src/docs/api/parcelShape/value.md | 2 - .../src/docs/notes/ChildKeys.md | 2 +- .../src/docs/notes/IndexedKeys.md | 10 +- .../src/docs/notes/ShapeUpdater.md | 13 ++ .../src/docs/notes/ValueUpdater.md | 15 ++ .../src/examples/EditingArraysSortableHoc.jsx | 51 ++--- .../src/examples/EditingObjects.jsx | 11 +- .../src/examples/ModifyConditional.jsx | 34 ++++ .../src/examples/ModifyDownUp.jsx | 31 +++ .../src/examples/ParcelBoundaryHold.jsx | 4 +- .../src/examples/ParcelMetaChangedValues.jsx | 47 +++++ .../ParcelMetaConfirmingDeletions.jsx | 34 ++++ .../dataparcels-docs/src/pages/api/Parcel.jsx | 34 +--- .../src/pages/examples/editing-arrays.md | 55 +++--- .../src/pages/examples/parcelboundary-hold.md | 4 +- .../src/pages/modifiers-and-updaters.js | 11 ++ .../src/pages/modifiers-and-updaters.md | 47 +++++ .../dataparcels-docs/src/pages/parcel-keys.js | 15 +- .../dataparcels-docs/src/pages/parcel-keys.md | 35 ++++ .../dataparcels-docs/src/pages/parcel-meta.js | 15 +- .../dataparcels-docs/src/pages/parcel-meta.md | 179 ++++++++++++++++++ .../src/pages/shape-updaters.js | 10 - .../src/pages/value-updaters.js | 10 - 101 files changed, 1232 insertions(+), 257 deletions(-) create mode 100644 packages/dataparcels-docs/src/content/parcelshape.gif delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/batch.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/batchAndReturn.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/hasDispatched.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/setChangeRequestMeta.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md create mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md create mode 100644 packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md create mode 100644 packages/dataparcels-docs/src/docs/notes/ValueUpdater.md create mode 100644 packages/dataparcels-docs/src/examples/ModifyConditional.jsx create mode 100644 packages/dataparcels-docs/src/examples/ModifyDownUp.jsx create mode 100644 packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx create mode 100644 packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx create mode 100644 packages/dataparcels-docs/src/pages/modifiers-and-updaters.js create mode 100644 packages/dataparcels-docs/src/pages/modifiers-and-updaters.md create mode 100644 packages/dataparcels-docs/src/pages/parcel-keys.md create mode 100644 packages/dataparcels-docs/src/pages/parcel-meta.md delete mode 100644 packages/dataparcels-docs/src/pages/shape-updaters.js delete mode 100644 packages/dataparcels-docs/src/pages/value-updaters.js diff --git a/packages/dataparcels-docs/src/content/APIExamples.md b/packages/dataparcels-docs/src/content/APIExamples.md index 6f8303ee..c8943fed 100644 --- a/packages/dataparcels-docs/src/content/APIExamples.md +++ b/packages/dataparcels-docs/src/content/APIExamples.md @@ -5,7 +5,8 @@ import Link from 'gatsby-link'; ### Parcel * Editing objects -* Editing arrays +* Editing arrays (including drag & drop) +* Parcel meta * Managing your own parcel state ### ParcelHoc diff --git a/packages/dataparcels-docs/src/content/Examples.md b/packages/dataparcels-docs/src/content/Examples.md index e17d4a0d..94323645 100644 --- a/packages/dataparcels-docs/src/content/Examples.md +++ b/packages/dataparcels-docs/src/content/Examples.md @@ -1,6 +1,8 @@ import Link from 'gatsby-link'; * Editing objects -* Editing arrays -* Managing your own parcel state +* Editing arrays (including drag & drop) * Storing parcel state in the query string +* Confirming deletions +* Debouncing inputs +* Managing your own parcel state diff --git a/packages/dataparcels-docs/src/content/parcelshape.gif b/packages/dataparcels-docs/src/content/parcelshape.gif new file mode 100644 index 0000000000000000000000000000000000000000..2add16017f51220cea05b7f04a01c61b624b8209 GIT binary patch literal 3018 zcma)#_dnE+1IOQIuS6;`Ldhn3%P4!D@+m7(nPqlyirg~qj-{%j{$K&~UydIC2m5rsIzKp8z{kN+$Jw zU{OG2?ZeHtVanr>;6-TdPRtIIj1RL`7EK#0i5Pll@RC{qv8{2hqg6+aY(ME@5TW*} z1>@^)p1ccbU)&|dIM&VW9CbV!-}%ji!4XJQd_rPUata!QO-;k4XJlq&=j7%+&o6jU zSo9MAicnlqT2@~1y0WUernZh)-_ZD`skw#J+ScCD`L>JP-P7CGKR_8A8Xg&aH#Sb4 zn0!C=VS0u(OP`xx__)YeT3-3|d3A05i#h-T0UK#sEGNI8Wcj+Aw14pD;K$BSV0-fi z3;-bxciBfZiIQ*@&THcGVK_!t{3Fr*ry_fOeJRJPcRh>i&szyg3Nll~^~+>BGc~Wf zy9{QaM-T#!2l;FoWwQ&^Vz)lEO!^Dq_0fC>Gw%ZgOC++DOK(lRK3U-uqQM@Z&3RMK z)a+C+{h)uQ7_=&g($|)rX;2)~NVg*d|3ea3SDZlisJgw3NoVt0`k^w=Z7I+zFAi20 zq-cp0AeB)X{6ote)eb2)Yp#yjl<`ZIKQCXpm;)z?8>@oME92ryataR*Sf^JuoL$a| zQMRg@bS3eL9-hX@?fyk&d+ijr<z5i4 zC&C|o$~v|xRC>0Pe`K#W-pZ!1!vE{6%AUtF##W1KT#s*4A=74|+mxZpF-&CKq#skf zVVXwk4ybf#uDOUeZb#RV+5xl^i8{m|A5nTfNyy}RJoI^D$O7dq_zIbX#TZOLb9oP2 z@x?ku`}hkyW(H6X$Tx}b`(C;kdVRRr)90?mI=2O|Wz$^sQMWHNbFt^nKwqE63OkyW zY5N(>N~T_~c5^6rHSrwvVv3fGDzakepLpq^6Bz$;5^zVox+Wlcf^dV!J)S^SQ$&@R znf~G{HTC|5EFBBTFD`ZoqhrdAal^=p(Y!Wfr2)Q;uS%c%YdM1fuPmzxpUnTr>NfZU zSv7nVgd|?tP?W556|iF^4#^it*E*}AF^w8vF(mU1#kESN;gw5*v=llBmvq!e^qMBy)mxbg0$Pb7mbg)tE^TjKNZ87t9L!E?}3!_oX9p&%T zH|ER7;gNrcBQ2*2tElJ1BvhzrL!-R$a!R*-jIE#cnm%r|RiUA{vfjf$9dJ_PblL(5 zFyN5_nj^$CW3Og>DCyLhz9$E2(TPYr)|}Nz;4XKLZd{OG)S18S$biJzlK2v;kVmd} zh1>OTZp&wSSHP5w$fwyJUaYHOSyC9%5)5aXtZgLQEs+i$Rq@D<>UwCVTe zv$Au4u-qUu?mePlcdk8{$Nk&{%X2D>?b(hfFTUt6+nYj8M`_TlM|4F1X7UsxpnO7v z%ux=QJRv!WYR8ag%|XDp2qT_s>I2wKn6rA~&TzW|tRh6%#Yr-hJ&>%Rcmz91mrAyK zxO|alEg);4&cWhM7Pf$snG%yQ^zrW93)FxD&Wdmj03gU#>$2+5SFv!tLXZGn2ep-+ zI!3)Hxi*kya%hHwp@0k7^@D<14g6_FW-@T~p;ImqC(3*8@orfgv&m?j0ENL=t1A-h zgZ9{8lq5>q%~Dj0A~<*gq|I(7Crr9H@Rf<*CI(Cf-)d?=)9lnWp7b zHjjmwVyIhuNCXp35Un=Tk*q{u%|RvftZr-0Vaa-N2+#Qi7Tb5NLuek&;!QIFD=Z^_ zhC0ReSsZY@LFU)mK3%rw5_oy>IRejr#s;LeF?rs!*w{e*r8afgI71Yf7h&Ff(*x0LcDKxw3lLhzbx;qoF)g5hTVA(2c|LE{Fds)2lUui zhb76uxk1|s)bbSIN?oDLpz0TEdj4*d)%L@Oi%lN%zi(PV$J>F(0{Vo-K4kc@$|IkG zImpshEAwsk_0Gxy1w6M#yXL5H6sMl&ESA4@fGxDXtZMF?xmJ9zOdx5Xoozhw!J|}( z^5FiFkG8?7Ps3`qE7z;oej`RZ<*Z9%>MR&Hj)e&av>no~IW|_S8crL`Zn=ENYtENv zyBk)B7hNotIZlf7%~`0&U3I>D#xAN-B2qofZEFef;mBJy({z(!Lfe*vU@~PPNNW1iRC6|(EBJ^?dsnc z)CYnFS>d+ZYyIstmj_>`l!)5OzO!leQBl*0Um=-+5-4ATENXX|iqDQHb@Py1BCl4aRaLYmeDv&IA^UiIvdZ|3cX18wN` z=}xDHZhNavmKNKXB@_A9$ai8wk_W5Y8cb5|9bAO?cL-f2t_9pE`hnP^w8mHDInGoG zcFLTKex)NBJy~TijqRPOF2UNlx8$$f)`?wp`FMY72oK}7$hDePjv~zEhew<;+Pt># z>rVSy!$zdUHtD9J_IB+h{?g;srDvg9E4GlXGeAAWsw&BT{YMAuTRznAEzAd6!{Fl zl{%Du=8HZ(quUfIJUG7Z91W#z7S*rGW0&Slr2Z-uF*|Y#A0B76(jkYjmV*AwuGKhC z4%nV7?1~v|!ygtr5JzAAH$y6A;X+BUO<%Y$7ks4*PD_A)T!X*93TKx`tXd*Y1R&;E z5aR@xb~g-Efv}+nk;Q8{<%jKu8%OR|Pz%_^vu)NJ3;aJFpgnJ^vo1Y+F8Nj{V1VeBn zIx1>)Kk7DDVySjwtiMuZQev`CBtcF-J1X&+b?g^^|K?jsGFnd$qaLHmlej*Z_D?^< ziLleGlCz literal 0 HcmV?d00001 diff --git a/packages/dataparcels-docs/src/docs/api/action/Action.md b/packages/dataparcels-docs/src/docs/api/action/Action.md index 429ce91d..dde96034 100644 --- a/packages/dataparcels-docs/src/docs/api/action/Action.md +++ b/packages/dataparcels-docs/src/docs/api/action/Action.md @@ -3,8 +3,8 @@ import Link from 'component/Link'; # Action ```js -import {Action} from 'dataparcels'; -import {Action} from 'react-dataparcels'; +import Action from 'dataparcels/Action'; +import Action from 'react-dataparcels/Action'; ``` ```flow diff --git a/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md b/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md index d11090c1..9fb62243 100644 --- a/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md +++ b/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md @@ -3,8 +3,8 @@ import Link from 'component/Link'; # ChangeRequest ```js -import {ChangeRequest} from 'dataparcels'; -import {ChangeRequest} from 'react-dataparcels'; +import ChangeRequest from 'dataparcels/ChangeRequest'; +import ChangeRequest from 'react-dataparcels/ChangeRequest'; ``` ```flow @@ -17,4 +17,4 @@ When a change occurs, ChangeRequests are used by Parcels to describe what to cha ChangeRequests contain an array of Actions to perform. -ChangeRequests can most often be accessed in `handleChange` and `modifyChange` functions. Most of the time these operate invisibly, and it's extremely rare that you'll create these yourself. +ChangeRequests can most often be accessed in `handleChange` and `modifyUp` functions. Most of the time these operate invisibly, and it's extremely rare that you'll create these yourself. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/batch.md b/packages/dataparcels-docs/src/docs/api/parcel/batch.md deleted file mode 100644 index 08740905..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/batch.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -batch(batcher: Function): void -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/batchAndReturn.md b/packages/dataparcels-docs/src/docs/api/parcel/batchAndReturn.md deleted file mode 100644 index fc712baa..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/batchAndReturn.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -batchAndReturn(batcher: Function): ?Parcel // only on TopLevelParcels -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/children.md b/packages/dataparcels-docs/src/docs/api/parcel/children.md index 18f8d0d5..0e1e34cd 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/children.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/children.md @@ -1,3 +1,29 @@ ```flow -children(mapper?: Function): ParentType // only on ParentParcels +children(mapper?: ParcelMapper): ParentType // only on ParentParcels + +type ParcelMapper = ( + item: Parcel, + property: string|number, + parent: Parcel +) => any; +``` + +Returns all of the Parcel's children as new ChildParcels, contained within the original Parcel's data structure. + +An optional `mapper` function can be passed, which will be called on each child. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcel = new Parcel({value}); +parcel.children(); + +// returns { +// abc: Parcel, // contains a value of 123 +// def: Parcel // contains a value of 456 +// } + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/delete.md b/packages/dataparcels-docs/src/docs/api/parcel/delete.md index 135f718c..c03d6b83 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/delete.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/delete.md @@ -1,4 +1,25 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -delete(): void +delete(): void // only on ChildParcels delete(key: string|number): void // only on ParentParcels, will delete a child ``` + +Calling `delete()` with no arguments will trigger a change that will delete the current Parcel off of its parent. This variation of the `delete()` method only exists on ChildParcels. + +On ParentParcels this method can be called with a `key`, which deletes the child value at that key. + +```js +let value = { + abc: 123, + def: 456 +}; +let parcel = new Parcel({value}); +parcel.get('abc').delete(); +// this triggers a change that sets the parcel's value to {def: 456} + +parcel.delete('abc'); +// this also triggers a change that sets the parcel's value to {def: 456} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/deleteIn.md b/packages/dataparcels-docs/src/docs/api/parcel/deleteIn.md index ca08ddb9..9372e7e3 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/deleteIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/deleteIn.md @@ -1,3 +1,20 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow deleteIn(keyPath: Array): void // only on ParentParcels ``` + +Calling `setIn()` will trigger a change that will delete the value at the provided `keyPath`. + +```js +let value = { + a: { + b: 123 + } +}; +let parcel = new Parcel({value}); +parcel.deleteIn(['a','b']); +// this triggers a change that sets the parcel's value to {a: {}} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/dispatch.md b/packages/dataparcels-docs/src/docs/api/parcel/dispatch.md index e9f93551..a16e372c 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/dispatch.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/dispatch.md @@ -1,3 +1,8 @@ +import Link from 'component/Link'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; + ```flow dispatch(dispatchable: Action|Action[]|ChangeRequest): void ``` + +The `dispatch()` method is used by Parcels internally to pass a ChangeRequest upward to the next Parcel in the chain. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/get.md b/packages/dataparcels-docs/src/docs/api/parcel/get.md index 1ce5dfb9..704b163c 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/get.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/get.md @@ -23,10 +23,6 @@ parcel.get('xyz', 789).value; // returns 789 #### get() with indexed values -When called on a Parcel with an indexed value, such as an array, `get()` can accept an `index` or a `key`. -- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. -- `key` (string) is used to get a specific value by its unique key within the Parcel. - ```js diff --git a/packages/dataparcels-docs/src/docs/api/parcel/getIn.md b/packages/dataparcels-docs/src/docs/api/parcel/getIn.md index f45a0a79..00ed77e0 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/getIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/getIn.md @@ -1,3 +1,5 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow getIn(keyPath: Array): Parcel // only on ParentParcels getIn(keyPath: Array, notSetValue: any): Parcel // only on ParentParcels @@ -15,11 +17,9 @@ let value = { } }; let parcel = new Parcel({value}); -parcel.get(['a','b']).value; // returns 123 -parcel.get(['a','z']).value; // returns undefined -parcel.get(['a','z'], 789).value; // returns 789 +parcel.getIn(['a','b']).value; // returns 123 +parcel.getIn(['a','z']).value; // returns undefined +parcel.getIn(['a','z'], 789).value; // returns 789 ``` -#### getIn() with indexed values - -... + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/has.md b/packages/dataparcels-docs/src/docs/api/parcel/has.md index 86e1e119..f610c61a 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/has.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/has.md @@ -2,4 +2,4 @@ has(key: string|number): boolean // only on ParentParcels ``` -Returns true if the parcel has a child at the provided `key` or `index`, or false otherwise. +Returns true if the Parcel has a child at the provided `key` or `index`, or false otherwise. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/hasDispatched.md b/packages/dataparcels-docs/src/docs/api/parcel/hasDispatched.md deleted file mode 100644 index f4691653..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/hasDispatched.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -hasDispatched(): boolean -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/initialMeta.md b/packages/dataparcels-docs/src/docs/api/parcel/initialMeta.md index 23c6925b..1797abf5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/initialMeta.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/initialMeta.md @@ -1,3 +1,20 @@ ```flow -initialMeta(initialMeta: Object): void +initialMeta(initialMeta: Object): Parcel +``` + +Parcel `meta` defaults to an empty object. The `initialMeta` method replaces this `meta` for all descendant Parcels. + +Once a descendant Parcel triggers a change, the initial meta is also propagated up to the top level Parcel. + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel + .initialMeta({ + abc: 123 + }) + .meta // this returns {abc: 123} initially, but this can change after subsequent calls to setMeta() + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/insertAfter.md b/packages/dataparcels-docs/src/docs/api/parcel/insertAfter.md index d6b3369a..00ee8d27 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/insertAfter.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/insertAfter.md @@ -1,4 +1,22 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -insertAfter(value: *): void // only on ElementParcels, will insert after self -insertAfter(key: string|number, value: *): void // only on IndexedParcels, will insert after child +insertAfter(value: any): void // only on ElementParcels, will insert after self +insertAfter(key: string|number, value: any): void // only on IndexedParcels, will insert after child ``` + +When called with one argument, this inserts `value` after the current Parcel, within the current ParentParcel. + +When called with two arguments, this inserts `value` after the child Parcel at `key`. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(1).insertAfter('!'); +// this triggers a change that sets the parcel's value to ['a','b','!','c']; + +parcel.insertAfter(1, '!'); +// this also triggers a change that sets the parcel's value to ['a','b','!','c']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/insertBefore.md b/packages/dataparcels-docs/src/docs/api/parcel/insertBefore.md index 5e788267..d474a940 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/insertBefore.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/insertBefore.md @@ -1,4 +1,21 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -insertBefore(value: *): void // only on ElementParcels, will insert before self -insertBefore(key: string|number, value: *): void // only on IndexedParcels, will insert before child +insertBefore(value: any): void // only on ElementParcels, will insert before self +insertBefore(key: string|number, value: any): void // only on IndexedParcels, will insert before child ``` + +When called with one argument, this inserts `value` before the current Parcel, within the current ParentParcel. +When called with two arguments, this inserts `value` as the next sibling Parcel before the child Parcel at `key`. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(1).insertBefore('!'); +// this triggers a change that sets the parcel's value to ['a','!','b','c']; + +parcel.insertBefore(1, '!'); +// this also triggers a change that sets the parcel's value to ['a','!','b','c']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/key.md b/packages/dataparcels-docs/src/docs/api/parcel/key.md index 36c6ae05..dde72b43 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/key.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/key.md @@ -4,7 +4,7 @@ import Link from 'component/Link'; key: string ``` -Returns the Parcel's `key`. Dataarcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. +Returns the Parcel's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated in the Editing Arrays example. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md deleted file mode 100644 index bdce6131..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyChange.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyChange(batcher: Function): void -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md index 1bbab5f1..f6628d7b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md @@ -1,4 +1,25 @@ +import ValueUpdater from 'docs/notes/ValueUpdater.md'; + ```flow -modifyDown(updater: Function): Parcel +modifyDown(updater: ValueUpdater): Parcel + +type ValueUpdater = (value: any, self: Parcel) => any; +``` + +`modifyDown` lets you modify a Parcel's value so that lower Parcels receive and make changes against the modified value. + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel + .modifyDown(value => value.toUpperCase()); + .value // "ABC" (top level Parcel is still "abc") ``` +It does not trigger any changes of its own, it just modifies the values that pass through it from above. Changes fired from beneath are passed through unchanged. + +The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md index 0a8057a8..0a5f592b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md @@ -1,3 +1,13 @@ +import Link from 'component/Link'; +import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; + ```flow -modifyShapeDown(updater: Function): Parcel +modifyShapeDown(updater: ShapeUpdater): Parcel + +type ShapeUpdater = (parcelShape: ParcelShape) => any ``` + +The `modifyShapeDown()` method is an advanced version of modifyDown(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md index 0a8057a8..fc8ab443 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md @@ -1,3 +1,16 @@ +import Link from 'component/Link'; +import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; + ```flow -modifyShapeDown(updater: Function): Parcel +modifyShapeUp(updater: ShapeUpdater): Parcel + +type ShapeUpdater = (parcelShape: ParcelShape) => any ``` + +The `modifyShapeUp()` method is an advanced version of modifyUp(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. + +Additionally if `updater` returns nothing (undefined), the change will be cancelled and will not propagate up any further. +If you want to legitimately return a value of `undefined` and continue to propagate the change request, return `new ParcelShape()` instead. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md index c4a128b5..139f3669 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md @@ -1,4 +1,32 @@ +import ValueUpdater from 'docs/notes/ValueUpdater.md'; + ```flow -modifyUp(updater: Function): Parcel +modifyUp(updater: ValueUpdater): Parcel + +type ValueUpdater = (value: any, self: Parcel) => any; +``` + +`modifyUp()` lets you modify a Parcel's new value when a change is being propagated upward. + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel + .modifyUp(value => value.toUpperCase()); + .set("def"); + +// this triggers a change to set the value to "def" +// which propagates upward through .modifyUp() +// .modifyUp() turns "def" into "DEF" +// and the change request continues up to the original Parcel + +// The Parcel then has a new value of "DEF" ``` +It does not trigger any changes of its own, but awaits a change from below. Values from above are passed through unchanged. + +The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/move.md b/packages/dataparcels-docs/src/docs/api/parcel/move.md index 9ba86475..b80ed0a2 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/move.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/move.md @@ -1,4 +1,23 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow move(key: string|number): void // only on ElementParcels, will move with sibling move(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will move children ``` + +When called with one argument, this moves the current Parcel to the position of `key`, within the current ParentParcel. +Other elements will shift left to fill any gaps left and/or shift right to make room for moved values. + +When called with two arguments, this moves the child Parcel at `keyA` to the position of `keyB`. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(2).move(0); +// this triggers a change that sets the parcel's value to ['c','a','b']; + +parcel.move(2, 0); +// this also triggers a change that sets the parcel's value to ['c','a','b']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/onChange.md b/packages/dataparcels-docs/src/docs/api/parcel/onChange.md index ee44497b..5c051a4e 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/onChange.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/onChange.md @@ -1,7 +1,7 @@ import {Box, Link, Message, Text} from 'dcme-style'; ```flow -onChange(value: *): void +onChange(value: any): void ``` This is designed for use with input components that call `onChange` with a new value. @@ -9,7 +9,7 @@ It triggers a change that replaces the current value in the Parcel with the `val If called on a ParentParcel, any child information that the Parcel had is removed, such as child keys or meta. -It is equivalent to calling set with no key. +It is equivalent to calling set() with no key. ```js let parcel = new Parcel({ diff --git a/packages/dataparcels-docs/src/docs/api/parcel/onChangeDOM.md b/packages/dataparcels-docs/src/docs/api/parcel/onChangeDOM.md index 308f3ed2..9ef83b6e 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/onChangeDOM.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/onChangeDOM.md @@ -1,7 +1,7 @@ import {Box, Link, Message, Text} from 'dcme-style'; ```flow -onChangeDOM(event: Event): void +onChangeDOM(event: HTMLEvent): void ``` This is designed for use with HTML inputs. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/pop.md b/packages/dataparcels-docs/src/docs/api/parcel/pop.md index daca3ead..645b98a5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/pop.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/pop.md @@ -1,3 +1,12 @@ ```flow pop(): void // only on IndexedParcels ``` + +This triggers a change that pops the last value off of the end of the current ParentParcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.pop(); +// this triggers a change that sets the parcel's value to ['a','b']; +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/push.md b/packages/dataparcels-docs/src/docs/api/parcel/push.md index 8148a42b..6485fc3a 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/push.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/push.md @@ -1,3 +1,12 @@ ```flow push(...values: Array<*>): void // only on IndexedParcels ``` + +This triggers a change that pushes all provided values to the end of the current ParentParcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.push('d','e'); +// this triggers a change that sets the parcel's value to ['a','b','c','d','e']; +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/set.md b/packages/dataparcels-docs/src/docs/api/parcel/set.md index 9db7e179..12cadc8d 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/set.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/set.md @@ -1,4 +1,32 @@ +import {Box, Link, Message} from 'dcme-style'; +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -set(value: *): void -set(key: string|number, value: *): void // only on ParentParcels, will set a child +set(value: any): void +set(key: string|number, value: any): void // only on ParentParcels, will set a child ``` + +Calling `set()` with one argument will trigger a change that replaces the current value in the Parcel with the `value` provided. This is equivalent to calling onChange(). + +```js +let parcel = new Parcel({ + value: 123 +}); +parcel.set(456); +// this triggers a change that sets the parcel's value to 456 +``` + +On ParentParcels this method can also be called with a `key`, which sets the child value at that key. + +```js +let parcel = new Parcel({ + value: { + abc: 123, + def: 789 + } +}); +parcel.set('abc', 456); +// this triggers a change that sets the parcel's value to {abc: 456, def: 789} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/setChangeRequestMeta.md b/packages/dataparcels-docs/src/docs/api/parcel/setChangeRequestMeta.md deleted file mode 100644 index 6ac69e22..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/setChangeRequestMeta.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -setChangeRequestMeta(meta: Object): void -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/setIn.md b/packages/dataparcels-docs/src/docs/api/parcel/setIn.md index dfee5742..5a4a593b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/setIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/setIn.md @@ -1,3 +1,21 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -setIn(keyPath: Array, value: *): void // only on ParentParcels +setIn(keyPath: Array, value: any): void // only on ParentParcels ``` + +Calling `setIn()` will trigger a change that will set the value at the provided `keyPath`. + +```js +let value = { + a: { + b: 123, + c: 789 + } +}; +let parcel = new Parcel({value}); +parcel.setIn(['a','b'], 456); +// this triggers a change that sets the parcel's value to {a: {b: 456, c: 789}} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/setMeta.md b/packages/dataparcels-docs/src/docs/api/parcel/setMeta.md index 662f84bb..4084d411 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/setMeta.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/setMeta.md @@ -1,3 +1,26 @@ +import ParcelMeta from 'docs/notes/ParcelMeta.md'; +import Link from 'component/Link'; + ```flow setMeta(partialMeta: Object): void ``` + +Triggers a change that sets `meta` at the current parcel's location. Values on the `partialMeta` object are merged shallowly onto any existing `meta`. + + + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel.setMeta({ + abc: 123 +}); +// ^ this triggers a change that sets the parcel's meta to {abc: 123} + +parcel.setMeta({ + def: 456 +}); +// ^ this triggers a change that sets the parcel's meta to {abc: 123, def: 456} +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/shift.md b/packages/dataparcels-docs/src/docs/api/parcel/shift.md index 143be743..784e7e89 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/shift.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/shift.md @@ -1,3 +1,12 @@ ```flow shift(): void // only on IndexedParcels ``` + +This triggers a change that pops the first value off of the start of the current ParentParcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.shift(); +// this triggers a change that sets the parcel's value to ['b','c']; +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/size.md b/packages/dataparcels-docs/src/docs/api/parcel/size.md index 3b56d840..6dc597ca 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/size.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/size.md @@ -2,4 +2,4 @@ size(): number // only on ParentParcels ``` -Returns the number of children this parcel has. +Returns the number of children this Parcel has. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/spread.md b/packages/dataparcels-docs/src/docs/api/parcel/spread.md index cdaca7c7..879368c5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/spread.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/spread.md @@ -1,6 +1,8 @@ ```flow -spread(): {value: *, onChange: Function} -spread(notFoundValue: any): {value: *, onChange: Function} +spread(): {value: *, onChange: OnChangeFunction} +spread(notFoundValue: any): {value: *, onChange: OnChangeFunction} + +type OnChangeFunction = (value: any) => void; ``` Returns an object with the Parcel's value and its onChange function. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/spreadDOM.md b/packages/dataparcels-docs/src/docs/api/parcel/spreadDOM.md index 2a6d3b0a..88f86a6d 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/spreadDOM.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/spreadDOM.md @@ -1,6 +1,8 @@ ```flow -spreadDOM(): {value: *, onChange: Function} -spreadDOM(notFoundValue: any): {value: *, onChange: Function} +spreadDOM(): {value: *, onChange: OnChangeDOMFunction} +spreadDOM(notFoundValue: any): {value: *, onChange: OnChangeDOMFunction} + +type OnChangeDOMFunction = (event: HTMLEvent) => void; ``` Returns an object with the Parcel's value and its onChangeDOM function. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/swap.md b/packages/dataparcels-docs/src/docs/api/parcel/swap.md index 853d6e4d..3693a7a6 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/swap.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/swap.md @@ -1,4 +1,22 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow swap(key: string|number): void // only on ElementParcels, will swap with sibling swap(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will swap children ``` + +When called with one argument, this swaps the current Parcel with the one at the position of `key`, within the current ParentParcel. + +When called with two arguments, this swaps the child Parcel at `keyA` with the one at the position of `keyB`. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(0).swap(1); +// this triggers a change that sets the parcel's value to ['b','a','c']; + +parcel.swap(0, 1); +// this also triggers a change that sets the parcel's value to ['b','a','c']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/swapNext.md b/packages/dataparcels-docs/src/docs/api/parcel/swapNext.md index c18f553a..950f5154 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/swapNext.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/swapNext.md @@ -1,4 +1,22 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow swapNext(): void // only on ElementParcels, will swap with next sibling swapNext(key: string|number): void // only on IndexedParcels, will swap child with next child ``` + +When called with no arguments, this swaps the current Parcel with its next sibling Parcel, within the current ParentParcel. If called on the last child, it swaps with the first child. + +When called with one argument, this swaps the child at the position of `key` with the next sibling Parcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(0).swapNext(); +// this triggers a change that sets the parcel's value to ['b','a','c']; + +parcel.swapNext(0); +// this also triggers a change that sets the parcel's value to ['b','a','c']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/swapPrev.md b/packages/dataparcels-docs/src/docs/api/parcel/swapPrev.md index 61155893..36100b8a 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/swapPrev.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/swapPrev.md @@ -1,4 +1,22 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow swapPrev(): void // only on ElementParcels, will swap with previous sibling swapPrev(key: string|number): void // only on IndexedParcels, will swap child with previous child ``` + +When called with no arguments, this swaps the current Parcel with its previous sibling Parcel, within the current ParentParcel. If called on the first child, it swaps with the last child. + +When called with one argument, this swaps the child at the position of `key` with the previous sibling Parcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.get(1).swapPrev(); +// this triggers a change that sets the parcel's value to ['b','a','c']; + +parcel.swapPrev(1); +// this also triggers a change that sets the parcel's value to ['b','a','c']; +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/toArray.md b/packages/dataparcels-docs/src/docs/api/parcel/toArray.md index e7b262b0..13a76110 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/toArray.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/toArray.md @@ -1,3 +1,29 @@ ```flow -toArray(mapper?: Function): Array // only on ParentParcels +toArray(mapper?: ParcelMapper): Array // only on ParentParcels + +type ParcelMapper = ( + item: Parcel, + property: string|number, + parent: Parcel +) => any; +``` + +Like [children()](#children), expect the returned data structure is cast to an array. + +An optional `mapper` function can be passed, which will be called on each child. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcel = new Parcel({value}); +parcel.toArray(); + +// returns [ +// Parcel, // contains a value of 123 +// Parcel // contains a value of 456 +// ] + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/toObject.md b/packages/dataparcels-docs/src/docs/api/parcel/toObject.md index 00bab19b..6ba17398 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/toObject.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/toObject.md @@ -1,3 +1,29 @@ ```flow -toObject(mapper?: Function): {[key: string]: Parcel} // only on ParentParcels +toObject(mapper?: ParcelMapper): Object // only on ParentParcels + +type ParcelMapper = ( + item: Parcel, + property: string|number, + parent: Parcel +) => any; +``` + +Like [children()](#children), expect the returned data structure is cast to an object. + +An optional `mapper` function can be passed, which will be called on each child. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcel = new Parcel({value}); +parcel.toObject(); + +// returns { +// abc: Parcel, // contains a value of 123 +// def: Parcel // contains a value of 456 +// } + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/unshift.md b/packages/dataparcels-docs/src/docs/api/parcel/unshift.md index 1611c11e..549c7e91 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/unshift.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/unshift.md @@ -1,3 +1,12 @@ ```flow unshift(...values: Array<*>): void // only on IndexedParcels ``` + +This triggers a change that unshifts all provided values to the start of the current ParentParcel. + +```js +let value = ['a','b','c']; +let parcel = new Parcel({value}); +parcel.unshift('d','e'); +// this triggers a change that sets the parcel's value to ['d','e','a','b','c']; +``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/update.md b/packages/dataparcels-docs/src/docs/api/parcel/update.md index def55433..68510fc5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/update.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/update.md @@ -1,4 +1,33 @@ +import ValueUpdater from 'docs/notes/ValueUpdater.md'; + ```flow -update(updater: Function): void -update(key: string|number, updater: Function): void // only on ParentParcels, will set a child +update(updater: ValueUpdater): void +update(key: string|number, updater: ValueUpdater): void // only on ParentParcels, will update a child + +type ValueUpdater = (value: any, self: Parcel) => any; ``` + +Calling `update()` with one argument will trigger a change that replaces the current value in the Parcel with the result of the value updater provided to it. The value updater is passed the current value of the Parcel, from which you can return the intended replacement value. + +```js +let parcel = new Parcel({ + value: 123 +}); +parcel.update(value => value + 1); +// this triggers a change that sets the parcel's value to 124 +``` + +On ParentParcels this method can also be called with a `key`, which updates the child value at that key. The value updater is passed the current value found at the `key`, from which you can return the intended replacement value. + +```js +let parcel = new Parcel({ + value: { + abc: 123, + def: 789 + } +}); +parcel.update('abc', value => value + 1); +// this triggers a change that sets the parcel's value to {abc: 124, def: 789} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateIn.md b/packages/dataparcels-docs/src/docs/api/parcel/updateIn.md index 0dadd4ff..fa4f4090 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateIn.md @@ -1,3 +1,21 @@ +import ValueUpdater from 'docs/notes/ValueUpdater.md'; + ```flow -updateIn(keyPath: Array, updater: Function): void // only on ParentParcels +updateIn(keyPath: Array, updater: ValueUpdater): void // only on ParentParcels ``` + +Calling `updateIn()` will trigger a change that will update the value at the provided `keyPath`. The value updater is passed the current value found at the `keyPath`, from which you can return the intended replacement value. + +```js +let value = { + a: { + b: 123, + c: 789 + } +}; +let parcel = new Parcel({value}); +parcel.updateIn(['a','b'], value => value + 1); +// this triggers a change that sets the parcel's value to {a: {b: 124, c: 789}} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md b/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md deleted file mode 100644 index 856d5dbc..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateInShape.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -updateInShape(keyPath: Array, updater: Function): void // only on ParentParcels -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md b/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md index c28d5b64..6bbd042e 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateShape.md @@ -1,4 +1,14 @@ +import Link from 'component/Link'; +import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; + ```flow -updateShape(updater: Function): void -updateShape(key: string|number, updater: Function): void // only on ParentParcels, will set a child +updateShape(updater: ShapeUpdater): void +updateShape(key: string|number, updater: ShapeUpdater): void // only on ParentParcels, will set a child + +type ShapeUpdater = (parcelShape: ParcelShape) => any ``` + +The `updateShape()` method is an advanced version of update(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md b/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md new file mode 100644 index 00000000..25848c1b --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md @@ -0,0 +1,13 @@ +import Link from 'component/Link'; +import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; + +```flow +updateShapeIn(keyPath: Array, updater: ShapeUpdater): void // only on ParentParcels + +type ShapeUpdater = (parcelShape: ParcelShape) => any +``` + +The `updateShapeIn()` method is an advanced version of updateIn(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. + + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/value.md b/packages/dataparcels-docs/src/docs/api/parcel/value.md index 407d001a..12ed5f45 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/value.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/value.md @@ -1,5 +1,3 @@ -import IndexedKeys from 'docs/notes/IndexedKeys.md'; - ```flow value: any ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md index 98ef8fab..edeebb8b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md @@ -2,7 +2,7 @@ import Link from 'component/Link'; import Param from 'component/Param'; import ApiPageIcon from 'component/ApiPageIcon'; import ParcelCreateReact from 'docs/notes/ParcelCreateReact.md'; -import IconParcel from 'content/parcel.gif'; +import IconParcel from 'content/parcelshape.gif'; # ParcelShape @@ -14,8 +14,8 @@ These exist to be used with shape updaters, to ParcelShape's methods are a subset of Parcel's methods. ```js -import {ParcelShape} from 'dataparcels'; -import {ParcelShape} from 'react-dataparcels'; +import ParcelShape from 'dataparcels/ParcelShape'; +import ParcelShape from 'react-dataparcels/ParcelShape'; ``` ```flow diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/children.md b/packages/dataparcels-docs/src/docs/api/parcelShape/children.md index 18f8d0d5..51bac7bb 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/children.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/children.md @@ -1,3 +1,21 @@ ```flow -children(mapper?: Function): ParentType // only on ParentParcels +children(): ParentType // only on ParentParcels +``` + +Returns all of the ParcelShape's children as new ParcelShapes, contained within the original ParcelShape's data structure. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcelShape = new ParcelShape(value); +parcelShape.children(); + +// returns { +// abc: ParcelShape, // contains a value of 123 +// def: ParcelShape // contains a value of 456 +// } + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/delete.md b/packages/dataparcels-docs/src/docs/api/parcelShape/delete.md index 135f718c..a0f76966 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/delete.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/delete.md @@ -1,4 +1,4 @@ ```flow -delete(): void -delete(key: string|number): void // only on ParentParcels, will delete a child +delete(): ParcelShape +delete(key: string|number): ParcelShape // only on ParentParcels, will delete a child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md index ca08ddb9..4aba0bfa 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/deleteIn.md @@ -1,3 +1,3 @@ ```flow -deleteIn(keyPath: Array): void // only on ParentParcels +deleteIn(keyPath: Array): ParcelShape // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/get.md b/packages/dataparcels-docs/src/docs/api/parcelShape/get.md index 78b27485..cdd6630f 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/get.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/get.md @@ -23,10 +23,6 @@ parcelShape.get('xyz', 789).value; // returns 789 #### get() with indexed values -When called on a ParcelShape with an indexed value, such as an array, `get()` can accept an `index` or a `key`. -- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. -- `key` (string) is used to get a specific value by its unique key within the ParcelShape. - ```js diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md index f45a0a79..022e7299 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/getIn.md @@ -1,11 +1,13 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -getIn(keyPath: Array): Parcel // only on ParentParcels -getIn(keyPath: Array, notSetValue: any): Parcel // only on ParentParcels +getIn(keyPath: Array): ParcelShape // only on ParentParcels +getIn(keyPath: Array, notSetValue: any): ParcelShape // only on ParentParcels ``` -Returns a Parcel containing the value associated with the provided key path. -If the key path doesn't exist, a Parcel with a value of `notSetValue` will be returned. -If `notSetValue` is not provided then a Parcel with a value of +Returns a ParcelShape containing the value associated with the provided key path. +If the key path doesn't exist, a ParcelShape with a value of `notSetValue` will be returned. +If `notSetValue` is not provided then a ParcelShape with a value of `undefined` will be returned. ```js @@ -14,12 +16,10 @@ let value = { b: 123 } }; -let parcel = new Parcel({value}); -parcel.get(['a','b']).value; // returns 123 -parcel.get(['a','z']).value; // returns undefined -parcel.get(['a','z'], 789).value; // returns 789 +let parcelShape = new ParcelShape(value); +parcelShape.get(['a','b']).value; // returns 123 +parcelShape.get(['a','z']).value; // returns undefined +parcelShape.get(['a','z'], 789).value; // returns 789 ``` -#### getIn() with indexed values - -... + diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/has.md b/packages/dataparcels-docs/src/docs/api/parcelShape/has.md index 86e1e119..a2b0990b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/has.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/has.md @@ -2,4 +2,4 @@ has(key: string|number): boolean // only on ParentParcels ``` -Returns true if the parcel has a child at the provided `key` or `index`, or false otherwise. +Returns true if the ParcelShape has a child at the provided `key` or `index`, or false otherwise. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md b/packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md index d6b3369a..b68f8177 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/insertAfter.md @@ -1,4 +1,4 @@ ```flow -insertAfter(value: *): void // only on ElementParcels, will insert after self -insertAfter(key: string|number, value: *): void // only on IndexedParcels, will insert after child +insertAfter(value: *): ParcelShape // only on ElementParcels, will insert after self +insertAfter(key: string|number, value: *): ParcelShape // only on IndexedParcels, will insert after child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md b/packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md index 5e788267..7710d2f3 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/insertBefore.md @@ -1,4 +1,4 @@ ```flow -insertBefore(value: *): void // only on ElementParcels, will insert before self -insertBefore(key: string|number, value: *): void // only on IndexedParcels, will insert before child +insertBefore(value: *): ParcelShape // only on ElementParcels, will insert before self +insertBefore(key: string|number, value: *): ParcelShape // only on IndexedParcels, will insert before child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md deleted file mode 100644 index 579c550d..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeDown.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyShapeDown(updater: Function): ParcelShape -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md deleted file mode 100644 index 579c550d..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/modifyShapeUp.md +++ /dev/null @@ -1,3 +0,0 @@ -```flow -modifyShapeDown(updater: Function): ParcelShape -``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/move.md b/packages/dataparcels-docs/src/docs/api/parcelShape/move.md index 9ba86475..37e725b3 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/move.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/move.md @@ -1,4 +1,4 @@ ```flow -move(key: string|number): void // only on ElementParcels, will move with sibling -move(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will move children +move(key: string|number): ParcelShape // only on ElementParcels, will move with sibling +move(keyA: string|number, keyB: string|number): ParcelShape // only on IndexedParcels, will move children ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/pop.md b/packages/dataparcels-docs/src/docs/api/parcelShape/pop.md index daca3ead..6f8ca09b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/pop.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/pop.md @@ -1,3 +1,3 @@ ```flow -pop(): void // only on IndexedParcels +pop(): ParcelShape // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/push.md b/packages/dataparcels-docs/src/docs/api/parcelShape/push.md index 8148a42b..27ac4b12 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/push.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/push.md @@ -1,3 +1,3 @@ ```flow -push(...values: Array<*>): void // only on IndexedParcels +push(...values: Array<*>): ParcelShape // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/set.md b/packages/dataparcels-docs/src/docs/api/parcelShape/set.md index 9db7e179..4dc1083f 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/set.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/set.md @@ -1,4 +1,30 @@ +import {Box, Link, Message} from 'dcme-style'; +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -set(value: *): void -set(key: string|number, value: *): void // only on ParentParcels, will set a child +set(value: any): ParcelShape +set(key: string|number, value: any): ParcelShape // only on ParentParcels, will set a child ``` + +Calling `set()` with one argument will return a new ParcelShape where the original value is replaced with the `value` provided. + +```js +let parcelShape = new ParcelShape(123); +parcelShape.set(456); +// returns a new ParcelShape containing 456 +``` + +On ParentParcels this method can also be called with a `key`, which returns a new ParcelShape with the the child value at that `key` set to `value`. + +```js +let parcelShape = new ParcelShape({ + value: { + abc: 123, + def: 789 + } +}); +parcelShape.set('abc', 456); +// returns a new ParcelShape containing {abc: 456, def: 789} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md index dfee5742..88197511 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/setIn.md @@ -1,3 +1,21 @@ +import IndexedKeys from 'docs/notes/IndexedKeys.md'; + ```flow -setIn(keyPath: Array, value: *): void // only on ParentParcels +setIn(keyPath: Array, value: any): ParcelShape // only on ParentParcels ``` + +Calling `setIn()` will return a new ParcelShape where the value at the provided `keyPath` has been set to `value`. + +```js +let value = { + a: { + b: 123, + c: 789 + } +}; +let parcelShape = new ParcelShape(value); +parcelShape.set(['a','b'], 456); +// returns a new ParcelShape containing {a: {b: 456, c: 789}} +``` + + diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md b/packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md index 662f84bb..fb0eb796 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/setMeta.md @@ -1,3 +1,3 @@ ```flow -setMeta(partialMeta: Object): void +setMeta(partialMeta: Object): ParcelShape ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/shift.md b/packages/dataparcels-docs/src/docs/api/parcelShape/shift.md index 143be743..c15299b8 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/shift.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/shift.md @@ -1,3 +1,3 @@ ```flow -shift(): void // only on IndexedParcels +shift(): ParcelShape // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/size.md b/packages/dataparcels-docs/src/docs/api/parcelShape/size.md index 3b56d840..3a6b29fd 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/size.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/size.md @@ -2,4 +2,4 @@ size(): number // only on ParentParcels ``` -Returns the number of children this parcel has. +Returns the number of children this ParcelShape has. diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/swap.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swap.md index 853d6e4d..f74d5d22 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/swap.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/swap.md @@ -1,4 +1,4 @@ ```flow -swap(key: string|number): void // only on ElementParcels, will swap with sibling -swap(keyA: string|number, keyB: string|number): void // only on IndexedParcels, will swap children +swap(key: string|number): ParcelShape // only on ElementParcels, will swap with sibling +swap(keyA: string|number, keyB: string|number): ParcelShape // only on IndexedParcels, will swap children ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md index c18f553a..9b19a605 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/swapNext.md @@ -1,4 +1,4 @@ ```flow -swapNext(): void // only on ElementParcels, will swap with next sibling -swapNext(key: string|number): void // only on IndexedParcels, will swap child with next child +swapNext(): ParcelShape // only on ElementParcels, will swap with next sibling +swapNext(key: string|number): ParcelShape // only on IndexedParcels, will swap child with next child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md b/packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md index 61155893..dda6ae22 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/swapPrev.md @@ -1,4 +1,4 @@ ```flow -swapPrev(): void // only on ElementParcels, will swap with previous sibling -swapPrev(key: string|number): void // only on IndexedParcels, will swap child with previous child +swapPrev(): ParcelShape // only on ElementParcels, will swap with previous sibling +swapPrev(key: string|number): ParcelShape // only on IndexedParcels, will swap child with previous child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md b/packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md index e7b262b0..3efea360 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/toArray.md @@ -1,3 +1,21 @@ ```flow -toArray(mapper?: Function): Array // only on ParentParcels +toArray(): Array // only on ParentParcels +``` + +Like [children()](#children), expect the returned data structure is cast to an array. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcelShape = new ParcelShape(value); +parcelShape.toArray(); + +// returns [ +// ParcelShape, // contains a value of 123 +// ParcelShape // contains a value of 456 +// ] + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md b/packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md index 00bab19b..d58a7f7c 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/toObject.md @@ -1,3 +1,21 @@ ```flow -toObject(mapper?: Function): {[key: string]: Parcel} // only on ParentParcels +toObject(): {[key: string]: ParcelShape} // only on ParentParcels +``` + +Like [children()](#children), expect the returned data structure is cast to an object. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcelShape = new ParcelShape(value); +parcelShape.toObject() + +// returns { +// abc: ParcelShape, // contains a value of 123 +// def: ParcelShape // contains a value of 456 +// } + ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md b/packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md index 1611c11e..21b590c0 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/unshift.md @@ -1,3 +1,3 @@ ```flow -unshift(...values: Array<*>): void // only on IndexedParcels +unshift(...values: Array<*>): ParcelShape // only on IndexedParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/update.md b/packages/dataparcels-docs/src/docs/api/parcelShape/update.md index def55433..34f14e4d 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/update.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/update.md @@ -1,4 +1,4 @@ ```flow -update(updater: Function): void -update(key: string|number, updater: Function): void // only on ParentParcels, will set a child +update(updater: Function): ParcelShape +update(key: string|number, updater: Function): ParcelShape // only on ParentParcels, will set a child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md index 0dadd4ff..3816f1ad 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/updateIn.md @@ -1,3 +1,3 @@ ```flow -updateIn(keyPath: Array, updater: Function): void // only on ParentParcels +updateIn(keyPath: Array, updater: Function): ParcelShape // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md index c28d5b64..0b4bbedc 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShape.md @@ -1,4 +1,4 @@ ```flow -updateShape(updater: Function): void -updateShape(key: string|number, updater: Function): void // only on ParentParcels, will set a child +updateShape(updater: Function): ParcelShape +updateShape(key: string|number, updater: Function): ParcelShape // only on ParentParcels, will set a child ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md index 50aa9bcc..9f10252b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/updateShapeIn.md @@ -1,3 +1,3 @@ ```flow -updateShapeIn(keyPath: Array, updater: Function): void // only on ParentParcels +updateShapeIn(keyPath: Array, updater: Function): ParcelShape // only on ParentParcels ``` diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/value.md b/packages/dataparcels-docs/src/docs/api/parcelShape/value.md index 2f9a46c5..5a1052fb 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/value.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/value.md @@ -1,5 +1,3 @@ -import IndexedKeys from 'docs/notes/IndexedKeys.md'; - ```flow value: any ``` diff --git a/packages/dataparcels-docs/src/docs/notes/ChildKeys.md b/packages/dataparcels-docs/src/docs/notes/ChildKeys.md index cbb86168..c6e95535 100644 --- a/packages/dataparcels-docs/src/docs/notes/ChildKeys.md +++ b/packages/dataparcels-docs/src/docs/notes/ChildKeys.md @@ -2,5 +2,5 @@ import {Box, Message} from 'dcme-style'; import Link from 'component/Link'; - Parcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. + Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. diff --git a/packages/dataparcels-docs/src/docs/notes/IndexedKeys.md b/packages/dataparcels-docs/src/docs/notes/IndexedKeys.md index 7898eb3b..550d72fa 100644 --- a/packages/dataparcels-docs/src/docs/notes/IndexedKeys.md +++ b/packages/dataparcels-docs/src/docs/notes/IndexedKeys.md @@ -1,6 +1,12 @@ import {Box, Message} from 'dcme-style'; import Link from 'component/Link'; - - Parcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info. +When called on a Parcel with an indexed value, such as an array, this method can accept an `index` or a `key`. +- `index` (number) is used to get a value based off its position. It can also be negative, indicating an offset from the end of the sequence. +- `key` (string) is used to get a specific value by its unique key within the Parcel. + + + + Dataparcels automatically gives unique keys to all elements of an indexed parcel. See parcel keys for more info. + diff --git a/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md b/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md new file mode 100644 index 00000000..a145fd54 --- /dev/null +++ b/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md @@ -0,0 +1,13 @@ +import Link from 'component/Link'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; +prop alt + +#### Limitations + +This method accepts a **shape updater**. Shape updaters are designed to allow collections with deep values to be altered, while also allowing Dataparcels to internally keep track of the changes that are made. + +Consider using for simple changes that don't require the shape of the data to be changed. + + + See modifiers and updaters for more info and explanations. + diff --git a/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md b/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md new file mode 100644 index 00000000..f6239b4f --- /dev/null +++ b/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md @@ -0,0 +1,15 @@ +import Link from 'component/Link'; +import {Box, Link as HtmlLink, Message} from 'dcme-style'; +prop alt + +#### Limitations + +This method accepts a **value updater**. Value updaters are great for updating primitive data types and data types that have no children, but cannot be used to update the *shape* of the data. + +When a value updater receives a collection, it must either pass it through unchanged, or turn it into a data type that has no children. + +If you need to update the shape of the data, consider using . + + + See modifiers and updaters for more info and explanations. + diff --git a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx index 510e33cc..34b75db5 100644 --- a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx @@ -3,42 +3,49 @@ import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; import {SortableContainer, SortableElement} from 'react-sortable-hoc'; import ExampleHoc from 'component/ExampleHoc'; -const FruitListParcelHoc = ParcelHoc({ - name: "fruitListParcel", - valueFromProps: (/* props */) => [ - "Apple", - "Banana", - "Crumpets" - ] -}); +// this is a generic react-sortable-hoc + dataparcels list hoc +// that you can use in your own projects + +const SortableParcelList = ({element, container}) => { + let Container = container || 'div'; + let Element = SortableElement(({parcel, ...rest}) => element(parcel, rest)); + + return SortableContainer(({parcel}) => + {parcel.toArray((elementParcel, index) => )} + ); +}; -const SortableFruitItem = SortableElement(({fruitParcel}) => { - return +// use the generic react-sortable-hoc + dataparcels list hoc +// to create a fruit-specific sortable list component + +const SortableFruitList = SortableParcelList({ + element: (parcel) => {(parcel) =>
} -
; +
}); -const SortableFruitList = SortableContainer(({fruitListParcel}) => { - return
- {fruitListParcel.toArray((fruitParcel, index) => { - return ; - })} -
; +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] }); const FruitListEditor = (props) => { let {fruitListParcel} = props; return
fruitListParcel.move(oldIndex, newIndex)} /> diff --git a/packages/dataparcels-docs/src/examples/EditingObjects.jsx b/packages/dataparcels-docs/src/examples/EditingObjects.jsx index 4ad2a24d..c0fd9d8c 100644 --- a/packages/dataparcels-docs/src/examples/EditingObjects.jsx +++ b/packages/dataparcels-docs/src/examples/EditingObjects.jsx @@ -15,24 +15,19 @@ const PersonParcelHoc = ParcelHoc({ const PersonEditor = (props) => { let {personParcel} = props; - - let firstname = personParcel.get('firstname'); - let lastname = personParcel.get('lastname'); - let postcode = personParcel.getIn(['address', 'postcode']); - return
- + {(firstname) => } - + {(lastname) => } - + {(postcode) => }
; diff --git a/packages/dataparcels-docs/src/examples/ModifyConditional.jsx b/packages/dataparcels-docs/src/examples/ModifyConditional.jsx new file mode 100644 index 00000000..e2a8dc35 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ModifyConditional.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const AgeParcelHoc = ParcelHoc({ + name: "ageParcel", + valueFromProps: (/* props */) => 22 +}); + +const NameEditor = (props) => { + let ageParcel = props + .ageParcel + .modifyDown(number => `${number}`) + // .modifyShapeUp(parcelShape => { + // let updated = parcelShape.update(string => Number(string)); + // return isNaN(updated.value) ? undefined : updated; + // }); + // .modifyChange((parcel, changeRequest) => { + // let string = changeRequest.nextData.value; + // let updated = Number(string); + // if(!isNaN(updated)) { + // parcel.set(updated); + // } + // }) + + return
+ + + {(ageParcel) => } + +
; +}; + +export default AgeParcelHoc(ExampleHoc(NameEditor)); diff --git a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx new file mode 100644 index 00000000..610d75d0 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const PathParcelHoc = ParcelHoc({ + name: "pathParcel", + valueFromProps: (/* props */) => "abc.def" +}); + +const PathEditor = (props) => { + let pathArrayParcel = props + .pathParcel + .modifyDown(string => string.split(".")) // turn value into an array on the way down + .modifyUp(array => array.join(".")); // turn value back into a string on the way up + + return
+ {pathArrayParcel.toArray((pathSegmentParcel) => { + return + {(parcel) =>
+ + + + +
} +
; + })} + +
; +}; + +export default PathParcelHoc(ExampleHoc(PathEditor)); diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx index 836ecfaf..bfe0546d 100644 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx @@ -7,7 +7,7 @@ const NameParcelHoc = ParcelHoc({ valueFromProps: (/* props */) => "Gregor" }); -const FoodEditor = (props) => { +const NameEditor = (props) => { let {nameParcel} = props; return
@@ -21,4 +21,4 @@ const FoodEditor = (props) => {
; }; -export default NameParcelHoc(ExampleHoc(FoodEditor)); +export default NameParcelHoc(ExampleHoc(NameEditor)); diff --git a/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx b/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx new file mode 100644 index 00000000..c8b3bb82 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + firstname: "Robert", + lastname: "Clamps" + }) +}); + +const withOriginalMeta = (parcel) => parcel.initialMeta({ + original: parcel.value +}); + +const PersonEditor = (props) => { + let {personParcel} = props; + + let firstname = personParcel + .get('firstname') + .pipe(withOriginalMeta); + + let lastname = personParcel + .get('lastname') + .pipe(withOriginalMeta); + + return
+ + + {(firstname) =>
+ +
Changed? {firstname.meta.original === firstname.value ? 'No' : 'Yes'}
+
} +
+ + + + {(lastname) =>
+ +
Changed? {lastname.meta.original === lastname.value ? 'No' : 'Yes'}
+
} +
+
; +}; + +export default PersonParcelHoc(ExampleHoc(PersonEditor)); diff --git a/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx b/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx new file mode 100644 index 00000000..a3be22c0 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ {fruitListParcel.toArray((fruitParcel) => { + return + {(parcel) =>
+ + {parcel.meta.confirming + ? Are you sure? + + + + : } +
} +
; + })} + +
; +}; + +export default FruitListParcelHoc(ExampleHoc(FruitListEditor)); diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 24e14d8d..4a14f557 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -26,9 +26,7 @@ import Markdown_onChangeDOM from 'docs/api/parcel/onChangeDOM.md'; import Markdown_set from 'docs/api/parcel/set.md'; import Markdown_setIn from 'docs/api/parcel/setIn.md'; import Markdown_update from 'docs/api/parcel/update.md'; -import Markdown_updateShape from 'docs/api/parcel/updateShape.md'; import Markdown_updateIn from 'docs/api/parcel/updateIn.md'; -import Markdown_updateInShape from 'docs/api/parcel/updateInShape.md'; import Markdown_delete from 'docs/api/parcel/delete.md'; import Markdown_deleteIn from 'docs/api/parcel/deleteIn.md'; import Markdown_insertAfter from 'docs/api/parcel/insertAfter.md'; @@ -42,22 +40,15 @@ import Markdown_swapNext from 'docs/api/parcel/swapNext.md'; import Markdown_swapPrev from 'docs/api/parcel/swapPrev.md'; import Markdown_unshift from 'docs/api/parcel/unshift.md'; import Markdown_setMeta from 'docs/api/parcel/setMeta.md'; -import Markdown_setChangeRequestMeta from 'docs/api/parcel/setChangeRequestMeta.md'; import Markdown_dispatch from 'docs/api/parcel/dispatch.md'; -import Markdown_batch from 'docs/api/parcel/batch.md'; -import Markdown_batchAndReturn from 'docs/api/parcel/batchAndReturn.md'; import Markdown_modifyDown from 'docs/api/parcel/modifyDown.md'; import Markdown_modifyUp from 'docs/api/parcel/modifyUp.md'; -import Markdown_modifyShapeDown from 'docs/api/parcel/modifyShapeDown.md'; -import Markdown_modifyShapeUp from 'docs/api/parcel/modifyShapeUp.md'; -import Markdown_modifyChange from 'docs/api/parcel/modifyChange.md'; import Markdown_initialMeta from 'docs/api/parcel/initialMeta.md'; import Markdown_isChild from 'docs/api/parcel/isChild.md'; import Markdown_isElement from 'docs/api/parcel/isElement.md'; import Markdown_isIndexed from 'docs/api/parcel/isIndexed.md'; import Markdown_isParent from 'docs/api/parcel/isParent.md'; import Markdown_isTopLevel from 'docs/api/parcel/isTopLevel.md'; -import Markdown_hasDispatched from 'docs/api/parcel/hasDispatched.md'; import Markdown_log from 'docs/api/parcel/log.md'; import Markdown_spy from 'docs/api/parcel/spy.md'; import Markdown_spyChange from 'docs/api/parcel/spyChange.md'; @@ -89,9 +80,7 @@ const md = { set: Markdown_set, setIn: Markdown_setIn, update: Markdown_update, - updateShape: Markdown_updateShape, updateIn: Markdown_updateIn, - updateInShape: Markdown_updateInShape, delete: Markdown_delete, deleteIn: Markdown_deleteIn, insertAfter: Markdown_insertAfter, @@ -105,22 +94,15 @@ const md = { swapPrev: Markdown_swapPrev, unshift: Markdown_unshift, setMeta: Markdown_setMeta, - setChangeRequestMeta: Markdown_setChangeRequestMeta, dispatch: Markdown_dispatch, - batch: Markdown_batch, - batchAndReturn: Markdown_batchAndReturn, modifyDown: Markdown_modifyDown, modifyUp: Markdown_modifyUp, - modifyShapeDown: Markdown_modifyShapeDown, - modifyShapeUp: Markdown_modifyShapeUp, - modifyChange: Markdown_modifyChange, initialMeta: Markdown_initialMeta, isChild: Markdown_isChild, isElement: Markdown_isElement, isIndexed: Markdown_isIndexed, isParent: Markdown_isParent, isTopLevel: Markdown_isTopLevel, - hasDispatched: Markdown_hasDispatched, log: Markdown_log, spy: Markdown_spy, spyChange: Markdown_spyChange, @@ -160,9 +142,9 @@ setIn() delete() deleteIn() update() -updateShape() updateIn() -updateShapeIn() +setMeta() +dispatch() # Indexed & element change methods insertAfter() @@ -190,19 +172,8 @@ isTopLevel() # Modify methods modifyDown() modifyUp() -modifyShapeDown() -modifyShapeUp() -modifyChange() initialMeta() -# Advanced change methods -setMeta() -setChangeRequestMeta() -dispatch() -batch() -batchAndReturn() -hasDispatched() - # Side-effect methods spy() spyChange() @@ -213,7 +184,6 @@ pipe() # Debug methods log() toConsole() - `; export default () => [ - "Apple", - "Banana", - "Crumpets" - ] -}); +// this is a generic react-sortable-hoc + dataparcels list hoc +// that you can use in your own projects + +const SortableParcelList = ({element, container}) => { + let Container = container || 'div'; + let Element = SortableElement(({parcel, ...rest}) => element(parcel, rest)); + + return SortableContainer(({parcel}) => + {parcel.toArray((elementParcel, index) => )} + ); +}; -const SortableFruitItem = SortableElement(({fruitParcel}) => { - return - {(parcel) =>
+// use the generic react-sortable-hoc + dataparcels list hoc +// to create a fruit-specific sortable list component + +const SortableFruitList = SortableParcelList({ + element: ({parcel}) => + {(parcel) =>
} -
; + }); -const SortableFruitList = SortableContainer(({fruitListParcel}) => { - return
- {fruitListParcel.toArray((fruitParcel, index) => { - return ; - })} -
; +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] }); const FruitListEditor = (props) => { let {fruitListParcel} = props; return
fruitListParcel.move(oldIndex, newIndex)} /> diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md index 577a736a..dbc23857 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md @@ -16,7 +16,7 @@ const NameParcelHoc = ParcelHoc({ valueFromProps: (/* props */) => "Gregor" }); -const FoodEditor = (props) => { +const NameEditor = (props) => { let {nameParcel} = props; return
@@ -30,5 +30,5 @@ const FoodEditor = (props) => {
; }; -export default NameParcelHoc(FoodEditor); +export default NameParcelHoc(NameEditor); ``` diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js new file mode 100644 index 00000000..fa1d9ef8 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js @@ -0,0 +1,11 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/modifiers-and-updaters.md'; +import PageLayout from 'component/PageLayout'; + +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md new file mode 100644 index 00000000..2ddf4178 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md @@ -0,0 +1,47 @@ +import Link from 'component/Link'; +import {Link as HtmlLink} from 'dcme-style'; +import ModifyDownUp from 'examples/ModifyDownUp'; + +# Modifiers and Updaters + +## modifyDown() and modifyUp() + +The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. + +This example shows how a string can be turned into an array for the editor, and during changes the array can be turned back into a string. + + + +```js +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; + +const PathParcelHoc = ParcelHoc({ + name: "pathParcel", + valueFromProps: (/* props */) => "abc.def" +}); + +const PathEditor = (props) => { + let pathArrayParcel = props + .pathParcel + .modifyDown(string => string.split(".")) // turn value into an array on the way down + .modifyUp(array => array.join(".")); // turn value back into a string on the way up + + return
+ {pathArrayParcel.toArray((pathSegmentParcel) => { + return + {(parcel) =>
+ + + + +
} +
; + })} + +
; +}; + +export default PathParcelHoc(PathEditor); + +``` diff --git a/packages/dataparcels-docs/src/pages/parcel-keys.js b/packages/dataparcels-docs/src/pages/parcel-keys.js index 5c2f78ba..d0d07926 100644 --- a/packages/dataparcels-docs/src/pages/parcel-keys.js +++ b/packages/dataparcels-docs/src/pages/parcel-keys.js @@ -1,10 +1,11 @@ // @flow +import type {Node} from 'react'; import React from 'react'; -import {Box, CenteredLanding, Text} from 'dcme-style'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/parcel-keys.md'; +import PageLayout from 'component/PageLayout'; -export default () => - Parcel Keys} - bottom={() => This doesn't exist yet. These docs are still very much under construction.} - /> -; +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/parcel-keys.md b/packages/dataparcels-docs/src/pages/parcel-keys.md new file mode 100644 index 00000000..ea16b373 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/parcel-keys.md @@ -0,0 +1,35 @@ +# Parcel Keys + +Dataparcels automatically gives unique keys to all children of a parent parcel. These can safely be used as unique identifiers for each child parcel, regardless of the child parcel's position within the parent. + +## Keyed parents + +Child Parcels who belong to a keyed data type, such as an object, are given keys that match the keys on the parent data type. + +```js +let value = { + abc: 123, + def: 456 +}; + +let parcel = new Parcel({value}); + +parcel.get('abc').key // key is 'abc' +parcel.get('def').key // key is 'def' +``` + +## Indexed parents + +Child Parcels who belong to a indexed data type, such as an array, are given autogenerated keys when the Parcel is first instanciated. + +```js +let value = [ + 123, + 456 +] + +let parcel = new Parcel({value}); + +parcel.get(0).key // key is '#a' +parcel.get(1).key // key is '#b' +``` diff --git a/packages/dataparcels-docs/src/pages/parcel-meta.js b/packages/dataparcels-docs/src/pages/parcel-meta.js index ed4fdb08..78f90256 100644 --- a/packages/dataparcels-docs/src/pages/parcel-meta.js +++ b/packages/dataparcels-docs/src/pages/parcel-meta.js @@ -1,10 +1,11 @@ // @flow +import type {Node} from 'react'; import React from 'react'; -import {Box, CenteredLanding, Text} from 'dcme-style'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/parcel-meta.md'; +import PageLayout from 'component/PageLayout'; -export default () => - Parcel Meta} - bottom={() => This doesn't exist yet. These docs are still very much under construction.} - /> -; +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/parcel-meta.md b/packages/dataparcels-docs/src/pages/parcel-meta.md new file mode 100644 index 00000000..69c83620 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/parcel-meta.md @@ -0,0 +1,179 @@ +import Link from 'component/Link'; +import {Link as HtmlLink} from 'dcme-style'; +import ParcelMetaConfirmingDeletions from 'examples/ParcelMetaConfirmingDeletions'; +import ParcelMetaChangedValues from 'examples/ParcelMetaChangedValues'; + +# Parcel Meta + +Parcel meta provides the ability to store extra data that pertains to parts of a data shape, such as validation error messages against each of the fields in a form. Each location (unique key path) in a Parcel's value has a corresponding meta object, which defaults to an empty object. + +```js +let value = { + abc: 123, + def: { + ghi: 456 + } +}; + +let parcel = new Parcel({value}); + +// the value above has four locations where meta can be stored: +parcel.meta // returns the meta data object on the top level parcel +parcel.get('abc').meta // returns the meta data object at ['abc'] +parcel.get('def').meta // returns the meta data object at ['def'] +parcel.get('def').get('ghi').meta // returns the meta data object at ['def', 'ghi'] +``` + +There are three main ways to interact with meta on a Parcel: +* The [meta](/api/Parcel#meta) property +* The [setMeta()](/api/Parcel#setMeta) method +* The [initialMeta()](/api/Parcel#initialMeta) method + +Meta is set using a Parcel's [setMeta()](/api/Parcel#setMeta) method, which triggers a change that sets `meta` at the parcel's location. + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel.setMeta({ + abc: 123 +}); +// ^ this triggers a change that sets the parcel's meta to {abc: 123} + +parcel.setMeta({ + def: 456 +}); +// ^ this triggers a change that sets the parcel's meta to {abc: 123, def: 456} +``` + +The [initialMeta()](/api/Parcel#initialMeta) method can also be used to set the initial meta object. + +```js +let parcel = new Parcel({ + value: "abc" +}); + +parcel + .initialMeta({ + abc: 123 + }) + .meta // this returns {abc: 123} initially, but this can change after subsequent calls to setMeta() +``` + +# Examples + +Here are some examples of how meta can be useful. + +## Confirming deletions + +This example shows how to uses meta stored against each element in an array to show a confirmation message with options. + + + +```js +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ExampleHoc from 'component/ExampleHoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ {fruitListParcel.toArray((fruitParcel) => { + return + {(parcel) =>
+ + {parcel.meta.confirming + ? Are you sure? + + + + : } +
} +
; + })} + +
; +}; + +export default FruitListParcelHoc(FruitListEditor); +``` + +### What's going on +* Clicking on an "x" button sets the `meta.confirming` state to `true`, which renders a choice of two buttons. +* "No" sets `meta.confirming` back to false again, while "Yes" calls [delete()](/api/Parcel#delete) method on the Parcel. +* Notice how the meta always relates to the correct element, even if other elements are deleted. + +## Displaying changed values + +This example shows how `initialMeta` can be used to store information for later reference. + + + +```js +import React from 'react'; +import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + firstname: "Robert", + lastname: "Clamps" + }) +}); + +const withOriginalMeta = (parcel) => parcel.initialMeta({ + original: parcel.value +}); + +const PersonEditor = (props) => { + let {personParcel} = props; + + let firstname = personParcel + .get('firstname') + .pipe(withOriginalMeta); + + let lastname = personParcel + .get('lastname') + .pipe(withOriginalMeta); + + return
+ + + {(firstname) =>
+ +
Changed? {firstname.meta.original === firstname.value ? 'No' : 'Yes'}
+
} +
+ + + + {(lastname) =>
+ +
Changed? {lastname.meta.original === lastname.value ? 'No' : 'Yes'}
+
} +
+
; +}; + +export default PersonParcelHoc(PersonEditor); + +``` + +### What's going on +* The `firstname` and `lastname` parcels use the [pipe()](/api/Parcel#pipe) method, which simply passes each parcel through the `withOriginalMeta` function and calls the [initialMeta()](/api/Parcel#initialMeta) function on each of them. +* `initialMeta()` gets the initial value of the parcel and stores it in `meta.original` +* When rendering, `meta.original` is compared against the current `value` to detect changes of the value since the initial render. + +## Validation messages on forms + +... diff --git a/packages/dataparcels-docs/src/pages/shape-updaters.js b/packages/dataparcels-docs/src/pages/shape-updaters.js deleted file mode 100644 index 59897ee2..00000000 --- a/packages/dataparcels-docs/src/pages/shape-updaters.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import React from 'react'; -import {Box, CenteredLanding, Text} from 'dcme-style'; - -export default () => - Shape Updaters} - bottom={() => This doesn't exist yet. These docs are still very much under construction.} - /> -; diff --git a/packages/dataparcels-docs/src/pages/value-updaters.js b/packages/dataparcels-docs/src/pages/value-updaters.js deleted file mode 100644 index 45398ae4..00000000 --- a/packages/dataparcels-docs/src/pages/value-updaters.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import React from 'react'; -import {Box, CenteredLanding, Text} from 'dcme-style'; - -export default () => - Value Updaters} - bottom={() => This doesn't exist yet. These docs are still very much under construction.} - /> -; From ab982dbf14916a0cea8aca7521d0f359cb31183c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 29 Jan 2019 15:24:18 +1100 Subject: [PATCH 091/120] docs: make docs use new slash exports --- packages/dataparcels-docs/src/docs/api/action/Action.md | 4 ++-- .../src/docs/api/changeRequest/ChangeRequest.md | 4 ++-- .../src/docs/api/parcelBoundary/ParcelBoundary.md | 2 +- .../src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md | 2 +- .../dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md | 2 +- .../src/docs/api/parcelShape/ParcelShape.md | 6 +++--- packages/dataparcels-docs/src/examples/EditingArrays.jsx | 3 ++- .../src/examples/EditingArraysFlipMove.jsx | 3 ++- .../src/examples/EditingArraysSortableHoc.jsx | 3 ++- .../dataparcels-docs/src/examples/EditingObjects.jsx | 3 ++- .../src/examples/EditingObjectsBeginner.jsx | 2 +- .../src/examples/ManagingOwnParcelState.jsx | 3 ++- .../src/examples/ParcelBoundaryDebounce.jsx | 3 ++- .../src/examples/ParcelBoundaryForceUpdate.jsx | 3 ++- .../dataparcels-docs/src/examples/ParcelBoundaryHold.jsx | 3 ++- .../dataparcels-docs/src/examples/ParcelBoundaryPure.jsx | 3 ++- .../dataparcels-docs/src/examples/ParcelHocExample.jsx | 2 +- .../src/examples/ParcelHocExampleDelayUntil.jsx | 2 +- .../examples/ParcelHocExampleInitialValueFromProps.jsx | 2 +- .../src/examples/ParcelHocExampleOnChange.jsx | 2 +- .../src/examples/ParcelHocUpdateFromProps.jsx | 2 +- .../src/examples/ParcelHocUpdateFromQueryString.jsx | 4 ++-- .../src/pages/examples/editing-arrays.md | 9 ++++++--- .../src/pages/examples/editing-objects.md | 3 ++- .../src/pages/examples/managing-your-own-parcel-state.md | 3 ++- .../src/pages/examples/parcelboundary-debounce.md | 3 ++- .../src/pages/examples/parcelboundary-forceUpdate.md | 3 ++- .../src/pages/examples/parcelboundary-hold.md | 3 ++- .../src/pages/examples/parcelboundary-pure.md | 3 ++- .../src/pages/examples/parcelhoc-delayuntil.md | 2 +- .../src/pages/examples/parcelhoc-example.md | 2 +- .../src/pages/examples/parcelhoc-onchange.md | 2 +- .../src/pages/examples/parcelhoc-updatefromprops.md | 6 +++--- .../src/pages/examples/parcelhoc-valuefromprops.md | 2 +- packages/dataparcels-docs/src/pages/getting-started.md | 5 +++-- 35 files changed, 64 insertions(+), 45 deletions(-) diff --git a/packages/dataparcels-docs/src/docs/api/action/Action.md b/packages/dataparcels-docs/src/docs/api/action/Action.md index 429ce91d..dde96034 100644 --- a/packages/dataparcels-docs/src/docs/api/action/Action.md +++ b/packages/dataparcels-docs/src/docs/api/action/Action.md @@ -3,8 +3,8 @@ import Link from 'component/Link'; # Action ```js -import {Action} from 'dataparcels'; -import {Action} from 'react-dataparcels'; +import Action from 'dataparcels/Action'; +import Action from 'react-dataparcels/Action'; ``` ```flow diff --git a/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md b/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md index d11090c1..df49d41a 100644 --- a/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md +++ b/packages/dataparcels-docs/src/docs/api/changeRequest/ChangeRequest.md @@ -3,8 +3,8 @@ import Link from 'component/Link'; # ChangeRequest ```js -import {ChangeRequest} from 'dataparcels'; -import {ChangeRequest} from 'react-dataparcels'; +import ChangeRequest from 'dataparcels/ChangeRequest'; +import ChangeRequest from 'react-dataparcels/ChangeRequest'; ``` ```flow diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md b/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md index 6367e66c..b4092b3a 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md @@ -18,7 +18,7 @@ Each ParcelBoundary is passed a Parcel. By default the ParcelBoundary uses pure ParcelBoundaries have an internal action buffer that can hold onto changes as they exit the boundary. These are normally released immediately, but also allow for debouncing changes, or putting a hold on all changes so they can be released later. ```js -import {ParcelBoundary} from 'react-dataparcels'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; ``` ```js diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md index d16c86a5..a730cd30 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md @@ -20,7 +20,7 @@ ParcelBoundaryHocs have an internal action buffer that can hold onto changes as Unlike ParcelBoundary, it cannot use pure rendering. ```js -import {ParcelBoundaryHoc} from 'react-dataparcels'; +import ParcelBoundaryHoc from 'react-dataparcels/ParcelBoundaryHoc'; ``` ```js diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md index 28f4cfa7..0ae0705b 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md @@ -15,7 +15,7 @@ ParcelHoc is a React higher order component. It's job is to provide a parcel as It is recommended that you use ParcelHoc, rather than managing your own Parcel state. ```js -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; ``` ```flow diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md index 98ef8fab..e60eb7a5 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md @@ -14,8 +14,8 @@ These exist to be used with shape updaters, to ParcelShape's methods are a subset of Parcel's methods. ```js -import {ParcelShape} from 'dataparcels'; -import {ParcelShape} from 'react-dataparcels'; +import ParcelShape from 'dataparcels/ParcelShape'; +import ParcelShape from 'react-dataparcels/ParcelShape'; ``` ```flow @@ -34,4 +34,4 @@ let parcelShape = new ParcelShape(123); ParcelShapes are used in a very similar way to [Immutable.js Maps and Lists](https://facebook.github.io/immutable-js/docs/), by calling methods that return new and updated ParcelShapes. -TODO +TODOTODO diff --git a/packages/dataparcels-docs/src/examples/EditingArrays.jsx b/packages/dataparcels-docs/src/examples/EditingArrays.jsx index beaaa130..88b3b7d8 100644 --- a/packages/dataparcels-docs/src/examples/EditingArrays.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArrays.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/EditingArraysFlipMove.jsx b/packages/dataparcels-docs/src/examples/EditingArraysFlipMove.jsx index c378b791..27fe89fc 100644 --- a/packages/dataparcels-docs/src/examples/EditingArraysFlipMove.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArraysFlipMove.jsx @@ -1,6 +1,7 @@ import React from 'react'; import FlipMove from 'react-flip-move'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx index 510e33cc..9eb4a1c3 100644 --- a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import {SortableContainer, SortableElement} from 'react-sortable-hoc'; import ExampleHoc from 'component/ExampleHoc'; diff --git a/packages/dataparcels-docs/src/examples/EditingObjects.jsx b/packages/dataparcels-docs/src/examples/EditingObjects.jsx index 4ad2a24d..19e02fcf 100644 --- a/packages/dataparcels-docs/src/examples/EditingObjects.jsx +++ b/packages/dataparcels-docs/src/examples/EditingObjects.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const PersonParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/EditingObjectsBeginner.jsx b/packages/dataparcels-docs/src/examples/EditingObjectsBeginner.jsx index 14d54079..c331c698 100644 --- a/packages/dataparcels-docs/src/examples/EditingObjectsBeginner.jsx +++ b/packages/dataparcels-docs/src/examples/EditingObjectsBeginner.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; const PersonParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ManagingOwnParcelState.jsx b/packages/dataparcels-docs/src/examples/ManagingOwnParcelState.jsx index f53cadf5..225c4d23 100644 --- a/packages/dataparcels-docs/src/examples/ManagingOwnParcelState.jsx +++ b/packages/dataparcels-docs/src/examples/ManagingOwnParcelState.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import Parcel, {ParcelBoundary} from 'react-dataparcels'; +import Parcel from 'react-dataparcels'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; export default class ManagingOwnParcelState extends React.Component { constructor(props) { diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryDebounce.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryDebounce.jsx index b503f735..b4bf4793 100644 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryDebounce.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryDebounce.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FoodParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryForceUpdate.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryForceUpdate.jsx index 836d89d1..f16e242f 100644 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryForceUpdate.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryForceUpdate.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const ColourParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx index 836ecfaf..6320b2cb 100644 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryHold.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const NameParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx b/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx index 2303954b..7a6f71e6 100644 --- a/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelBoundaryPure.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const PersonParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelHocExample.jsx b/packages/dataparcels-docs/src/examples/ParcelHocExample.jsx index 57def380..6d710503 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocExample.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocExample.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; const WordParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelHocExampleDelayUntil.jsx b/packages/dataparcels-docs/src/examples/ParcelHocExampleDelayUntil.jsx index cd5db144..b73a3ebd 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocExampleDelayUntil.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocExampleDelayUntil.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; const DelayParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelHocExampleInitialValueFromProps.jsx b/packages/dataparcels-docs/src/examples/ParcelHocExampleInitialValueFromProps.jsx index 27bf85b7..2b92672b 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocExampleInitialValueFromProps.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocExampleInitialValueFromProps.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; const WordParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelHocExampleOnChange.jsx b/packages/dataparcels-docs/src/examples/ParcelHocExampleOnChange.jsx index b0e7a5fa..2f909c42 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocExampleOnChange.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocExampleOnChange.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; const WordParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromProps.jsx b/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromProps.jsx index 1fe55058..3c066b3e 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromProps.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromProps.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ExampleHoc from 'component/ExampleHoc'; import {Box} from 'dcme-style'; diff --git a/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromQueryString.jsx b/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromQueryString.jsx index 9d3b0b74..95541a52 100644 --- a/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromQueryString.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelHocUpdateFromQueryString.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; -import {ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; import IsRenderingStaticHtml from 'utils/IsRenderingStaticHtml'; import ReactRouterQueryStringHoc from 'react-cool-storage/lib/ReactRouterQueryStringHoc'; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index 8cf26eeb..97274987 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -9,7 +9,8 @@ Dataparcels has a powerful set of methods for manipulating indexed data types, s ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ @@ -59,7 +60,8 @@ Dataparcels' plays nicely with [react-sortable-hoc](https://github.com/clauderic ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import {SortableContainer, SortableElement} from 'react-sortable-hoc'; const FruitListParcelHoc = ParcelHoc({ @@ -116,7 +118,8 @@ Dataparcels' also plays nicely with [react-flip-move](https://github.com/joshwco ```js import React from 'react'; import FlipMove from 'react-flip-move'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListEditor = (props) => { diff --git a/packages/dataparcels-docs/src/pages/examples/editing-objects.md b/packages/dataparcels-docs/src/pages/examples/editing-objects.md index 23c533b6..8ae4521b 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-objects.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-objects.md @@ -18,7 +18,8 @@ This example demonstrates a pretty typical React setup to do that. ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const PersonParcelHoc = ParcelHoc({ name: "personParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md index a2199a8b..c85420f0 100644 --- a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md +++ b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md @@ -7,7 +7,8 @@ If you don't want to use the ParcelHoc higher order co ```js import React from 'react'; -import Parcel, {ParcelBoundary} from 'react-dataparcels'; +import Parcel from 'react-dataparcels'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; export default class ManagingOwnParcelState extends React.Component { constructor(props) { diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-debounce.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-debounce.md index 51a81e0c..2e44e361 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-debounce.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-debounce.md @@ -9,7 +9,8 @@ This example demonstrates ParcelBoundary's `debounce` feature. The first field i ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const FoodParcelHoc = ParcelHoc({ name: "foodParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-forceUpdate.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-forceUpdate.md index d3d25cef..7cfc3eed 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-forceUpdate.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-forceUpdate.md @@ -11,7 +11,8 @@ The `forceUpdate` option is used to force the ParcelBoundary to update when `opt ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const ColourParcelHoc = ParcelHoc({ name: "colourParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md index 577a736a..9740d822 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-hold.md @@ -9,7 +9,8 @@ This example demonstrates ParcelBoundary's `hold` feature. ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const NameParcelHoc = ParcelHoc({ name: "nameParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md index 74211f7f..d63d1f98 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelboundary-pure.md @@ -11,7 +11,8 @@ Note how the `height` field has a prop of `pure={false}`, and therefore updates ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const PersonParcelHoc = ParcelHoc({ name: "personParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelhoc-delayuntil.md b/packages/dataparcels-docs/src/pages/examples/parcelhoc-delayuntil.md index 3491f876..04efb354 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelhoc-delayuntil.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelhoc-delayuntil.md @@ -9,7 +9,7 @@ This example shows how to delay the creation of a Parcel with `ParcelHoc`. The e ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; const DelayParcelHoc = ParcelHoc({ name: "delayParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelhoc-example.md b/packages/dataparcels-docs/src/pages/examples/parcelhoc-example.md index a8afdf4a..a8578bfd 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelhoc-example.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelhoc-example.md @@ -9,7 +9,7 @@ This example demonstrates a simple usage of `ParcelHoc`. ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; const WordParcelHoc = ParcelHoc({ name: "wordParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelhoc-onchange.md b/packages/dataparcels-docs/src/pages/examples/parcelhoc-onchange.md index 018d5394..358d41e1 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelhoc-onchange.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelhoc-onchange.md @@ -11,7 +11,7 @@ This example demonstrates a `ParcelHoc` with an initial value that originates fr ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; const WordParcelHoc = ParcelHoc({ name: "wordParcel", diff --git a/packages/dataparcels-docs/src/pages/examples/parcelhoc-updatefromprops.md b/packages/dataparcels-docs/src/pages/examples/parcelhoc-updatefromprops.md index cd31edec..809906c2 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelhoc-updatefromprops.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelhoc-updatefromprops.md @@ -28,7 +28,7 @@ When you type in the second input, the ParcelHoc changes and notifies the higher ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; const NameParcelHoc = ParcelHoc({ name: "nameParcel", @@ -86,8 +86,8 @@ The same method can be used to allow a ParcelHoc to be controlled by another oth ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; -import {ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ReactRouterQueryStringHoc from 'react-cool-storage/lib/ReactRouterQueryStringHoc'; import composeWith from 'unmutable/lib/util/composeWith'; diff --git a/packages/dataparcels-docs/src/pages/examples/parcelhoc-valuefromprops.md b/packages/dataparcels-docs/src/pages/examples/parcelhoc-valuefromprops.md index 315679e9..eb93416b 100644 --- a/packages/dataparcels-docs/src/pages/examples/parcelhoc-valuefromprops.md +++ b/packages/dataparcels-docs/src/pages/examples/parcelhoc-valuefromprops.md @@ -9,7 +9,7 @@ This example demonstrates a `ParcelHoc` with an initial value that originates fr ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; const WordParcelHoc = ParcelHoc({ name: "wordParcel", diff --git a/packages/dataparcels-docs/src/pages/getting-started.md b/packages/dataparcels-docs/src/pages/getting-started.md index 8b0298e0..3c5466fe 100644 --- a/packages/dataparcels-docs/src/pages/getting-started.md +++ b/packages/dataparcels-docs/src/pages/getting-started.md @@ -43,7 +43,7 @@ We could do something like this. ```js import React from 'react'; -import {ParcelHoc} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; // PLEASE DON'T USE THIS CODE // THIS CODE IS FOR DEMONSTRAION PURPOSES ONLY @@ -99,7 +99,8 @@ This is the same example with a few improvements added: better rendering perform ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const PersonParcelHoc = ParcelHoc({ name: "personParcel", From 924b0645bda20081f063f869d5f5cb10e45a1ccb Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Tue, 29 Jan 2019 15:59:16 +1100 Subject: [PATCH 092/120] wip --- packages/dataparcels-docs/src/content/API.js | 8 ++++---- packages/dataparcels-docs/src/docs/api/parcel/Parcel.md | 2 +- .../src/docs/api/parcelBoundary/ParcelBoundary.md | 2 +- .../src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md | 2 +- .../src/docs/api/parcelBoundaryHoc/name.md | 2 +- .../dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md | 2 +- .../dataparcels-docs/src/docs/api/parcelHoc/onChange.md | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/dataparcels-docs/src/content/API.js b/packages/dataparcels-docs/src/content/API.js index 02c5f9e9..7bdce536 100644 --- a/packages/dataparcels-docs/src/content/API.js +++ b/packages/dataparcels-docs/src/content/API.js @@ -31,7 +31,7 @@ export default () => name="Parcel" description={ Parcel is a data container. - It's job is to hold your data, split it into smaller parts, and merge changes back together. + Its job is to hold your data, split it into smaller parts, and merge changes back together. } image={IconParcel} /> @@ -39,7 +39,7 @@ export default () => name="ParcelHoc" description={ ParcelHoc is a React higher order component. - It's job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. + Its job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. } image={IconParcelHoc} /> @@ -47,7 +47,7 @@ export default () => name="ParcelBoundary" description={ ParcelBoundary is a React component. - It's job is to optimise rendering performance, and to optionally control the flow of parcel changes. + Its job is to optimise rendering performance, and to optionally control the flow of parcel changes. } image={IconParcelBoundary} /> @@ -55,7 +55,7 @@ export default () => name="ParcelBoundaryHoc" description={ ParcelBoundaryHoc is a React higher order component. - It's job is to control the flow of parcel changes. It is the higher order component version of a ParcelBoundary. + Its job is to control the flow of parcel changes. It is the higher order component version of a ParcelBoundary. } image={IconParcelBoundaryHoc} /> diff --git a/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md b/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md index 501a88e3..babafd03 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/Parcel.md @@ -8,7 +8,7 @@ import IconParcel from 'content/parcel.gif'; {IconParcel} -Parcel is a data container. It's job is to hold your data, split it into smaller parts, and merge changes back together. +Parcel is a data container. Its job is to hold your data, split it into smaller parts, and merge changes back together. If you're using React, you probably won't be instanciating parcels directly. Please see the getting started page to see how to best use Parcels in a React app. diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md b/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md index b4092b3a..ad256c75 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundary/ParcelBoundary.md @@ -11,7 +11,7 @@ import {Box, Message} from 'dcme-style'; {IconParcelBoundary} -ParcelBoundary is a React component. It's job is to optimise rendering performance, and to optionally control the flow of parcel changes. +ParcelBoundary is a React component. Its job is to optimise rendering performance, and to optionally control the flow of parcel changes. Each ParcelBoundary is passed a Parcel. By default the ParcelBoundary uses pure rendering, and will only update when the Parcel's data changes to avoid unnecessary re-rendering. diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md index a730cd30..32126870 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/ParcelBoundaryHoc.md @@ -11,7 +11,7 @@ import {Box, Message} from 'dcme-style'; {IconParcelBoundaryHoc} -ParcelBoundaryHoc is a React higher order component. It's job is to control the flow of parcel changes. It is the higher order component version of a ParcelBoundary. +ParcelBoundaryHoc is a React higher order component. Its job is to control the flow of parcel changes. It is the higher order component version of a ParcelBoundary. Each ParcelBoundaryHoc is given a name, and expects that it will be given Parcel as a prop of the same name. diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/name.md b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/name.md index f65966b5..1e8304cf 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/name.md +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundaryHoc/name.md @@ -4,6 +4,6 @@ import Link from 'component/Link'; name: string | (props: *) => string ``` -The name of the prop that will contain a parcel. +The name of the prop that will contain a parcel. This should correspond with a prop containing a Parcel. The parcel is allowed to be undefined, in which case the ParcelBoundaryHoc will have no effect. diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md index 0ae0705b..40f6c773 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md @@ -10,7 +10,7 @@ import IconParcelHoc from 'content/parcelhoc.gif'; {IconParcelHoc} -ParcelHoc is a React higher order component. It's job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. +ParcelHoc is a React higher order component. Its job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. It is recommended that you use ParcelHoc, rather than managing your own Parcel state. diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/onChange.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/onChange.md index 160dcf8e..5f355d80 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/onChange.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/onChange.md @@ -1,10 +1,10 @@ import Link from 'component/Link'; ```flow -onChange?: (props: Object) => (parcel: Parcel, changeRequest: ChangeRequest) => void // optional +onChange?: (props: Object) => (value: any, changeRequest: ChangeRequest) => void // optional ``` -The `onChange` function is called whenever ParcelHoc changes. It expects to be given a double barrel function. The first function will be passed `props`, and the next is passed the recently-changed Parcel. It is only fired if the value actually changes. +The `onChange` function is called whenever ParcelHoc changes. It expects to be given a double barrel function. The first function will be passed `props`, and the next is passed the new value. It is only fired if the value actually changes. `onChange` is often used to relay changes further up the React DOM heirarchy. This works in a very similar way to [uncontrolled components in React](https://reactjs.org/docs/uncontrolled-components.html). From 9ee8ea54e7d16e9f71297c98a399e5f80feadde6 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 30 Jan 2019 20:06:47 +1100 Subject: [PATCH 093/120] wip --- .../dataparcels-docs/src/examples/ModifyConditional.jsx | 3 ++- packages/dataparcels-docs/src/examples/ModifyDownUp.jsx | 3 ++- .../src/examples/ParcelMetaChangedValues.jsx | 3 ++- .../src/examples/ParcelMetaConfirmingDeletions.jsx | 3 ++- .../dataparcels-docs/src/pages/examples/editing-arrays.md | 2 +- .../dataparcels-docs/src/pages/modifiers-and-updaters.md | 3 ++- packages/dataparcels-docs/src/pages/parcel-meta.md | 6 ++++-- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/dataparcels-docs/src/examples/ModifyConditional.jsx b/packages/dataparcels-docs/src/examples/ModifyConditional.jsx index e2a8dc35..40c6642a 100644 --- a/packages/dataparcels-docs/src/examples/ModifyConditional.jsx +++ b/packages/dataparcels-docs/src/examples/ModifyConditional.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const AgeParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx index 610d75d0..8e0da144 100644 --- a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx +++ b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const PathParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx b/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx index c8b3bb82..d1e5142e 100644 --- a/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelMetaChangedValues.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const PersonParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx b/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx index a3be22c0..f1852c1c 100644 --- a/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx +++ b/packages/dataparcels-docs/src/examples/ParcelMetaConfirmingDeletions.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index 67ee1991..a60524c2 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -84,7 +84,7 @@ const SortableParcelList = ({element, container}) => { // to create a fruit-specific sortable list component const SortableFruitList = SortableParcelList({ - element: ({parcel}) => + element: (parcel) => {(parcel) =>
diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md index 2ddf4178..d810e87b 100644 --- a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md +++ b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md @@ -14,7 +14,8 @@ This example shows how a string can be turned into an array for the editor, and ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const PathParcelHoc = ParcelHoc({ name: "pathParcel", diff --git a/packages/dataparcels-docs/src/pages/parcel-meta.md b/packages/dataparcels-docs/src/pages/parcel-meta.md index 69c83620..30036ae2 100644 --- a/packages/dataparcels-docs/src/pages/parcel-meta.md +++ b/packages/dataparcels-docs/src/pages/parcel-meta.md @@ -73,7 +73,8 @@ This example shows how to uses meta stored against each element in an array to s ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ @@ -121,7 +122,8 @@ This example shows how `initialMeta` can be used to store information for later ```js import React from 'react'; -import {ParcelHoc, ParcelBoundary} from 'react-dataparcels'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; const PersonParcelHoc = ParcelHoc({ name: "personParcel", From 2bd3dd648580f10aead40f72169dedd61d3e0d32 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 30 Jan 2019 21:05:07 +1100 Subject: [PATCH 094/120] add: react-dataparcels-draggable --- ...ableHoc.jsx => EditingArraysDraggable.jsx} | 25 +---- .../src/pages/examples/editing-arrays.md | 38 +++---- .../react-dataparcels-draggable/README.md | 14 +++ .../__test__/Exports-test.js | 9 ++ .../react-dataparcels-draggable/package.json | 32 ++++++ .../src/Draggable.js | 43 ++++++++ .../src/__test__/Draggable-test.js | 99 +++++++++++++++++++ .../react-dataparcels-draggable/src/index.js | 4 + packages/react-dataparcels/package.json | 3 + yarn.lock | 6 +- 10 files changed, 223 insertions(+), 50 deletions(-) rename packages/dataparcels-docs/src/examples/{EditingArraysSortableHoc.jsx => EditingArraysDraggable.jsx} (56%) create mode 100644 packages/react-dataparcels-draggable/README.md create mode 100644 packages/react-dataparcels-draggable/__test__/Exports-test.js create mode 100644 packages/react-dataparcels-draggable/package.json create mode 100644 packages/react-dataparcels-draggable/src/Draggable.js create mode 100644 packages/react-dataparcels-draggable/src/__test__/Draggable-test.js create mode 100644 packages/react-dataparcels-draggable/src/index.js diff --git a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx b/packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx similarity index 56% rename from packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx rename to packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx index 9eb4a1c3..7852b94c 100644 --- a/packages/dataparcels-docs/src/examples/EditingArraysSortableHoc.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import {SortableContainer, SortableElement} from 'react-sortable-hoc'; +import ParcelDraggable from 'react-dataparcels-draggable'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ @@ -13,35 +13,20 @@ const FruitListParcelHoc = ParcelHoc({ ] }); -const SortableFruitItem = SortableElement(({fruitParcel}) => { - return +const SortableFruitList = ParcelDraggable({ + element: (fruitParcel) => {(parcel) =>
} -
; -}); - -const SortableFruitList = SortableContainer(({fruitListParcel}) => { - return
- {fruitListParcel.toArray((fruitParcel, index) => { - return ; - })} -
; +
}); const FruitListEditor = (props) => { let {fruitListParcel} = props; return
- fruitListParcel.move(oldIndex, newIndex)} - /> +
; }; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index 97274987..44c49ba0 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -1,7 +1,7 @@ import Link from 'gatsby-link'; import EditingArrays from 'examples/EditingArrays'; import EditingArraysFlipMove from 'examples/EditingArraysFlipMove'; -import EditingArraysSortableHoc from 'examples/EditingArraysSortableHoc'; +import EditingArraysDraggable from 'examples/EditingArraysDraggable'; Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. @@ -52,17 +52,17 @@ export default FruitListParcelHoc(FruitListEditor); For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. -## Drag and drop with react-sortable-hoc +## Drag and drop with react-dataparcels-draggable -Dataparcels' plays nicely with [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. +Drag and drop is easy using [react-dataparcels-draggable](https://www.npmjs.com/package/react-dataparcels-draggable), which is a slim wrapper around [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. - + ```js import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import {SortableContainer, SortableElement} from 'react-sortable-hoc'; +import ParcelDraggable from 'react-dataparcels-draggable'; const FruitListParcelHoc = ParcelHoc({ name: "fruitListParcel", @@ -73,35 +73,20 @@ const FruitListParcelHoc = ParcelHoc({ ] }); -const SortableFruitItem = SortableElement(({fruitParcel}) => { - return - {(parcel) =>
+const SortableFruitList = ParcelDraggable({ + element: (fruitParcel) => + {(parcel) =>
} -
; -}); - -const SortableFruitList = SortableContainer(({fruitListParcel}) => { - return
- {fruitListParcel.toArray((fruitParcel, index) => { - return ; - })} -
; + }); const FruitListEditor = (props) => { let {fruitListParcel} = props; return
- fruitListParcel.move(oldIndex, newIndex)} - /> +
; }; @@ -120,7 +105,6 @@ import React from 'react'; import FlipMove from 'react-flip-move'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ExampleHoc from 'component/ExampleHoc'; const FruitListEditor = (props) => { let {fruitListParcel} = props; @@ -149,6 +133,6 @@ const FruitListParcelHoc = ParcelHoc({ name: "fruitListParcel" }); -export default FruitListParcelHoc(ExampleHoc(FruitListEditor)); +export default FruitListParcelHoc(FruitListEditor); ``` diff --git a/packages/react-dataparcels-draggable/README.md b/packages/react-dataparcels-draggable/README.md new file mode 100644 index 00000000..8ac5ab51 --- /dev/null +++ b/packages/react-dataparcels-draggable/README.md @@ -0,0 +1,14 @@ +![dataparcels](https://user-images.githubusercontent.com/345320/48319791-4eece200-e666-11e8-8b19-252cd1135ae2.png) + + +[![CircleCI](https://circleci.com/gh/blueflag/dataparcels/tree/master.svg?style=shield)](https://circleci.com/gh/blueflag/dataparcels/tree/master) + +A plugin for [`react-dataparcels`](https://www.npmjs.com/package/react-dataparcels) that adds drag and drop re-ordering of elements, using the wonderful [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). + +## Example + +**[See the example](https://dataparcels.blueflag.codes/examples/editing-arrays)** + +## Packages + +Get [`react-dataparcels-draggable`](https://www.npmjs.com/package/react-dataparcels-draggable). diff --git a/packages/react-dataparcels-draggable/__test__/Exports-test.js b/packages/react-dataparcels-draggable/__test__/Exports-test.js new file mode 100644 index 00000000..03266239 --- /dev/null +++ b/packages/react-dataparcels-draggable/__test__/Exports-test.js @@ -0,0 +1,9 @@ +// @flow + +// dataparcels exports +import Draggable from '../src/index'; +import InternalDraggable from '../src/Draggable'; + +test('index should export Draggable', () => { + expect(Draggable).toBe(InternalDraggable); +}); diff --git a/packages/react-dataparcels-draggable/package.json b/packages/react-dataparcels-draggable/package.json new file mode 100644 index 00000000..af01a4e5 --- /dev/null +++ b/packages/react-dataparcels-draggable/package.json @@ -0,0 +1,32 @@ +{ + "name": "react-dataparcels-draggable", + "version": "0.18.0-2", + "description": "A plugin for react-dataparcels that adds drag and drop re-ordering of elements.", + "main": "lib/index.js", + "license": "UNLICENSED", + "author": "Damien Clarke", + "repository": { + "type": "git", + "url": "git+https://github.com/blueflag/dataparcels.git" + }, + "files": [ + "lib" + ], + "bugs": { + "url": "https://github.com/blueflag/dataparcels/issues" + }, + "private": false, + "scripts": { + "build": "rm -rf lib && NODE_ENV=production babel src --out-dir lib --ignore '**/__test__/*.js'", + "build-all": "yarn build", + "watch": "yarn run build -w" + }, + "dependencies": { + "babel-runtime": "6.23.0", + "react-sortable-hoc": "1.4.0" + }, + "peerDependencies": { + "react": "16.4.2", + "react-dataparcels": "^0.18.0-2" + } +} diff --git a/packages/react-dataparcels-draggable/src/Draggable.js b/packages/react-dataparcels-draggable/src/Draggable.js new file mode 100644 index 00000000..9289c2f3 --- /dev/null +++ b/packages/react-dataparcels-draggable/src/Draggable.js @@ -0,0 +1,43 @@ +// @flow + +import type {ComponentType} from 'react'; +import type {Node} from 'react'; +import type Parcel from 'react-dataparcels'; + +import React from 'react'; +import {SortableContainer} from 'react-sortable-hoc'; +import {SortableElement} from 'react-sortable-hoc'; + +type Config = { + element: (parcel: Parcel, rest: *) => Node, + container?: ComponentType<*> +}; + +type Props = { + parcel: Parcel, + onSortEnd?: ({oldIndex: number, newIndex: number}) => void +}; + +export default ({element, container}: Config) => { + let Container = container || 'div'; + let ConfiguredElement = SortableElement(({parcel, ...rest}) => element(parcel, rest)); + let ConfiguredContainer = SortableContainer(({parcel}) => + {parcel.toArray((elementParcel, index) => )} + ); + + return ({parcel, onSortEnd, ...rest}: Props): Node => { + return { + let {oldIndex, newIndex} = param; + parcel.move(oldIndex, newIndex); + onSortEnd && onSortEnd(param); + }} + {...rest} + />; + }; +}; diff --git a/packages/react-dataparcels-draggable/src/__test__/Draggable-test.js b/packages/react-dataparcels-draggable/src/__test__/Draggable-test.js new file mode 100644 index 00000000..09ddd7ef --- /dev/null +++ b/packages/react-dataparcels-draggable/src/__test__/Draggable-test.js @@ -0,0 +1,99 @@ +// // @flow +import React from 'react'; +import Parcel from 'react-dataparcels'; +import Draggable from '../Draggable'; + +test('Draggable must pass props correctly', () => { + + let handleChange = jest.fn(); + + let parcel = new Parcel({ + value: [1,2,3], + handleChange + }); + + let MyDraggable = Draggable({ + element: () =>
+ }); + + // $FlowFixMe + let wrapper = shallow(, {disableLifecycleMethods: true}); + + // first level in + let props1 = wrapper.props(); + expect(props1.parcel).toBe(parcel); + props1.onSortEnd({oldIndex: 0, newIndex: 2}); + expect(handleChange.mock.calls[0][0].value).toEqual([2,3,1]); + + // second level in + let props2 = wrapper.dive().props(); + expect(props2.parcel).toBe(parcel); + + // third level in + let props3 = wrapper.dive().dive().props(); + expect(props3.children.length).toBe(3); +}); + +test('Draggable must accept onSortEnd and still call internal onSortEnd', () => { + + let handleChange = jest.fn(); + + let parcel = new Parcel({ + value: [1,2,3], + handleChange + }); + + let MyDraggable = Draggable({ + element: () =>
+ }); + + let onSortEnd = jest.fn(); + + // $FlowFixMe + let wrapper = shallow(, {disableLifecycleMethods: true}); + + let props = wrapper.props(); + let sortEndArg = {oldIndex: 0, newIndex: 2}; + + expect(props.parcel).toBe(parcel); + props.onSortEnd(sortEndArg); + expect(handleChange.mock.calls[0][0].value).toEqual([2,3,1]); + expect(onSortEnd.mock.calls[0][0]).toEqual(sortEndArg); +}); + + +test('Draggable must accept additional params and pass them to react-sortable-hoc', () => { + + let parcel = new Parcel({ + value: [1,2,3] + }); + + let MyDraggable = Draggable({ + element: () =>
+ }); + + // $FlowFixMe + let wrapper = shallow(, {disableLifecycleMethods: true}); + + let props = wrapper.props(); + expect(props.woo).toBe(123); +}); + +test('Draggable must render elements and pass parcels to them', () => { + + let value = [1,2,3]; + + let parcel = new Parcel({ + value + }); + + let element = jest.fn(() =>
); + + let MyDraggable = Draggable({ + element + }); + + // $FlowFixMe + let wrapper = mount(); + expect(element.mock.calls.map(call => call[0].value)).toEqual([1,2,3]); +}); diff --git a/packages/react-dataparcels-draggable/src/index.js b/packages/react-dataparcels-draggable/src/index.js new file mode 100644 index 00000000..1a5db795 --- /dev/null +++ b/packages/react-dataparcels-draggable/src/index.js @@ -0,0 +1,4 @@ +// @flow + +import Draggable from './Draggable'; +export default Draggable; diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index 58115fd8..91fb4567 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -25,5 +25,8 @@ "babel-runtime": "6.23.0", "dataparcels": "^0.18.0-2", "unmutable": "^0.39.0" + }, + "peerDependencies": { + "react": "16.4.2" } } diff --git a/yarn.lock b/yarn.lock index 7c2cbccb..d08aeb59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -97,8 +97,8 @@ js-tokens "^3.0.0" "@babel/runtime@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.2.0.tgz#b03e42eeddf5898e00646e4c840fa07ba8dcad7f" + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" dependencies: regenerator-runtime "^0.12.0" @@ -11190,7 +11190,7 @@ react-side-effect@^1.1.0: exenv "^1.2.1" shallowequal "^1.0.1" -react-sortable-hoc@^1.4.0: +react-sortable-hoc@1.4.0, react-sortable-hoc@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-1.4.0.tgz#b477ce700ba755754200a1dabd36e588e2f5608d" dependencies: From cd499e533efc6b6f89345313a427a25af0159fe2 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 30 Jan 2019 21:10:22 +1100 Subject: [PATCH 095/120] amend: rename draggable to drag --- ...aysDraggable.jsx => EditingArraysDrag.jsx} | 4 +-- .../src/pages/examples/editing-arrays.md | 12 ++++----- .../react-dataparcels-draggable/README.md | 4 +-- .../__test__/Exports-test.js | 8 +++--- .../react-dataparcels-draggable/package.json | 2 +- .../src/{Draggable.js => Drag.js} | 0 .../{Draggable-test.js => Drag-test.js} | 26 +++++++++---------- .../react-dataparcels-draggable/src/index.js | 4 +-- 8 files changed, 30 insertions(+), 30 deletions(-) rename packages/dataparcels-docs/src/examples/{EditingArraysDraggable.jsx => EditingArraysDrag.jsx} (91%) rename packages/react-dataparcels-draggable/src/{Draggable.js => Drag.js} (100%) rename packages/react-dataparcels-draggable/src/__test__/{Draggable-test.js => Drag-test.js} (66%) diff --git a/packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx b/packages/dataparcels-docs/src/examples/EditingArraysDrag.jsx similarity index 91% rename from packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx rename to packages/dataparcels-docs/src/examples/EditingArraysDrag.jsx index 7852b94c..9bb43410 100644 --- a/packages/dataparcels-docs/src/examples/EditingArraysDraggable.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArraysDrag.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ParcelDraggable from 'react-dataparcels-draggable'; +import ParcelDrag from 'react-dataparcels-drag'; import ExampleHoc from 'component/ExampleHoc'; const FruitListParcelHoc = ParcelHoc({ @@ -13,7 +13,7 @@ const FruitListParcelHoc = ParcelHoc({ ] }); -const SortableFruitList = ParcelDraggable({ +const SortableFruitList = ParcelDrag({ element: (fruitParcel) => {(parcel) =>
diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index 44c49ba0..7d79f34b 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -1,7 +1,7 @@ import Link from 'gatsby-link'; import EditingArrays from 'examples/EditingArrays'; import EditingArraysFlipMove from 'examples/EditingArraysFlipMove'; -import EditingArraysDraggable from 'examples/EditingArraysDraggable'; +import EditingArraysDrag from 'examples/EditingArraysDrag'; Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. @@ -52,17 +52,17 @@ export default FruitListParcelHoc(FruitListEditor); For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. -## Drag and drop with react-dataparcels-draggable +## Drag and drop with react-dataparcels-drag -Drag and drop is easy using [react-dataparcels-draggable](https://www.npmjs.com/package/react-dataparcels-draggable), which is a slim wrapper around [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. +Drag and drop is easy using [react-dataparcels-drag](https://www.npmjs.com/package/react-dataparcels-drag), which is a slim wrapper around [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. - + ```js import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ParcelDraggable from 'react-dataparcels-draggable'; +import ParcelDrag from 'react-dataparcels-drag'; const FruitListParcelHoc = ParcelHoc({ name: "fruitListParcel", @@ -73,7 +73,7 @@ const FruitListParcelHoc = ParcelHoc({ ] }); -const SortableFruitList = ParcelDraggable({ +const SortableFruitList = ParcelDrag({ element: (fruitParcel) => {(parcel) =>
diff --git a/packages/react-dataparcels-draggable/README.md b/packages/react-dataparcels-draggable/README.md index 8ac5ab51..4e54d20d 100644 --- a/packages/react-dataparcels-draggable/README.md +++ b/packages/react-dataparcels-draggable/README.md @@ -1,6 +1,6 @@ ![dataparcels](https://user-images.githubusercontent.com/345320/48319791-4eece200-e666-11e8-8b19-252cd1135ae2.png) - + [![CircleCI](https://circleci.com/gh/blueflag/dataparcels/tree/master.svg?style=shield)](https://circleci.com/gh/blueflag/dataparcels/tree/master) A plugin for [`react-dataparcels`](https://www.npmjs.com/package/react-dataparcels) that adds drag and drop re-ordering of elements, using the wonderful [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). @@ -11,4 +11,4 @@ A plugin for [`react-dataparcels`](https://www.npmjs.com/package/react-dataparce ## Packages -Get [`react-dataparcels-draggable`](https://www.npmjs.com/package/react-dataparcels-draggable). +Get [`react-dataparcels-drag`](https://www.npmjs.com/package/react-dataparcels-drag). diff --git a/packages/react-dataparcels-draggable/__test__/Exports-test.js b/packages/react-dataparcels-draggable/__test__/Exports-test.js index 03266239..9ed38e32 100644 --- a/packages/react-dataparcels-draggable/__test__/Exports-test.js +++ b/packages/react-dataparcels-draggable/__test__/Exports-test.js @@ -1,9 +1,9 @@ // @flow // dataparcels exports -import Draggable from '../src/index'; -import InternalDraggable from '../src/Draggable'; +import Drag from '../src/index'; +import InternalDrag from '../src/Drag'; -test('index should export Draggable', () => { - expect(Draggable).toBe(InternalDraggable); +test('index should export Drag', () => { + expect(Drag).toBe(InternalDrag); }); diff --git a/packages/react-dataparcels-draggable/package.json b/packages/react-dataparcels-draggable/package.json index af01a4e5..17b927c7 100644 --- a/packages/react-dataparcels-draggable/package.json +++ b/packages/react-dataparcels-draggable/package.json @@ -1,5 +1,5 @@ { - "name": "react-dataparcels-draggable", + "name": "react-dataparcels-drag", "version": "0.18.0-2", "description": "A plugin for react-dataparcels that adds drag and drop re-ordering of elements.", "main": "lib/index.js", diff --git a/packages/react-dataparcels-draggable/src/Draggable.js b/packages/react-dataparcels-draggable/src/Drag.js similarity index 100% rename from packages/react-dataparcels-draggable/src/Draggable.js rename to packages/react-dataparcels-draggable/src/Drag.js diff --git a/packages/react-dataparcels-draggable/src/__test__/Draggable-test.js b/packages/react-dataparcels-draggable/src/__test__/Drag-test.js similarity index 66% rename from packages/react-dataparcels-draggable/src/__test__/Draggable-test.js rename to packages/react-dataparcels-draggable/src/__test__/Drag-test.js index 09ddd7ef..a49b8d1b 100644 --- a/packages/react-dataparcels-draggable/src/__test__/Draggable-test.js +++ b/packages/react-dataparcels-draggable/src/__test__/Drag-test.js @@ -1,9 +1,9 @@ // // @flow import React from 'react'; import Parcel from 'react-dataparcels'; -import Draggable from '../Draggable'; +import Drag from '../Drag'; -test('Draggable must pass props correctly', () => { +test('Drag must pass props correctly', () => { let handleChange = jest.fn(); @@ -12,12 +12,12 @@ test('Draggable must pass props correctly', () => { handleChange }); - let MyDraggable = Draggable({ + let MyDrag = Drag({ element: () =>
}); // $FlowFixMe - let wrapper = shallow(, {disableLifecycleMethods: true}); + let wrapper = shallow(, {disableLifecycleMethods: true}); // first level in let props1 = wrapper.props(); @@ -34,7 +34,7 @@ test('Draggable must pass props correctly', () => { expect(props3.children.length).toBe(3); }); -test('Draggable must accept onSortEnd and still call internal onSortEnd', () => { +test('Drag must accept onSortEnd and still call internal onSortEnd', () => { let handleChange = jest.fn(); @@ -43,14 +43,14 @@ test('Draggable must accept onSortEnd and still call internal onSortEnd', () => handleChange }); - let MyDraggable = Draggable({ + let MyDrag = Drag({ element: () =>
}); let onSortEnd = jest.fn(); // $FlowFixMe - let wrapper = shallow(, {disableLifecycleMethods: true}); + let wrapper = shallow(, {disableLifecycleMethods: true}); let props = wrapper.props(); let sortEndArg = {oldIndex: 0, newIndex: 2}; @@ -62,24 +62,24 @@ test('Draggable must accept onSortEnd and still call internal onSortEnd', () => }); -test('Draggable must accept additional params and pass them to react-sortable-hoc', () => { +test('Drag must accept additional params and pass them to react-sortable-hoc', () => { let parcel = new Parcel({ value: [1,2,3] }); - let MyDraggable = Draggable({ + let MyDrag = Drag({ element: () =>
}); // $FlowFixMe - let wrapper = shallow(, {disableLifecycleMethods: true}); + let wrapper = shallow(, {disableLifecycleMethods: true}); let props = wrapper.props(); expect(props.woo).toBe(123); }); -test('Draggable must render elements and pass parcels to them', () => { +test('Drag must render elements and pass parcels to them', () => { let value = [1,2,3]; @@ -89,11 +89,11 @@ test('Draggable must render elements and pass parcels to them', () => { let element = jest.fn(() =>
); - let MyDraggable = Draggable({ + let MyDrag = Drag({ element }); // $FlowFixMe - let wrapper = mount(); + let wrapper = mount(); expect(element.mock.calls.map(call => call[0].value)).toEqual([1,2,3]); }); diff --git a/packages/react-dataparcels-draggable/src/index.js b/packages/react-dataparcels-draggable/src/index.js index 1a5db795..a5099964 100644 --- a/packages/react-dataparcels-draggable/src/index.js +++ b/packages/react-dataparcels-draggable/src/index.js @@ -1,4 +1,4 @@ // @flow -import Draggable from './Draggable'; -export default Draggable; +import Drag from './Drag'; +export default Drag; From e54df3fa7e557ce0109e19c1d606be256f6cdae1 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 30 Jan 2019 21:15:34 +1100 Subject: [PATCH 096/120] amend: rename drag folder --- .../README.md | 0 .../__test__/Exports-test.js | 0 .../package.json | 0 .../src/Drag.js | 0 .../src/__test__/Drag-test.js | 0 .../src/index.js | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/README.md (100%) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/__test__/Exports-test.js (100%) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/package.json (100%) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/src/Drag.js (100%) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/src/__test__/Drag-test.js (100%) rename packages/{react-dataparcels-draggable => react-dataparcels-drag}/src/index.js (100%) diff --git a/packages/react-dataparcels-draggable/README.md b/packages/react-dataparcels-drag/README.md similarity index 100% rename from packages/react-dataparcels-draggable/README.md rename to packages/react-dataparcels-drag/README.md diff --git a/packages/react-dataparcels-draggable/__test__/Exports-test.js b/packages/react-dataparcels-drag/__test__/Exports-test.js similarity index 100% rename from packages/react-dataparcels-draggable/__test__/Exports-test.js rename to packages/react-dataparcels-drag/__test__/Exports-test.js diff --git a/packages/react-dataparcels-draggable/package.json b/packages/react-dataparcels-drag/package.json similarity index 100% rename from packages/react-dataparcels-draggable/package.json rename to packages/react-dataparcels-drag/package.json diff --git a/packages/react-dataparcels-draggable/src/Drag.js b/packages/react-dataparcels-drag/src/Drag.js similarity index 100% rename from packages/react-dataparcels-draggable/src/Drag.js rename to packages/react-dataparcels-drag/src/Drag.js diff --git a/packages/react-dataparcels-draggable/src/__test__/Drag-test.js b/packages/react-dataparcels-drag/src/__test__/Drag-test.js similarity index 100% rename from packages/react-dataparcels-draggable/src/__test__/Drag-test.js rename to packages/react-dataparcels-drag/src/__test__/Drag-test.js diff --git a/packages/react-dataparcels-draggable/src/index.js b/packages/react-dataparcels-drag/src/index.js similarity index 100% rename from packages/react-dataparcels-draggable/src/index.js rename to packages/react-dataparcels-drag/src/index.js From 088d77fc995807191e795437f876fd70076ad6d9 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Wed, 30 Jan 2019 22:29:32 +1100 Subject: [PATCH 097/120] add: throw error if non indexed type provided to drag --- packages/react-dataparcels-drag/src/Drag.js | 3 +++ .../src/__test__/Drag-test.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/packages/react-dataparcels-drag/src/Drag.js b/packages/react-dataparcels-drag/src/Drag.js index 9289c2f3..43fdfa90 100644 --- a/packages/react-dataparcels-drag/src/Drag.js +++ b/packages/react-dataparcels-drag/src/Drag.js @@ -30,6 +30,9 @@ export default ({element, container}: Config) => { ); return ({parcel, onSortEnd, ...rest}: Props): Node => { + if(!parcel.isIndexed()) { + throw new Error(`react-dataparcels-drag's parcel prop must be of type indexed`); + } return { diff --git a/packages/react-dataparcels-drag/src/__test__/Drag-test.js b/packages/react-dataparcels-drag/src/__test__/Drag-test.js index a49b8d1b..8cffa502 100644 --- a/packages/react-dataparcels-drag/src/__test__/Drag-test.js +++ b/packages/react-dataparcels-drag/src/__test__/Drag-test.js @@ -34,6 +34,22 @@ test('Drag must pass props correctly', () => { expect(props3.children.length).toBe(3); }); +test('Drag should throw if parcel is not indexed', () => { + + let parcel = new Parcel({ + value: {abc: 123} + }); + + let MyDrag = Drag({ + element: () =>
+ }); + + expect(() => { + // $FlowFixMe + shallow(, {disableLifecycleMethods: true}); + }).toThrow(`react-dataparcels-drag's parcel prop must be of type indexed`); +}); + test('Drag must accept onSortEnd and still call internal onSortEnd', () => { let handleChange = jest.fn(); From a1e8cebb6f5ae972ec0aeb640673617127a0317a Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 09:21:13 +1100 Subject: [PATCH 098/120] add: ability to se sortable props via config --- packages/react-dataparcels-drag/src/Drag.js | 3 +- .../src/__test__/Drag-test.js | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/react-dataparcels-drag/src/Drag.js b/packages/react-dataparcels-drag/src/Drag.js index 43fdfa90..bccba709 100644 --- a/packages/react-dataparcels-drag/src/Drag.js +++ b/packages/react-dataparcels-drag/src/Drag.js @@ -18,7 +18,7 @@ type Props = { onSortEnd?: ({oldIndex: number, newIndex: number}) => void }; -export default ({element, container}: Config) => { +export default ({element, container, ...configRest}: Config) => { let Container = container || 'div'; let ConfiguredElement = SortableElement(({parcel, ...rest}) => element(parcel, rest)); let ConfiguredContainer = SortableContainer(({parcel}) => @@ -40,6 +40,7 @@ export default ({element, container}: Config) => { parcel.move(oldIndex, newIndex); onSortEnd && onSortEnd(param); }} + {...configRest} {...rest} />; }; diff --git a/packages/react-dataparcels-drag/src/__test__/Drag-test.js b/packages/react-dataparcels-drag/src/__test__/Drag-test.js index 8cffa502..beebed12 100644 --- a/packages/react-dataparcels-drag/src/__test__/Drag-test.js +++ b/packages/react-dataparcels-drag/src/__test__/Drag-test.js @@ -78,7 +78,7 @@ test('Drag must accept onSortEnd and still call internal onSortEnd', () => { }); -test('Drag must accept additional params and pass them to react-sortable-hoc', () => { +test('Drag must accept additional props and pass them to react-sortable-hoc as props', () => { let parcel = new Parcel({ value: [1,2,3] @@ -95,6 +95,42 @@ test('Drag must accept additional params and pass them to react-sortable-hoc', ( expect(props.woo).toBe(123); }); +test('Drag must accept additional config and pass them to react-sortable-hoc as props', () => { + + let parcel = new Parcel({ + value: [1,2,3] + }); + + let MyDrag = Drag({ + element: () =>
, + woo: 123 + }); + + // $FlowFixMe + let wrapper = shallow(, {disableLifecycleMethods: true}); + + let props = wrapper.props(); + expect(props.woo).toBe(123); +}); + +test('Drag must prefer props over config', () => { + + let parcel = new Parcel({ + value: [1,2,3] + }); + + let MyDrag = Drag({ + element: () =>
, + woo: 123 + }); + + // $FlowFixMe + let wrapper = shallow(, {disableLifecycleMethods: true}); + + let props = wrapper.props(); + expect(props.woo).toBe(456); +}); + test('Drag must render elements and pass parcels to them', () => { let value = [1,2,3]; From d59be3b05d6278b9515f371b045cc781c6a68279 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 09:24:46 +1100 Subject: [PATCH 099/120] build: enforce coverage --- lerna.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 55ba91a5..b1e030da 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,15 @@ "lerna": "2.9.0", "npmClient": "yarn", "useWorkspaces": true, - "version": "0.18.0-2" + "version": "0.18.0-2", + "jest": { + "coverageThreshold": { + "global": { + "branches": 90, + "functions": 90, + "lines": 90, + "statements": 90 + } + } + } } From bc3ebfae561ecf3bcc10b1c6da4732b619fd324e Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 09:32:54 +1100 Subject: [PATCH 100/120] amend: put jest config in the right place --- jest.config.js | 10 +++++++++- lerna.json | 12 +----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/jest.config.js b/jest.config.js index 96733b5f..b695422a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,5 +8,13 @@ module.exports = { "!packages/dataparcels-docs/**" ], testMatch: ["**/__test__/**/*-test.js?(x)"], - testURL: 'http://localhost' + testURL: 'http://localhost', + coverageThreshold: { + global: { + branches: 90, + functions: 90, + lines: 90, + statements: 90 + } + } }; diff --git a/lerna.json b/lerna.json index b1e030da..55ba91a5 100644 --- a/lerna.json +++ b/lerna.json @@ -2,15 +2,5 @@ "lerna": "2.9.0", "npmClient": "yarn", "useWorkspaces": true, - "version": "0.18.0-2", - "jest": { - "coverageThreshold": { - "global": { - "branches": 90, - "functions": 90, - "lines": 90, - "statements": 90 - } - } - } + "version": "0.18.0-2" } From 47ede29763307daf34f1e610bce5c3b383cbf416 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 09:37:19 +1100 Subject: [PATCH 101/120] docs: add note about usage --- packages/dataparcels-docs/src/pages/examples/editing-arrays.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md index 7d79f34b..cfb97a13 100644 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md @@ -56,6 +56,8 @@ For the full list of methods you can use on indexed data types, see + {(parcel) =>
From 50c1b8b7293712ff1b061c21d0c03fcd506789bd Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 12:48:50 +1100 Subject: [PATCH 103/120] add: remove value updater error in favour of warning --- packages/dataparcels/src/errors/Errors.js | 1 - .../dataparcels/src/util/ValidateValueUpdater.js | 5 ++--- .../__test__/TestValidateValueUpdater-testUtil.js | 13 ++++++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/dataparcels/src/errors/Errors.js b/packages/dataparcels/src/errors/Errors.js index 7175ad88..4b1c3699 100644 --- a/packages/dataparcels/src/errors/Errors.js +++ b/packages/dataparcels/src/errors/Errors.js @@ -2,6 +2,5 @@ export const ReadOnlyError = () => new Error(`This property is read-only`); export const ReducerInvalidActionError = (actionType: string) => new Error(`"${actionType}" is not a valid action`); -export const UnsafeValueUpdaterError = () => new Error(`Value updaters can only pass collections through if the collection is unchanged by the updater. Consider using a shape updater method (e.g. Shape()) for updating collections.`); export const ChangeRequestUnbasedError = () => new Error(`ChangeRequest data cannot be accessed before calling changeRequest._setBaseParcel()`); export const ShapeUpdaterNonShapeChildError = () => new Error(`Every child value on a collection returned from a shape updater must be a ParcelShape`); diff --git a/packages/dataparcels/src/util/ValidateValueUpdater.js b/packages/dataparcels/src/util/ValidateValueUpdater.js index a0a21768..ed006a2f 100644 --- a/packages/dataparcels/src/util/ValidateValueUpdater.js +++ b/packages/dataparcels/src/util/ValidateValueUpdater.js @@ -1,11 +1,10 @@ // @flow import isParentValue from '../parcelData/isParentValue'; -import {UnsafeValueUpdaterError} from '../errors/Errors'; import equals from 'unmutable/lib/equals'; export default (value: any, updatedValue: any) => { - if(isParentValue(value) && isParentValue(updatedValue) && !equals(value)(updatedValue)) { - throw UnsafeValueUpdaterError(); + if(process.env.NODE_ENV !== 'production' && isParentValue(value) && isParentValue(updatedValue) && !equals(value)(updatedValue)) { + console.warn(`Warning: please ensure you do not change the shape of the value, as changing the data shape or moving children within the data shape can cause dataparcels to misplace its keying and meta information!`); /* eslint-disable-line */ } }; diff --git a/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js b/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js index 4e193d8a..2a05942d 100644 --- a/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js +++ b/packages/dataparcels/src/util/__test__/TestValidateValueUpdater-testUtil.js @@ -1,9 +1,20 @@ // @flow +/* eslint-disable */ export default (expect: Function, test: Function) => { + + // $FlowFixMe + console.warn = jest.fn(); + expect(() => test(123, _ => _)).not.toThrowError(); expect(() => test(123, () => [])).not.toThrowError(); expect(() => test([], () => 123)).not.toThrowError(); expect(() => test([1], _ => _)).not.toThrowError(); - expect(() => test([1], () => [2])).toThrowError('Value updaters'); + + expect(console.warn).not.toHaveBeenCalled(); + + test([1], () => [2]); + + expect(console.warn).toHaveBeenCalled(); + expect(console.warn.mock.calls[0][0]).toBe(`Warning: please ensure you do not change the shape of the value, as changing the data shape or moving children within the data shape can cause dataparcels to misplace its keying and meta information!`); }; From 1e4d034614056ad69c3ed1d31cc5c62e672256ce Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 12:49:01 +1100 Subject: [PATCH 104/120] docs: update updater docs --- .../src/docs/api/parcel/modifyDown.md | 2 +- .../src/docs/api/parcel/modifyShapeDown.md | 13 ------ .../src/docs/api/parcel/modifyShapeUp.md | 16 ------- .../src/docs/api/parcel/modifyUp.md | 2 +- .../src/docs/api/parcel/updateShapeIn.md | 13 ------ .../src/docs/api/parcelShape/ParcelShape.md | 2 +- .../src/docs/notes/ShapeUpdater.md | 13 ------ .../src/docs/notes/ValueUpdater.md | 46 +++++++++++++++---- 8 files changed, 41 insertions(+), 66 deletions(-) delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md delete mode 100644 packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md delete mode 100644 packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md index f6628d7b..4470b098 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyDown.md @@ -22,4 +22,4 @@ It does not trigger any changes of its own, it just modifies the values that pas The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. - + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md deleted file mode 100644 index 0a5f592b..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeDown.md +++ /dev/null @@ -1,13 +0,0 @@ -import Link from 'component/Link'; -import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; -import {Box, Link as HtmlLink, Message} from 'dcme-style'; - -```flow -modifyShapeDown(updater: ShapeUpdater): Parcel - -type ShapeUpdater = (parcelShape: ParcelShape) => any -``` - -The `modifyShapeDown()` method is an advanced version of modifyDown(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. - - diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md deleted file mode 100644 index fc8ab443..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyShapeUp.md +++ /dev/null @@ -1,16 +0,0 @@ -import Link from 'component/Link'; -import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; -import {Box, Link as HtmlLink, Message} from 'dcme-style'; - -```flow -modifyShapeUp(updater: ShapeUpdater): Parcel - -type ShapeUpdater = (parcelShape: ParcelShape) => any -``` - -The `modifyShapeUp()` method is an advanced version of modifyUp(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. - -Additionally if `updater` returns nothing (undefined), the change will be cancelled and will not propagate up any further. -If you want to legitimately return a value of `undefined` and continue to propagate the change request, return `new ParcelShape()` instead. - - diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md index 139f3669..a9a1f92e 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md @@ -29,4 +29,4 @@ It does not trigger any changes of its own, but awaits a change from below. Valu The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. - + diff --git a/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md b/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md deleted file mode 100644 index 25848c1b..00000000 --- a/packages/dataparcels-docs/src/docs/api/parcel/updateShapeIn.md +++ /dev/null @@ -1,13 +0,0 @@ -import Link from 'component/Link'; -import ShapeUpdater from 'docs/notes/ShapeUpdater.md'; -import {Box, Link as HtmlLink, Message} from 'dcme-style'; - -```flow -updateShapeIn(keyPath: Array, updater: ShapeUpdater): void // only on ParentParcels - -type ShapeUpdater = (parcelShape: ParcelShape) => any -``` - -The `updateShapeIn()` method is an advanced version of updateIn(). It provides a ParcelShape containing the value to update. It expects either a ParcelShape or a value to be returned. If a value is returned, and if the returned value has children, then those children *must* all be ParcelShapes. - - diff --git a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md index e57fa838..90e436eb 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md +++ b/packages/dataparcels-docs/src/docs/api/parcelShape/ParcelShape.md @@ -10,7 +10,7 @@ import IconParcel from 'content/parcelshape.gif'; ParcelShape is a data container very similar to a Parcel but without the automatic data binding. All it does is contain data, no strings attached, and provide methods for you to alter its data. -These exist to be used with shape updaters, to provide a safe way to alter the shape of data in a Parcel. +These exist to be used with updater methods, such as Parcel.modifyDown, to provide a safe way to alter the shape of data in a Parcel. ParcelShape's methods are a subset of Parcel's methods. ```js diff --git a/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md b/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md deleted file mode 100644 index a145fd54..00000000 --- a/packages/dataparcels-docs/src/docs/notes/ShapeUpdater.md +++ /dev/null @@ -1,13 +0,0 @@ -import Link from 'component/Link'; -import {Box, Link as HtmlLink, Message} from 'dcme-style'; -prop alt - -#### Limitations - -This method accepts a **shape updater**. Shape updaters are designed to allow collections with deep values to be altered, while also allowing Dataparcels to internally keep track of the changes that are made. - -Consider using for simple changes that don't require the shape of the data to be changed. - - - See modifiers and updaters for more info and explanations. - diff --git a/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md b/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md index f6239b4f..4d9bb66e 100644 --- a/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md +++ b/packages/dataparcels-docs/src/docs/notes/ValueUpdater.md @@ -1,15 +1,45 @@ import Link from 'component/Link'; import {Box, Link as HtmlLink, Message} from 'dcme-style'; -prop alt -#### Limitations +### Please be careful -This method accepts a **value updater**. Value updaters are great for updating primitive data types and data types that have no children, but cannot be used to update the *shape* of the data. -When a value updater receives a collection, it must either pass it through unchanged, or turn it into a data type that has no children. +This method is safe to use in most cases, but in some cases it should not be used: -If you need to update the shape of the data, consider using . +- If the updater gives you a primitive value or childless value, you can return anything. +- If the updater gives you a value that has children, you can always return a primitive value or childless value. +- If the updater gives you a value that has children, you can return a value with children **only if the shape hasn't changed**. - - See modifiers and updaters for more info and explanations. - +Please ensure you do not change the shape of the value, as changing the data shape or moving children within the data shape can cause dataparcels to misplace its keying and meta information! +Dataparcels stores data against each part of a deep value's data structure, so it can only let you change the value if you promise not to alter the shape. + +```js +// example updaters +string => string + "!" // good +string => [string] // good +date => date.toString() // good +array => array.join(".") // good +array => array.map(number => number + 1) // good, shape is still the same + +array => array.slice(0,2) // bad, shape has changed if array is longer that 2! +array => array.reverse() // bad, shape has changed because items have moved around! +``` + +If you need to update the shape of the data, you can do so using `dataparcels/shape`. +The `shape` function will wrap your Parcel's data in a ParcelShape which allows for safe shape editing. See ParcelShape for more details. + +```js +import shape from 'dataparcels/shape'; + +let parcel = new Parcel({ + value: [1,2,3] +}); + +let modifiedParcel = parcel.modifyDown(shape(parcelShape => parcelShape + .push("foo") + .push("bar") + .setMeta({ + cool: true + }) +)); +``` From ddb44c0aad186eb38fdf105d502b4edf05ba3586 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 20:08:17 +1100 Subject: [PATCH 105/120] docs: add features section --- packages/dataparcels-docs/src/pages/index.js | 25 +++++++++------- packages/dataparcels-docs/src/pages/index.md | 31 ++++++++++++++++++-- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/packages/dataparcels-docs/src/pages/index.js b/packages/dataparcels-docs/src/pages/index.js index c58d9c84..6dc92c52 100644 --- a/packages/dataparcels-docs/src/pages/index.js +++ b/packages/dataparcels-docs/src/pages/index.js @@ -8,6 +8,7 @@ import PageLayout from 'component/PageLayout'; import API from 'content/API'; import IconParcel from 'content/parcelinverted.gif'; import APIExamples from 'content/APIExamples.md'; +import APINavigation from 'component/APINavigation'; export default () => @@ -35,21 +36,23 @@ export default () => } - nav={() => - What is it? - Getting Started - Examples - API - API Examples - } + nav={() => + + What is it? + Getting Started + + + Features + - Data editing + - UI behaviour + - Data synchronisation + + + } /> API - API Examples - - - diff --git a/packages/dataparcels-docs/src/pages/index.md b/packages/dataparcels-docs/src/pages/index.md index 9a4d47d6..0d24b935 100644 --- a/packages/dataparcels-docs/src/pages/index.md +++ b/packages/dataparcels-docs/src/pages/index.md @@ -1,7 +1,6 @@ import Link from 'gatsby-link'; import API from 'content/API'; import {Divider, Grid, GridItem, Text} from 'dcme-style'; -import Examples from 'content/Examples.md'; ## What is it? @@ -18,6 +17,32 @@ It's designed for use with [React](https://reactjs.org/), and comes with compone Get started with dataparcels, installation instructions and a first example. -## Examples +## Features - +### 1. Data editing + +Data editing is the ability to manipulate data based on user input, in a way that's expressive to code. This includes: +- Data traversal +- Merging partial changes into larger data structures +- Binding data to inputs +- Methods for working with indexed data types such as arrays +- Automatic unique keying of array elements +- Ability to modify data from its original format to make it suitable for the UI + +### 2. UI behaviour + +UI behaviour covers features that help the user interact with the data. This includes: +- Submit buttons for forms +- Validation on user input +- Confirmation on important actions such as deleting +- Selections of one or more items +- Drag and drop sorting of arrays of items +- Debouncing changes for good application performace +- Pure rendering for good rendering performace + +### 3. Data synchronisation + +Data synchronisation is how dataparcels interacts with related pieces of external data. This includes: +- Setting up Parcels as a slave to higher state, such as the query string +- Coping with sending failable changes, such as saving data to a server +- Caching unsaved changes From 11942a5966c39f82380a474b1e802d6163c247f0 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Thu, 31 Jan 2019 20:45:11 +1100 Subject: [PATCH 106/120] docs: fix link --- packages/dataparcels-docs/src/pages/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataparcels-docs/src/pages/index.md b/packages/dataparcels-docs/src/pages/index.md index 0d24b935..da988d2d 100644 --- a/packages/dataparcels-docs/src/pages/index.md +++ b/packages/dataparcels-docs/src/pages/index.md @@ -43,6 +43,6 @@ It's designed for use with [React](https://reactjs.org/), and comes with compone ### 3. Data synchronisation Data synchronisation is how dataparcels interacts with related pieces of external data. This includes: -- Setting up Parcels as a slave to higher state, such as the query string +- Setting up a Parcel as a slave to higher state, such as the query string - Coping with sending failable changes, such as saving data to a server - Caching unsaved changes From deb1630b43372342c9252a6238320ab0c5d944b9 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Fri, 1 Feb 2019 19:53:20 +1100 Subject: [PATCH 107/120] docs: more docs --- .../dataparcels-docs/src/content/Examples.md | 8 - .../src/docs/api/parcel/ParcelAfter.md | 4 +- .../src/docs/api/parcel/key.md | 2 +- .../src/docs/api/parcelHoc/ParcelHoc.md | 2 +- .../src/examples/EditingArrays.jsx | 1 + .../dataparcels-docs/src/layouts/index.scss | 5 +- .../dataparcels-docs/src/pages/api/Parcel.jsx | 12 +- .../src/pages/data-editing.js | 11 ++ .../src/pages/data-editing.md | 180 ++++++++++++++++++ .../src/pages/examples/editing-arrays.js | 9 - .../src/pages/examples/editing-arrays.md | 147 -------------- .../src/pages/examples/editing-objects.js | 9 - .../src/pages/examples/editing-objects.md | 71 ------- .../managing-your-own-parcel-state.js | 9 - .../managing-your-own-parcel-state.md | 44 ----- .../src/pages/getting-started.md | 15 +- packages/dataparcels-docs/src/pages/index.md | 19 +- .../src/pages/ui-behaviour.js | 11 ++ .../src/pages/ui-behaviour.md | 22 +++ 19 files changed, 257 insertions(+), 324 deletions(-) delete mode 100644 packages/dataparcels-docs/src/content/Examples.md create mode 100644 packages/dataparcels-docs/src/pages/data-editing.js create mode 100644 packages/dataparcels-docs/src/pages/data-editing.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-arrays.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-arrays.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-objects.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-objects.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md create mode 100644 packages/dataparcels-docs/src/pages/ui-behaviour.js create mode 100644 packages/dataparcels-docs/src/pages/ui-behaviour.md diff --git a/packages/dataparcels-docs/src/content/Examples.md b/packages/dataparcels-docs/src/content/Examples.md deleted file mode 100644 index 94323645..00000000 --- a/packages/dataparcels-docs/src/content/Examples.md +++ /dev/null @@ -1,8 +0,0 @@ -import Link from 'gatsby-link'; - -* Editing objects -* Editing arrays (including drag & drop) -* Storing parcel state in the query string -* Confirming deletions -* Debouncing inputs -* Managing your own parcel state diff --git a/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md b/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md index 037fcdc7..798acf09 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md @@ -1,5 +1,5 @@ -import Examples from 'content/Examples.md'; +import Link from 'gatsby-link'; ### Examples - +Many examples can be found on the data editing page. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/key.md b/packages/dataparcels-docs/src/docs/api/parcel/key.md index dde72b43..45e53fd0 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/key.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/key.md @@ -6,7 +6,7 @@ key: string Returns the Parcel's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. -Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated in the Editing Arrays example. +Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated here. ```js let value = { diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md index 40f6c773..39abeba8 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md @@ -12,7 +12,7 @@ import IconParcelHoc from 'content/parcelhoc.gif'; ParcelHoc is a React higher order component. Its job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. -It is recommended that you use ParcelHoc, rather than managing your own Parcel state. +It is recommended that you use ParcelHoc, rather than managing your own Parcel state. ```js import ParcelHoc from 'react-dataparcels/ParcelHoc'; diff --git a/packages/dataparcels-docs/src/examples/EditingArrays.jsx b/packages/dataparcels-docs/src/examples/EditingArrays.jsx index 88b3b7d8..4c576725 100644 --- a/packages/dataparcels-docs/src/examples/EditingArrays.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArrays.jsx @@ -23,6 +23,7 @@ const FruitListEditor = (props) => { + key {fruitParcel.key}
} ; })} diff --git a/packages/dataparcels-docs/src/layouts/index.scss b/packages/dataparcels-docs/src/layouts/index.scss index 907824f4..05c03937 100644 --- a/packages/dataparcels-docs/src/layouts/index.scss +++ b/packages/dataparcels-docs/src/layouts/index.scss @@ -35,7 +35,10 @@ @include DcmeBulletList; @include DcmeButton; @include DcmeCenteredLanding; -@include DcmeDivider; +@include DcmeDivider { + border-top: 1px solid #CCC; + margin: 5rem 0 4rem; +} @include DcmeGrid; @include DcmeImage { &-logo { diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 4a14f557..b4a6f084 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -119,12 +119,6 @@ key id path -# Spread methods -spread() -spreadDOM() -onChange() -onChangeDOM() - # Branch methods get() getIn() @@ -132,6 +126,12 @@ children() toObject() toArray() +# Input binding methods +spread() +spreadDOM() +onChange() +onChangeDOM() + # Child methods isFirst() isLast() diff --git a/packages/dataparcels-docs/src/pages/data-editing.js b/packages/dataparcels-docs/src/pages/data-editing.js new file mode 100644 index 00000000..887befd8 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/data-editing.js @@ -0,0 +1,11 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/data-editing.md'; +import PageLayout from 'component/PageLayout'; + +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/data-editing.md b/packages/dataparcels-docs/src/pages/data-editing.md new file mode 100644 index 00000000..e08ae7f3 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/data-editing.md @@ -0,0 +1,180 @@ +import Link from 'gatsby-link'; +import EditingObjects from 'examples/EditingObjects'; +import EditingArrays from 'examples/EditingArrays'; +import ManagingOwnParcelState from 'examples/ManagingOwnParcelState'; + +# Data Editing + +Data editing is the ability to manipulate data based on user input, in a way that's expressive to code. + +The core of dataparcels' flexible data editing capabilities come from its Parcel class and methods. It provides methods to let you **traverse data structures** and **bind data to inputs**, so each input is connected to a specific piece of data in the Parcel. Any changes that occur in each input are propagated back to the top level Parcel, which takes care of **merging partial changes** back into the original data structure. + +Say we want to allow the user to edit the fields in the following data structure: + +```js +{ + firstname: "Robert", + lastname: "Clamps", + address: { + postcode: "1234" + } +} +``` + +This example demonstrates a pretty typical React setup to do that. + + + +```js +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + firstname: "Robert", + lastname: "Clamps", + address: { + postcode: "1234" + } + }) +}); + +const PersonEditor = (props) => { + let {personParcel} = props; + return
+ + + {(firstname) => } + + + + + {(lastname) => } + + + + + {(postcode) => } + +
; +}; + +export default PersonParcelHoc(PersonEditor); + +``` + +### What's going on + +* `react-dataparcels` is imported. +* It stores the data in a ParcelHoc higher order component, which creates and stores a Parcel in state, and passes it down as props. +* The `.get()` and `getIn()` methods are used on the Parcel to create smaller parcels containing just `firstname`, `lastname` and `postcode` respectively. +* It uses the ParcelBoundary React component to avoid needless re-rendering. This isn't *required*, but it is very recommended. +* Finally `.spreadDOM()` is used to provide the `value` and `onChange` props to the `input` elements. + +For the full list of methods you can use to traverse and change Parcels, see Branch Methods, Input Binding Methods and Change Methods in the Parcel API reference. + +## Indexed data types + +Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. + +Notice how items in the array are given **automatic unique keys**, displayed under each input as `#a`, `#b` ..., which can be used by React to identify each element regardless of how the elements move around. + + + +```js +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import ExampleHoc from 'component/ExampleHoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ {fruitListParcel.toArray((fruitParcel) => { + return + {(parcel) =>
+ + + + + + key {fruitParcel.key} +
} +
; + })} + +
; +}; + +export default FruitListParcelHoc(FruitListEditor); +``` + +### What's going on + +* `fruitListParcel` contains an array. +* `Parcel.toArray()` is used to iterate over the Parcel's elements, and it is passed a `mapper` function to return React elements. +* Each element parcel's `key` property is used to uniquely key each React element. +* `ParcelBoundary` is used to ensure great rendering performance. + +For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. + +## Modifying data + +Will be added soon. + +## Managing your own Parcel state + +If you don't want to use the ParcelHoc higher order component and would prefer to manage your Parcel's state yourself, this example deomstrates how. + +This example also serves as an indication on how you might use `dataparcels` with something other than React. + + + +```js +import React from 'react'; +import Parcel from 'react-dataparcels'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; + +export default class ManagingOwnParcelState extends React.Component { + constructor(props) { + super(props); + + let personParcel = new Parcel({ + value: { + firstname: "Robert", + lastname: "Clamps" + }, + handleChange: (personParcel) => this.setState({personParcel}) + }); + + this.state = {personParcel}; + } + + render() { + let {personParcel} = this.state; + return
+ + + {(firstname) => } + + + + + {(lastname) => } + +
; + } +} + +``` diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.js b/packages/dataparcels-docs/src/pages/examples/editing-arrays.js deleted file mode 100644 index 39920acc..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/editing-arrays.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md deleted file mode 100644 index 572440fc..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ /dev/null @@ -1,147 +0,0 @@ -import Link from 'gatsby-link'; -import EditingArrays from 'examples/EditingArrays'; -import EditingArraysFlipMove from 'examples/EditingArraysFlipMove'; -import EditingArraysDrag from 'examples/EditingArraysDrag'; - -Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ExampleHoc from 'component/ExampleHoc'; - -const FruitListParcelHoc = ParcelHoc({ - name: "fruitListParcel", - valueFromProps: (/* props */) => [ - "Apple", - "Banana", - "Crumpets" - ] -}); - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return
- {fruitListParcel.toArray((fruitParcel) => { - return - {(parcel) =>
- - - - - -
} -
; - })} - -
; -}; - -export default FruitListParcelHoc(FruitListEditor); -``` - -### What's going on - -* `fruitListParcel` contains an array. -* `Parcel.toArray()` is used to iterate over the Parcel's elements, and it is passed a `mapper` function to return React elements. -* Each element parcel's `key` property is used to uniquely key each React element. -* `ParcelBoundary` is used to ensure great rendering performance. - -For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. - -## Drag and drop with react-dataparcels-drag - -Drag and drop is easy using [react-dataparcels-drag](https://www.npmjs.com/package/react-dataparcels-drag), which is a slim wrapper around [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. - -The `react-dataparcels-drag` HOC attempts to keep a very similar API to `react-sortable-hoc`, and therefore its usage is a little different compared to the other HOCs in `react-dataparcels`. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ParcelDrag from 'react-dataparcels-drag'; - -// this is a generic react-sortable-hoc + dataparcels list hoc -// that you can use in your own projects - -const SortableParcelList = ({element, container}) => { - let Container = container || 'div'; - let Element = SortableElement(({parcel, ...rest}) => element(parcel, rest)); - - return SortableContainer(({parcel}) => - {parcel.toArray((elementParcel, index) => )} - ); -}; - -const SortableFruitList = ParcelDrag({ - element: (fruitParcel) => - {(parcel) =>
- - - -
} -
-}); - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return
- - -
; -}; - -export default FruitListParcelHoc(FruitListEditor); -``` - -## Animations with react-flip-move - -Dataparcels' also plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move) because of its automatic keying. Add, remove and move items to see. - - - -```js -import React from 'react'; -import FlipMove from 'react-flip-move'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return - {fruitListParcel.toArray((fruitParcel) => { - return - {(parcel) =>
- - - - - -
} -
; - })} - -
; -}; - -const FruitListParcelHoc = ParcelHoc({ - valueFromProps: (/* props */) => [ - "Apple", - "Banana", - "Crumpets" - ], - name: "fruitListParcel" -}); - -export default FruitListParcelHoc(FruitListEditor); - -``` diff --git a/packages/dataparcels-docs/src/pages/examples/editing-objects.js b/packages/dataparcels-docs/src/pages/examples/editing-objects.js deleted file mode 100644 index 7bce9993..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-objects.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/editing-objects.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-objects.md b/packages/dataparcels-docs/src/pages/examples/editing-objects.md deleted file mode 100644 index 8ae4521b..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-objects.md +++ /dev/null @@ -1,71 +0,0 @@ -import EditingObjects from 'examples/EditingObjects'; - -Say we want to allow the user to edit the fields in the following data structure: - -```js -{ - firstname: "Robert", - lastname: "Clamps", - address: { - postcode: "1234" - } -} -``` - -This example demonstrates a pretty typical React setup to do that. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const PersonParcelHoc = ParcelHoc({ - name: "personParcel", - valueFromProps: (/* props */) => ({ - firstname: "Robert", - lastname: "Clamps", - address: { - postcode: "1234" - } - }) -}); - -const PersonEditor = (props) => { - let {personParcel} = props; - - let firstname = personParcel.get('firstname'); - let lastname = personParcel.get('lastname'); - let postcode = personParcel.getIn(['address', 'postcode']); - - return
- - - {(firstname) => } - - - - - {(lastname) => } - - - - - {(postcode) => } - -
; -}; - -export default PersonParcelHoc(PersonEditor); - -``` - -### What's going on - -* `react-dataparcels` is imported. -* It stores the data in a `ParcelHoc` higher order component, which creates and stores a parcel in state, and passes it down as props. -* The `.get()` method is used on the parcel to create smaller parcels containing just `firstname` and `lastname`. -* It uses the `ParcelBoundary` React component to avoid needless re-rendering. This isn't *required*, but it is very recommended. -* Finally `.spreadDOM()` is used to provide the `value` and `onChange` props to the `input` elements. - diff --git a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js deleted file mode 100644 index 817120f2..00000000 --- a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/managing-your-own-parcel-state.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md deleted file mode 100644 index c85420f0..00000000 --- a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md +++ /dev/null @@ -1,44 +0,0 @@ -import Link from 'gatsby-link'; -import ManagingOwnParcelState from 'examples/ManagingOwnParcelState'; - -If you don't want to use the ParcelHoc higher order component and would prefer to manage your Parcel's state yourself, this example deomstrates how. - - - -```js -import React from 'react'; -import Parcel from 'react-dataparcels'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -export default class ManagingOwnParcelState extends React.Component { - constructor(props) { - super(props); - - let personParcel = new Parcel({ - value: { - firstname: "Robert", - lastname: "Clamps" - }, - handleChange: (personParcel) => this.setState({personParcel}) - }); - - this.state = {personParcel}; - } - - render() { - let {personParcel} = this.state; - return
- - - {(firstname) => } - - - - - {(lastname) => } - -
; - } -} - -``` diff --git a/packages/dataparcels-docs/src/pages/getting-started.md b/packages/dataparcels-docs/src/pages/getting-started.md index 3c5466fe..eb32d492 100644 --- a/packages/dataparcels-docs/src/pages/getting-started.md +++ b/packages/dataparcels-docs/src/pages/getting-started.md @@ -1,8 +1,6 @@ import Link from 'gatsby-link'; -import {Grid, GridItem} from 'dcme-style'; import EditingObjectsBeginner from 'examples/EditingObjectsBeginner'; import EditingObjects from 'examples/EditingObjects'; -import Examples from 'content/Examples.md'; # Getting Started @@ -85,7 +83,7 @@ export default PersonParcelHoc(PersonEditor); ### What's going on * `react-dataparcels` is imported. -* It stores the data in a `ParcelHoc` higher order component, which creates and stores a parcel in state, and passes it down as props. The parcel contains the data. +* It stores the data in a ParcelHoc higher order component, which creates and stores a parcel in state, and passes it down as props. The parcel contains the data. * The `.get()` method is used to branch off and create smaller parcels containing just `firstname`, `lastname` and `postcode`. * The `value` and the `onChangeDOM` functions aree given to each of the `input` elements to bind them to the parcel. @@ -139,13 +137,10 @@ export default PersonParcelHoc(PersonEditor); ### What's better about it? -* It's now using the `ParcelBoundary` React component to make sure that inputs are only re-rendered if their values have changed. This isn't *required*, but it is **very** recommended. Without this, all inputs will re-render any time any data changes. +* It's now using the ParcelBoundary React component to make sure that inputs are only re-rendered if their values have changed. This isn't *required*, but it is **very** recommended. Without this, all inputs will re-render any time any data changes. * `.spreadDOM()` is used to provide the `value` and `onChangeDOM` props to the `input` elements more easily. -## Docs +## More -For more info see the documentation for Parcel, ParcelHoc and ParcelBoundary. - -## More examples - - +- Browse the API +- Continue on to data editing diff --git a/packages/dataparcels-docs/src/pages/index.md b/packages/dataparcels-docs/src/pages/index.md index da988d2d..72a8f682 100644 --- a/packages/dataparcels-docs/src/pages/index.md +++ b/packages/dataparcels-docs/src/pages/index.md @@ -11,23 +11,28 @@ You can trigger changes to small parts of your data, and those changes will prop It's designed for use with [React](https://reactjs.org/), and comes with components for easy state management and performant rendering. The heirarchical, componentized nature of React fits perfectly with the heirarchical, componentized nature of dataparcels. -See an example of dataparcels code in action. +See an example of dataparcels code in action. + + ## Getting Started Get started with dataparcels, installation instructions and a first example. + + ## Features ### 1. Data editing Data editing is the ability to manipulate data based on user input, in a way that's expressive to code. This includes: -- Data traversal -- Merging partial changes into larger data structures -- Binding data to inputs -- Methods for working with indexed data types such as arrays -- Automatic unique keying of array elements +- Data traversal +- Binding data to inputs +- Merging partial changes into larger data structures +- Methods for working with indexed data types such as arrays +- Automatic unique keying of array elements - Ability to modify data from its original format to make it suitable for the UI +- Managing your own Parcel state ### 2. UI behaviour @@ -46,3 +51,5 @@ It's designed for use with [React](https://reactjs.org/), and comes with compone - Setting up a Parcel as a slave to higher state, such as the query string - Coping with sending failable changes, such as saving data to a server - Caching unsaved changes + + diff --git a/packages/dataparcels-docs/src/pages/ui-behaviour.js b/packages/dataparcels-docs/src/pages/ui-behaviour.js new file mode 100644 index 00000000..c3b8bc5d --- /dev/null +++ b/packages/dataparcels-docs/src/pages/ui-behaviour.js @@ -0,0 +1,11 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/ui-behaviour.md'; +import PageLayout from 'component/PageLayout'; + +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/ui-behaviour.md b/packages/dataparcels-docs/src/pages/ui-behaviour.md new file mode 100644 index 00000000..9e0db37f --- /dev/null +++ b/packages/dataparcels-docs/src/pages/ui-behaviour.md @@ -0,0 +1,22 @@ +import Link from 'gatsby-link'; +import EditingObjects from 'examples/EditingObjects'; +import EditingArrays from 'examples/EditingArrays'; + +# UI Behaviour + +UI behaviour covers features that help the user interact with the data. + +## Submit buttons + +## Validation on user input + +## Confirmation + +## Selections + +## Drag and drop sorting + +## Debouncing changes + +## Pure rendering + From fd1bafa2448000867aa1b5881763fe63228518f6 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 2 Feb 2019 12:08:07 +1100 Subject: [PATCH 108/120] docs: docs docs --- .../src/examples/ModifierMethods.jsx | 75 +++++++++++++++++++ .../src/examples/ModifyDownUp.jsx | 32 -------- .../src/pages/data-editing.md | 13 ++-- packages/dataparcels-docs/src/pages/index.md | 2 +- .../src/pages/modifiers-and-updaters.js | 11 --- .../src/pages/modifiers-and-updaters.md | 48 ------------ 6 files changed, 84 insertions(+), 97 deletions(-) create mode 100644 packages/dataparcels-docs/src/examples/ModifierMethods.jsx delete mode 100644 packages/dataparcels-docs/src/examples/ModifyDownUp.jsx delete mode 100644 packages/dataparcels-docs/src/pages/modifiers-and-updaters.js delete mode 100644 packages/dataparcels-docs/src/pages/modifiers-and-updaters.md diff --git a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx new file mode 100644 index 00000000..92c09922 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +//import shape from 'react-dataparcels/shape'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import ExampleHoc from 'component/ExampleHoc'; + +const ExampleParcelHoc = ParcelHoc({ + name: "exampleParcel", + valueFromProps: (/* props */) => ({ + alphanumeric: "Abc123", + delimitedString: "abc.def", + number: 123 + }) +}); + +const AlphanumericInput = (props) => { + let alphanumericParcel = props + .alphanumericParcel + .modifyUp(string => string.replace(/[^a-zA-Z0-9]/g, "")); // remove non alpha numeric characters on the way up + + return ; +}; + +const NumberInput = (props) => { + let numberParcel = props + .numberParcel + .modifyDown(string => `${string}`) // turn value into a string on the way down + //.modifyUp(shape(number => Number(number))); // turn value back into a number on the way up + + return ; +}; + +const DelimitedStringInput = (props) => { + let delimitedStringParcel = props + .delimitedStringParcel + .modifyDown(string => string.split(".")) // turn value into an array on the way down + .modifyUp(array => array.join(".")); // turn value back into a string on the way up + + return
+ {delimitedStringParcel.toArray((segmentParcel) => { + return + {(parcel) =>
+ + + + +
} +
; + })} + +
; +}; + +const ExampleEditor = (props) => { + let {exampleParcel} = props; + return
+

Alphanumeric input

+ + {(parcel) => } + + +

Number > string

+ + {(parcel) => } + + +

Delimited string > array of strings

+

Error: "Unmutable update() cannot be called with a value of [object Object]", from prepareChildKeys()

+ + {(parcel) => } + +
; +}; + +export default ExampleParcelHoc(ExampleHoc(ExampleEditor)); diff --git a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx deleted file mode 100644 index 8e0da144..00000000 --- a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ExampleHoc from 'component/ExampleHoc'; - -const PathParcelHoc = ParcelHoc({ - name: "pathParcel", - valueFromProps: (/* props */) => "abc.def" -}); - -const PathEditor = (props) => { - let pathArrayParcel = props - .pathParcel - .modifyDown(string => string.split(".")) // turn value into an array on the way down - .modifyUp(array => array.join(".")); // turn value back into a string on the way up - - return
- {pathArrayParcel.toArray((pathSegmentParcel) => { - return - {(parcel) =>
- - - - -
} -
; - })} - -
; -}; - -export default PathParcelHoc(ExampleHoc(PathEditor)); diff --git a/packages/dataparcels-docs/src/pages/data-editing.md b/packages/dataparcels-docs/src/pages/data-editing.md index e08ae7f3..aec26bb6 100644 --- a/packages/dataparcels-docs/src/pages/data-editing.md +++ b/packages/dataparcels-docs/src/pages/data-editing.md @@ -1,6 +1,7 @@ import Link from 'gatsby-link'; import EditingObjects from 'examples/EditingObjects'; import EditingArrays from 'examples/EditingArrays'; +import ModifierMethods from 'examples/ModifierMethods'; import ManagingOwnParcelState from 'examples/ManagingOwnParcelState'; # Data Editing @@ -23,7 +24,7 @@ Say we want to allow the user to edit the fields in the following data structure This example demonstrates a pretty typical React setup to do that. - +EditingObjects /> ```js import React from 'react'; @@ -81,7 +82,7 @@ Dataparcels has a powerful set of methods for manipulating indexed data types, s Notice how items in the array are given **automatic unique keys**, displayed under each input as `#a`, `#b` ..., which can be used by React to identify each element regardless of how the elements move around. - +EditingArrays /> ```js import React from 'react'; @@ -129,9 +130,11 @@ export default FruitListParcelHoc(FruitListEditor); For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. -## Modifying data +## Modifying data to fit the UI -Will be added soon. +Sometimes you may hit a situation where a Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. Parcel's modifyDown() and modifyUp() methods let you change data types and shapes between the top level Parcel and the input bindings. + + ## Managing your own Parcel state @@ -139,7 +142,7 @@ If you don't want to use the ParcelHoc higher order co This example also serves as an indication on how you might use `dataparcels` with something other than React. - +ManagingOwnParcelState /> ```js import React from 'react'; diff --git a/packages/dataparcels-docs/src/pages/index.md b/packages/dataparcels-docs/src/pages/index.md index 72a8f682..b3e22d95 100644 --- a/packages/dataparcels-docs/src/pages/index.md +++ b/packages/dataparcels-docs/src/pages/index.md @@ -31,7 +31,7 @@ It's designed for use with [React](https://reactjs.org/), and comes with compone - Merging partial changes into larger data structures - Methods for working with indexed data types such as arrays - Automatic unique keying of array elements -- Ability to modify data from its original format to make it suitable for the UI +- Ability to modify data to fit the UI - Managing your own Parcel state ### 2. UI behaviour diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js deleted file mode 100644 index fa1d9ef8..00000000 --- a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js +++ /dev/null @@ -1,11 +0,0 @@ -// @flow -import type {Node} from 'react'; -import React from 'react'; -import {Wrapper, Text, Typography} from 'dcme-style'; -import Markdown from 'pages/modifiers-and-updaters.md'; -import PageLayout from 'component/PageLayout'; - -export default () => } -/>; diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md deleted file mode 100644 index d810e87b..00000000 --- a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md +++ /dev/null @@ -1,48 +0,0 @@ -import Link from 'component/Link'; -import {Link as HtmlLink} from 'dcme-style'; -import ModifyDownUp from 'examples/ModifyDownUp'; - -# Modifiers and Updaters - -## modifyDown() and modifyUp() - -The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. - -This example shows how a string can be turned into an array for the editor, and during changes the array can be turned back into a string. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const PathParcelHoc = ParcelHoc({ - name: "pathParcel", - valueFromProps: (/* props */) => "abc.def" -}); - -const PathEditor = (props) => { - let pathArrayParcel = props - .pathParcel - .modifyDown(string => string.split(".")) // turn value into an array on the way down - .modifyUp(array => array.join(".")); // turn value back into a string on the way up - - return
- {pathArrayParcel.toArray((pathSegmentParcel) => { - return - {(parcel) =>
- - - - -
} -
; - })} - -
; -}; - -export default PathParcelHoc(PathEditor); - -``` From 5f00e51f9405dc9b2a35157f191d350703d9fa64 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sat, 2 Feb 2019 13:08:04 +1100 Subject: [PATCH 109/120] wip --- .../src/examples/ModifierMethods.jsx | 34 +++++++++++-------- .../src/pages/data-editing.md | 6 ++-- packages/dataparcels/__test__/Exports-test.js | 6 ++++ packages/dataparcels/cancel.js | 2 ++ .../src/change/ChangeRequestReducer.js | 5 ++- .../src/change/ReducerCancelAction.js | 11 ------ packages/dataparcels/src/change/cancel.js | 18 ++++++++++ .../src/parcel/__test__/ModifyMethods-test.js | 33 ++++++++++-------- .../src/parcel/methods/ModifyMethods.js | 12 +++++-- .../src/parcelShape/ParcelShape.js | 17 ++-------- packages/react-dataparcels/Action.js | 2 +- packages/react-dataparcels/ChangeRequest.js | 2 +- .../react-dataparcels/DeletedParcelMarker.js | 2 +- packages/react-dataparcels/ParcelBoundary.js | 2 +- .../react-dataparcels/ParcelBoundaryHoc.js | 2 +- packages/react-dataparcels/ParcelHoc.js | 2 +- packages/react-dataparcels/ParcelShape.js | 2 +- .../__test__/Exports-test.js | 6 ++++ packages/react-dataparcels/cancel.js | 2 ++ packages/react-dataparcels/shape.js | 2 +- 20 files changed, 98 insertions(+), 70 deletions(-) create mode 100644 packages/dataparcels/cancel.js delete mode 100644 packages/dataparcels/src/change/ReducerCancelAction.js create mode 100644 packages/dataparcels/src/change/cancel.js create mode 100644 packages/react-dataparcels/cancel.js diff --git a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx index 92c09922..e5cc6c45 100644 --- a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx +++ b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; -//import shape from 'react-dataparcels/shape'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import cancel from 'react-dataparcels/cancel'; import ExampleHoc from 'component/ExampleHoc'; const ExampleParcelHoc = ParcelHoc({ @@ -18,16 +18,25 @@ const AlphanumericInput = (props) => { .alphanumericParcel .modifyUp(string => string.replace(/[^a-zA-Z0-9]/g, "")); // remove non alpha numeric characters on the way up - return ; + return + {(parcel) => } + ; }; const NumberInput = (props) => { let numberParcel = props .numberParcel - .modifyDown(string => `${string}`) // turn value into a string on the way down - //.modifyUp(shape(number => Number(number))); // turn value back into a number on the way up + .modifyDown(number => `${number}`) // turn value into a string on the way down + .modifyUp(string => { + let number = Number(string); + return isNaN(number) ? cancel() : number; + }); + // turn value back into a number on the way up + // but cancel the change if the string could not be turned into a number - return ; + return + {(parcel) => } + ; }; const DelimitedStringInput = (props) => { @@ -55,20 +64,17 @@ const ExampleEditor = (props) => { let {exampleParcel} = props; return

Alphanumeric input

- - {(parcel) => } - +

Number > string

- - {(parcel) => } - +

Error: requires debounce, and re-parses valid changes (00000.1 > 0.1 instantly)

+

Delimited string > array of strings

Error: "Unmutable update() cannot be called with a value of [object Object]", from prepareChildKeys()

- - {(parcel) => } - + + +

Missing objects

; }; diff --git a/packages/dataparcels-docs/src/pages/data-editing.md b/packages/dataparcels-docs/src/pages/data-editing.md index aec26bb6..7f0d3f0d 100644 --- a/packages/dataparcels-docs/src/pages/data-editing.md +++ b/packages/dataparcels-docs/src/pages/data-editing.md @@ -24,7 +24,7 @@ Say we want to allow the user to edit the fields in the following data structure This example demonstrates a pretty typical React setup to do that. -EditingObjects /> + ```js import React from 'react'; @@ -82,7 +82,7 @@ Dataparcels has a powerful set of methods for manipulating indexed data types, s Notice how items in the array are given **automatic unique keys**, displayed under each input as `#a`, `#b` ..., which can be used by React to identify each element regardless of how the elements move around. -EditingArrays /> + ```js import React from 'react'; @@ -142,7 +142,7 @@ If you don't want to use the ParcelHoc higher order co This example also serves as an indication on how you might use `dataparcels` with something other than React. -ManagingOwnParcelState /> + ```js import React from 'react'; diff --git a/packages/dataparcels/__test__/Exports-test.js b/packages/dataparcels/__test__/Exports-test.js index 7fa55ef6..dd26415d 100644 --- a/packages/dataparcels/__test__/Exports-test.js +++ b/packages/dataparcels/__test__/Exports-test.js @@ -7,6 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; +import cancel from '../cancel'; // internal files import InternalParcel from '../src/parcel/Parcel'; @@ -17,6 +18,7 @@ import InternalChangeRequest from '../lib/change/ChangeRequest'; import InternalDeletedParcelMarker from '../lib/parcelData/DeletedParcelMarker'; import InternalParcelShape from '../lib/parcelShape/ParcelShape'; import InternalShape from '../lib/parcelShape/shape'; +import InternalCancel from '../lib/change/cancel'; test('index should export Parcel', () => { expect(Parcel).toBe(InternalParcel); @@ -41,3 +43,7 @@ test('/ParcelShape should export ParcelShape', () => { test('/shape should export shape', () => { expect(shape).toBe(InternalShape); }); + +test('/cancel should export cancel', () => { + expect(cancel).toBe(InternalCancel); +}); diff --git a/packages/dataparcels/cancel.js b/packages/dataparcels/cancel.js new file mode 100644 index 00000000..61dac2b1 --- /dev/null +++ b/packages/dataparcels/cancel.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/change/cancel.js').default; diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 4b7a99a2..b350c67d 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -12,8 +12,7 @@ import pipeWith from 'unmutable/lib/util/pipeWith'; import composeWith from 'unmutable/lib/util/composeWith'; import {ReducerInvalidActionError} from '../errors/Errors'; - -import {IsReducerCancelAction} from './ReducerCancelAction'; +import {isCancelledError} from './cancel'; import del from '../parcelData/delete'; import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; @@ -100,7 +99,7 @@ export default (changeRequest: ChangeRequest) => (parcelData: ParcelData): ?Parc try { return doDeepAction(action)(parcelData); } catch(e) { - if(IsReducerCancelAction(e)) { + if(isCancelledError(e)) { cancelled++; return parcelData; } diff --git a/packages/dataparcels/src/change/ReducerCancelAction.js b/packages/dataparcels/src/change/ReducerCancelAction.js deleted file mode 100644 index dfe487f3..00000000 --- a/packages/dataparcels/src/change/ReducerCancelAction.js +++ /dev/null @@ -1,11 +0,0 @@ -// @flow - -const MESSAGE = 'CancelAction'; - -export default () => { - throw new Error(MESSAGE); -}; - -export const IsReducerCancelAction = (e: Error): boolean => { - return e.message === MESSAGE; -}; diff --git a/packages/dataparcels/src/change/cancel.js b/packages/dataparcels/src/change/cancel.js new file mode 100644 index 00000000..31030c7b --- /dev/null +++ b/packages/dataparcels/src/change/cancel.js @@ -0,0 +1,18 @@ +// @flow +import type {ParcelData} from '../types/Types'; + +const CANCELLED_ACTION_MARKER = Symbol('CANCELLED_ACTION_MARKER'); +const CANCELLED_ERROR_MESSAGE = 'CANCELLED_ERROR_MESSAGE'; + +export default () => CANCELLED_ACTION_MARKER; + +export const checkCancellation = (parcelData: ParcelData): ParcelData => { + if(parcelData.value === CANCELLED_ACTION_MARKER) { + throw new Error(CANCELLED_ERROR_MESSAGE); + } + return parcelData; +}; + +export const isCancelledError = (e: Error): boolean => { + return e.message === CANCELLED_ERROR_MESSAGE; +}; diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 6f944470..55adad87 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -4,6 +4,7 @@ import update from 'unmutable/lib/update'; import Parcel from '../Parcel'; import ParcelShape from '../../parcelShape/ParcelShape'; +import cancel from '../../change/cancel'; import shape from '../../parcelShape/shape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; @@ -113,18 +114,6 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc expect(handleChange.mock.calls[0][0].value).toBe(457); }); -test('Parcel.modifyUp() should allow you to change the payload of a changed parcel to undefined (unlike modifyUp(parcelShapeUpdater))', () => { - var handleChange = jest.fn(); - new Parcel({ - value: 123, - handleChange - }) - .modifyUp(() => {}) - .onChange(456); - - expect(handleChange.mock.calls[0][0].value).toBe(undefined); -}); - test('Parcel.modifyUp() should validate value updater', () => { let handleChange = () => {}; @@ -161,6 +150,22 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { )); }); +test('Parcel.modifyUp() should cancel a change if cancel() is returned', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => cancel()); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyUp(updater); + parcelWithModifier.push(4); + + expect(handleChange).not.toHaveBeenCalled(); +}); + test('Parcel.modifyDown(parcelShapeUpdater) should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); @@ -324,10 +329,10 @@ test('Parcel.modifyUp(parcelShapeUpdater) should work with a returned collection expect(handleChange.mock.calls[0][0].data.value).toEqual([4,3,2,1]); }); -test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if undefined is returned', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if cancel() is returned', () => { let handleChange = jest.fn(); - let updater = jest.fn(() => {}); + let updater = jest.fn(() => cancel()); let parcel = new Parcel({ handleChange, diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index ac05ace4..f550f220 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -7,6 +7,7 @@ import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; import type {ParcelShapeUpdateFunction} from '../../types/Types'; +import {checkCancellation} from '../../change/cancel'; import Types from '../../types/Types'; import setSelf from '../../parcelData/setSelf'; import setMetaDefault from '../../parcelData/setMetaDefault'; @@ -16,6 +17,7 @@ import HashString from '../../util/HashString'; import filterNot from 'unmutable/lib/filterNot'; import has from 'unmutable/lib/has'; +import pipe from 'unmutable/lib/util/pipe'; import pipeWith from 'unmutable/lib/util/pipeWith'; let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; @@ -30,11 +32,11 @@ export default (_this: Parcel): Object => ({ return _this._id.pushModifier(`${prefix}-${id}`); }, - _getModifierUpdater: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction, errorOnUndefined: ?boolean = false): ParcelDataEvaluator => { + _getModifierUpdater: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): ParcelDataEvaluator => { // $FlowFixMe - flow just cant make the connection between updater._isParcelUpdater and the choice between ParcelValueUpdater or ParcelShapeUpdateFunction return updater._isParcelUpdater // $FlowFixMe - this branch should only be hit with ParcelShapeUpdateFunction - ? (parcelData: ParcelData): ParcelData => updater(parcelData, errorOnUndefined) + ? (parcelData: ParcelData): ParcelData => updater(parcelData) : (parcelData: ParcelData): ParcelData => { let {value} = parcelData; let updatedValue = updater(value, _this); @@ -66,7 +68,11 @@ export default (_this: Parcel): Object => ({ modifyUp: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => { Types(`modifyUp()`, `updater`, `function`)(updater); - let parcelDataUpdater: ParcelDataEvaluator = _this._methods._getModifierUpdater(updater, true); + let parcelDataUpdater: ParcelDataEvaluator = pipe( + _this._methods._getModifierUpdater(updater), + checkCancellation + ); + return _this._create({ id: _this._methods._pushModifierId('mu', updater), onDispatch: (changeRequest: ChangeRequest) => { diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index d3a412e4..d605f125 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -11,7 +11,6 @@ import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; -import ReducerCancelAction from '../change/ReducerCancelAction'; import ParcelTypes from '../parcel/ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; @@ -147,19 +146,9 @@ export default class ParcelShape { } static update(updater: ParcelShapeUpdater): ParcelShapeUpdateFunction { - let fn = (parcelData: ParcelData, errorOnUndefined: ?boolean): ParcelData => { - let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); - - if(errorOnUndefined) { - // $FlowFixMe - this is passed a ParcelShape, but flow thinks that is incompatible with the argument of ParcelShapeUpdater - let updated: any = updater(parcelShape); - if(updated === undefined) { - ReducerCancelAction(); - } - updater = () => updated; - } - - return parcelShape + let fn = (parcelData: ParcelData): ParcelData => { + return ParcelShape + .fromData(parcelData) .updateShape(updater) .data; }; diff --git a/packages/react-dataparcels/Action.js b/packages/react-dataparcels/Action.js index 9168ca7c..f9fd17c6 100644 --- a/packages/react-dataparcels/Action.js +++ b/packages/react-dataparcels/Action.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/Action.js').default; +module.exports = require('dataparcels/Action.js'); diff --git a/packages/react-dataparcels/ChangeRequest.js b/packages/react-dataparcels/ChangeRequest.js index 770fab1e..d6b3b673 100644 --- a/packages/react-dataparcels/ChangeRequest.js +++ b/packages/react-dataparcels/ChangeRequest.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/ChangeRequest.js').default; +module.exports = require('dataparcels/ChangeRequest.js'); diff --git a/packages/react-dataparcels/DeletedParcelMarker.js b/packages/react-dataparcels/DeletedParcelMarker.js index ac5e7729..81925835 100644 --- a/packages/react-dataparcels/DeletedParcelMarker.js +++ b/packages/react-dataparcels/DeletedParcelMarker.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/DeletedParcelMarker.js').default; +module.exports = require('dataparcels/DeletedParcelMarker.js'); diff --git a/packages/react-dataparcels/ParcelBoundary.js b/packages/react-dataparcels/ParcelBoundary.js index e52d78fa..3f22ef33 100644 --- a/packages/react-dataparcels/ParcelBoundary.js +++ b/packages/react-dataparcels/ParcelBoundary.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelBoundary.js').default; +module.exports = require('./lib/ParcelBoundary.js'); diff --git a/packages/react-dataparcels/ParcelBoundaryHoc.js b/packages/react-dataparcels/ParcelBoundaryHoc.js index 88864deb..a2ff3bc4 100644 --- a/packages/react-dataparcels/ParcelBoundaryHoc.js +++ b/packages/react-dataparcels/ParcelBoundaryHoc.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelBoundaryHoc.js').default; +module.exports = require('./lib/ParcelBoundaryHoc.js'); diff --git a/packages/react-dataparcels/ParcelHoc.js b/packages/react-dataparcels/ParcelHoc.js index 20d5fd79..a0bd9b70 100644 --- a/packages/react-dataparcels/ParcelHoc.js +++ b/packages/react-dataparcels/ParcelHoc.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelHoc.js').default; +module.exports = require('./lib/ParcelHoc.js'); diff --git a/packages/react-dataparcels/ParcelShape.js b/packages/react-dataparcels/ParcelShape.js index f51b4791..1de2afa9 100644 --- a/packages/react-dataparcels/ParcelShape.js +++ b/packages/react-dataparcels/ParcelShape.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/ParcelShape.js').default; +module.exports = require('dataparcels/ParcelShape.js'); diff --git a/packages/react-dataparcels/__test__/Exports-test.js b/packages/react-dataparcels/__test__/Exports-test.js index edb5864e..6fb7bcea 100644 --- a/packages/react-dataparcels/__test__/Exports-test.js +++ b/packages/react-dataparcels/__test__/Exports-test.js @@ -7,6 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; +import cancel from '../cancel'; // react-dataparcels import ParcelHoc from '../ParcelHoc'; @@ -20,6 +21,7 @@ import InternalChangeRequest from 'dataparcels/ChangeRequest'; import InternalDeletedParcelMarker from 'dataparcels/DeletedParcelMarker'; import InternalParcelShape from 'dataparcels/ParcelShape'; import InternalShape from 'dataparcels/shape'; +import InternalCancel from 'dataparcels/cancel'; // internal react-dataparcels import InternalParcelHoc from '../lib/ParcelHoc'; @@ -50,6 +52,10 @@ test('index should export Parcel', () => { // expect(shape).toBe(InternalShape); // }); +// test('/cancel should export cancel', () => { +// expect(cancel).toBe(InternalCancel); +// }); + test('/ParcelHoc should export ParcelHoc', () => { expect(ParcelHoc).toBe(InternalParcelHoc); }); diff --git a/packages/react-dataparcels/cancel.js b/packages/react-dataparcels/cancel.js new file mode 100644 index 00000000..a85864ed --- /dev/null +++ b/packages/react-dataparcels/cancel.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/cancel.js'); diff --git a/packages/react-dataparcels/shape.js b/packages/react-dataparcels/shape.js index 78aa9538..65829152 100644 --- a/packages/react-dataparcels/shape.js +++ b/packages/react-dataparcels/shape.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/shape.js').default; +module.exports = require('dataparcels/shape.js'); From bedf0eb76d22787ddf3ab01646784e5db767adac Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 09:07:24 +1100 Subject: [PATCH 110/120] amend: react-dataparcels exports --- packages/react-dataparcels/Action.js | 2 +- packages/react-dataparcels/ChangeRequest.js | 2 +- .../react-dataparcels/DeletedParcelMarker.js | 2 +- packages/react-dataparcels/ParcelBoundary.js | 2 +- .../react-dataparcels/ParcelBoundaryHoc.js | 2 +- packages/react-dataparcels/ParcelHoc.js | 2 +- packages/react-dataparcels/ParcelShape.js | 2 +- .../__test__/Exports-test.js | 36 +++++++++++-------- packages/react-dataparcels/shape.js | 2 +- 9 files changed, 29 insertions(+), 23 deletions(-) diff --git a/packages/react-dataparcels/Action.js b/packages/react-dataparcels/Action.js index 9168ca7c..f9fd17c6 100644 --- a/packages/react-dataparcels/Action.js +++ b/packages/react-dataparcels/Action.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/Action.js').default; +module.exports = require('dataparcels/Action.js'); diff --git a/packages/react-dataparcels/ChangeRequest.js b/packages/react-dataparcels/ChangeRequest.js index 770fab1e..d6b3b673 100644 --- a/packages/react-dataparcels/ChangeRequest.js +++ b/packages/react-dataparcels/ChangeRequest.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/ChangeRequest.js').default; +module.exports = require('dataparcels/ChangeRequest.js'); diff --git a/packages/react-dataparcels/DeletedParcelMarker.js b/packages/react-dataparcels/DeletedParcelMarker.js index ac5e7729..81925835 100644 --- a/packages/react-dataparcels/DeletedParcelMarker.js +++ b/packages/react-dataparcels/DeletedParcelMarker.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/DeletedParcelMarker.js').default; +module.exports = require('dataparcels/DeletedParcelMarker.js'); diff --git a/packages/react-dataparcels/ParcelBoundary.js b/packages/react-dataparcels/ParcelBoundary.js index e52d78fa..3f22ef33 100644 --- a/packages/react-dataparcels/ParcelBoundary.js +++ b/packages/react-dataparcels/ParcelBoundary.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelBoundary.js').default; +module.exports = require('./lib/ParcelBoundary.js'); diff --git a/packages/react-dataparcels/ParcelBoundaryHoc.js b/packages/react-dataparcels/ParcelBoundaryHoc.js index 88864deb..a2ff3bc4 100644 --- a/packages/react-dataparcels/ParcelBoundaryHoc.js +++ b/packages/react-dataparcels/ParcelBoundaryHoc.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelBoundaryHoc.js').default; +module.exports = require('./lib/ParcelBoundaryHoc.js'); diff --git a/packages/react-dataparcels/ParcelHoc.js b/packages/react-dataparcels/ParcelHoc.js index 20d5fd79..a0bd9b70 100644 --- a/packages/react-dataparcels/ParcelHoc.js +++ b/packages/react-dataparcels/ParcelHoc.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('./lib/ParcelHoc.js').default; +module.exports = require('./lib/ParcelHoc.js'); diff --git a/packages/react-dataparcels/ParcelShape.js b/packages/react-dataparcels/ParcelShape.js index f51b4791..1de2afa9 100644 --- a/packages/react-dataparcels/ParcelShape.js +++ b/packages/react-dataparcels/ParcelShape.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/ParcelShape.js').default; +module.exports = require('dataparcels/ParcelShape.js'); diff --git a/packages/react-dataparcels/__test__/Exports-test.js b/packages/react-dataparcels/__test__/Exports-test.js index edb5864e..12ff751e 100644 --- a/packages/react-dataparcels/__test__/Exports-test.js +++ b/packages/react-dataparcels/__test__/Exports-test.js @@ -7,6 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; +import cancel from '../cancel'; // react-dataparcels import ParcelHoc from '../ParcelHoc'; @@ -20,6 +21,7 @@ import InternalChangeRequest from 'dataparcels/ChangeRequest'; import InternalDeletedParcelMarker from 'dataparcels/DeletedParcelMarker'; import InternalParcelShape from 'dataparcels/ParcelShape'; import InternalShape from 'dataparcels/shape'; +import InternalCancel from 'dataparcels/cancel'; // internal react-dataparcels import InternalParcelHoc from '../lib/ParcelHoc'; @@ -30,25 +32,29 @@ test('index should export Parcel', () => { expect(Parcel).toBe(InternalParcel); }); -// test('/Action should export Action', () => { -// expect(Action).toBe(InternalAction); -// }); +test('/Action should export Action', () => { + expect(Action).toBe(InternalAction); +}); -// test('/ChangeRequest should export ChangeRequest', () => { -// expect(ChangeRequest).toBe(InternalChangeRequest); -// }); +test('/ChangeRequest should export ChangeRequest', () => { + expect(ChangeRequest).toBe(InternalChangeRequest); +}); -// test('/DeletedParcelMarker should export DeletedParcelMarker', () => { -// expect(DeletedParcelMarker).toBe(InternalDeletedParcelMarker); -// }); +test('/DeletedParcelMarker should export DeletedParcelMarker', () => { + expect(DeletedParcelMarker).toBe(InternalDeletedParcelMarker); +}); -// test('/ParcelShape should export ParcelShape', () => { -// expect(ParcelShape).toBe(InternalParcelShape); -// }); +test('/ParcelShape should export ParcelShape', () => { + expect(ParcelShape).toBe(InternalParcelShape); +}); -// test('/shape should export shape', () => { -// expect(shape).toBe(InternalShape); -// }); +test('/shape should export shape', () => { + expect(shape).toBe(InternalShape); +}); + +test('/cancel should export cancel', () => { + expect(cancel).toBe(InternalCancel); +}); test('/ParcelHoc should export ParcelHoc', () => { expect(ParcelHoc).toBe(InternalParcelHoc); diff --git a/packages/react-dataparcels/shape.js b/packages/react-dataparcels/shape.js index 78aa9538..65829152 100644 --- a/packages/react-dataparcels/shape.js +++ b/packages/react-dataparcels/shape.js @@ -1,2 +1,2 @@ /* eslint-disable */ -module.exports = require('dataparcels/shape.js').default; +module.exports = require('dataparcels/shape.js'); From e54c080316285c7ca4d3a730e7c6d9c163120116 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 09:17:16 +1100 Subject: [PATCH 111/120] amend: use a cancel() function to cancel changes instead of undefined --- .../src/docs/api/parcel/modifyUp.md | 20 +++++++++++ packages/dataparcels/__test__/Exports-test.js | 6 ++++ packages/dataparcels/cancel.js | 2 ++ .../src/change/ChangeRequestReducer.js | 5 ++- .../src/change/ReducerCancelAction.js | 11 ------- packages/dataparcels/src/change/cancel.js | 18 ++++++++++ .../src/parcel/__test__/ModifyMethods-test.js | 33 +++++++++++-------- .../src/parcel/methods/ModifyMethods.js | 12 +++++-- .../src/parcelShape/ParcelShape.js | 17 ++-------- packages/react-dataparcels/cancel.js | 2 ++ 10 files changed, 81 insertions(+), 45 deletions(-) create mode 100644 packages/dataparcels/cancel.js delete mode 100644 packages/dataparcels/src/change/ReducerCancelAction.js create mode 100644 packages/dataparcels/src/change/cancel.js create mode 100644 packages/react-dataparcels/cancel.js diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md index a9a1f92e..843c22ee 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md @@ -29,4 +29,24 @@ It does not trigger any changes of its own, but awaits a change from below. Valu The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. +#### Cancelling a change + +You can also cancel a change by returning `cancel()` from `modifyUp()`'s updater. This allows you to programatically prevent certain changes from being applied to the data in the top level Parcel. This example shows an input that cancels any changes that would set the value to `null`: + +```js +import cancel from 'dataparcels/cancel'; +// or +import cancel from 'react-dataparcels/cancel'; + +let parcel = new Parcel({ + value: 123 +}) + +parcel = parcel.modifyUp(value => value === null ? cancel() : value); + +parcel.set(456); // this would work, value becomes 123 +parcel.set(null); // this would cause no change + +``` + diff --git a/packages/dataparcels/__test__/Exports-test.js b/packages/dataparcels/__test__/Exports-test.js index 7fa55ef6..dd26415d 100644 --- a/packages/dataparcels/__test__/Exports-test.js +++ b/packages/dataparcels/__test__/Exports-test.js @@ -7,6 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; +import cancel from '../cancel'; // internal files import InternalParcel from '../src/parcel/Parcel'; @@ -17,6 +18,7 @@ import InternalChangeRequest from '../lib/change/ChangeRequest'; import InternalDeletedParcelMarker from '../lib/parcelData/DeletedParcelMarker'; import InternalParcelShape from '../lib/parcelShape/ParcelShape'; import InternalShape from '../lib/parcelShape/shape'; +import InternalCancel from '../lib/change/cancel'; test('index should export Parcel', () => { expect(Parcel).toBe(InternalParcel); @@ -41,3 +43,7 @@ test('/ParcelShape should export ParcelShape', () => { test('/shape should export shape', () => { expect(shape).toBe(InternalShape); }); + +test('/cancel should export cancel', () => { + expect(cancel).toBe(InternalCancel); +}); diff --git a/packages/dataparcels/cancel.js b/packages/dataparcels/cancel.js new file mode 100644 index 00000000..61dac2b1 --- /dev/null +++ b/packages/dataparcels/cancel.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/change/cancel.js').default; diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 4b7a99a2..b350c67d 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -12,8 +12,7 @@ import pipeWith from 'unmutable/lib/util/pipeWith'; import composeWith from 'unmutable/lib/util/composeWith'; import {ReducerInvalidActionError} from '../errors/Errors'; - -import {IsReducerCancelAction} from './ReducerCancelAction'; +import {isCancelledError} from './cancel'; import del from '../parcelData/delete'; import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; @@ -100,7 +99,7 @@ export default (changeRequest: ChangeRequest) => (parcelData: ParcelData): ?Parc try { return doDeepAction(action)(parcelData); } catch(e) { - if(IsReducerCancelAction(e)) { + if(isCancelledError(e)) { cancelled++; return parcelData; } diff --git a/packages/dataparcels/src/change/ReducerCancelAction.js b/packages/dataparcels/src/change/ReducerCancelAction.js deleted file mode 100644 index dfe487f3..00000000 --- a/packages/dataparcels/src/change/ReducerCancelAction.js +++ /dev/null @@ -1,11 +0,0 @@ -// @flow - -const MESSAGE = 'CancelAction'; - -export default () => { - throw new Error(MESSAGE); -}; - -export const IsReducerCancelAction = (e: Error): boolean => { - return e.message === MESSAGE; -}; diff --git a/packages/dataparcels/src/change/cancel.js b/packages/dataparcels/src/change/cancel.js new file mode 100644 index 00000000..31030c7b --- /dev/null +++ b/packages/dataparcels/src/change/cancel.js @@ -0,0 +1,18 @@ +// @flow +import type {ParcelData} from '../types/Types'; + +const CANCELLED_ACTION_MARKER = Symbol('CANCELLED_ACTION_MARKER'); +const CANCELLED_ERROR_MESSAGE = 'CANCELLED_ERROR_MESSAGE'; + +export default () => CANCELLED_ACTION_MARKER; + +export const checkCancellation = (parcelData: ParcelData): ParcelData => { + if(parcelData.value === CANCELLED_ACTION_MARKER) { + throw new Error(CANCELLED_ERROR_MESSAGE); + } + return parcelData; +}; + +export const isCancelledError = (e: Error): boolean => { + return e.message === CANCELLED_ERROR_MESSAGE; +}; diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 6f944470..55adad87 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -4,6 +4,7 @@ import update from 'unmutable/lib/update'; import Parcel from '../Parcel'; import ParcelShape from '../../parcelShape/ParcelShape'; +import cancel from '../../change/cancel'; import shape from '../../parcelShape/shape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; @@ -113,18 +114,6 @@ test('Parcel.modifyUp() should allow you to change the payload of a changed parc expect(handleChange.mock.calls[0][0].value).toBe(457); }); -test('Parcel.modifyUp() should allow you to change the payload of a changed parcel to undefined (unlike modifyUp(parcelShapeUpdater))', () => { - var handleChange = jest.fn(); - new Parcel({ - value: 123, - handleChange - }) - .modifyUp(() => {}) - .onChange(456); - - expect(handleChange.mock.calls[0][0].value).toBe(undefined); -}); - test('Parcel.modifyUp() should validate value updater', () => { let handleChange = () => {}; @@ -161,6 +150,22 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { )); }); +test('Parcel.modifyUp() should cancel a change if cancel() is returned', () => { + + let handleChange = jest.fn(); + let updater = jest.fn(() => cancel()); + + let parcel = new Parcel({ + handleChange, + value: [1,2,3] + }); + + let parcelWithModifier = parcel.modifyUp(updater); + parcelWithModifier.push(4); + + expect(handleChange).not.toHaveBeenCalled(); +}); + test('Parcel.modifyDown(parcelShapeUpdater) should be called with parcelShape and return with no change', () => { let handleChange = jest.fn(); @@ -324,10 +329,10 @@ test('Parcel.modifyUp(parcelShapeUpdater) should work with a returned collection expect(handleChange.mock.calls[0][0].data.value).toEqual([4,3,2,1]); }); -test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if undefined is returned', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if cancel() is returned', () => { let handleChange = jest.fn(); - let updater = jest.fn(() => {}); + let updater = jest.fn(() => cancel()); let parcel = new Parcel({ handleChange, diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index ac05ace4..f550f220 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -7,6 +7,7 @@ import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; import type {ParcelShapeUpdateFunction} from '../../types/Types'; +import {checkCancellation} from '../../change/cancel'; import Types from '../../types/Types'; import setSelf from '../../parcelData/setSelf'; import setMetaDefault from '../../parcelData/setMetaDefault'; @@ -16,6 +17,7 @@ import HashString from '../../util/HashString'; import filterNot from 'unmutable/lib/filterNot'; import has from 'unmutable/lib/has'; +import pipe from 'unmutable/lib/util/pipe'; import pipeWith from 'unmutable/lib/util/pipeWith'; let HashFunction = (fn: Function): string => `${HashString(fn.toString())}`; @@ -30,11 +32,11 @@ export default (_this: Parcel): Object => ({ return _this._id.pushModifier(`${prefix}-${id}`); }, - _getModifierUpdater: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction, errorOnUndefined: ?boolean = false): ParcelDataEvaluator => { + _getModifierUpdater: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): ParcelDataEvaluator => { // $FlowFixMe - flow just cant make the connection between updater._isParcelUpdater and the choice between ParcelValueUpdater or ParcelShapeUpdateFunction return updater._isParcelUpdater // $FlowFixMe - this branch should only be hit with ParcelShapeUpdateFunction - ? (parcelData: ParcelData): ParcelData => updater(parcelData, errorOnUndefined) + ? (parcelData: ParcelData): ParcelData => updater(parcelData) : (parcelData: ParcelData): ParcelData => { let {value} = parcelData; let updatedValue = updater(value, _this); @@ -66,7 +68,11 @@ export default (_this: Parcel): Object => ({ modifyUp: (updater: ParcelValueUpdater|ParcelShapeUpdateFunction): Parcel => { Types(`modifyUp()`, `updater`, `function`)(updater); - let parcelDataUpdater: ParcelDataEvaluator = _this._methods._getModifierUpdater(updater, true); + let parcelDataUpdater: ParcelDataEvaluator = pipe( + _this._methods._getModifierUpdater(updater), + checkCancellation + ); + return _this._create({ id: _this._methods._pushModifierId('mu', updater), onDispatch: (changeRequest: ChangeRequest) => { diff --git a/packages/dataparcels/src/parcelShape/ParcelShape.js b/packages/dataparcels/src/parcelShape/ParcelShape.js index d3a412e4..d605f125 100644 --- a/packages/dataparcels/src/parcelShape/ParcelShape.js +++ b/packages/dataparcels/src/parcelShape/ParcelShape.js @@ -11,7 +11,6 @@ import type {ParcelShapeSetMeta} from '../types/Types'; import Types from '../types/Types'; import {ReadOnlyError} from '../errors/Errors'; -import ReducerCancelAction from '../change/ReducerCancelAction'; import ParcelTypes from '../parcel/ParcelTypes'; import ParcelId from '../parcelId/ParcelId'; @@ -147,19 +146,9 @@ export default class ParcelShape { } static update(updater: ParcelShapeUpdater): ParcelShapeUpdateFunction { - let fn = (parcelData: ParcelData, errorOnUndefined: ?boolean): ParcelData => { - let parcelShape: ParcelShape = ParcelShape.fromData(parcelData); - - if(errorOnUndefined) { - // $FlowFixMe - this is passed a ParcelShape, but flow thinks that is incompatible with the argument of ParcelShapeUpdater - let updated: any = updater(parcelShape); - if(updated === undefined) { - ReducerCancelAction(); - } - updater = () => updated; - } - - return parcelShape + let fn = (parcelData: ParcelData): ParcelData => { + return ParcelShape + .fromData(parcelData) .updateShape(updater) .data; }; diff --git a/packages/react-dataparcels/cancel.js b/packages/react-dataparcels/cancel.js new file mode 100644 index 00000000..a85864ed --- /dev/null +++ b/packages/react-dataparcels/cancel.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/cancel.js'); From e8f54f235dc7aa7ad2deba5c98c14918862a6a12 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 09:17:54 +1100 Subject: [PATCH 112/120] fix: allow ParcelBoundary state to be ahead of the state of higher parcels even when debounce or hold arent being used --- packages/react-dataparcels/src/ParcelBoundary.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-dataparcels/src/ParcelBoundary.jsx b/packages/react-dataparcels/src/ParcelBoundary.jsx index e28f28b0..c6e99cbd 100644 --- a/packages/react-dataparcels/src/ParcelBoundary.jsx +++ b/packages/react-dataparcels/src/ParcelBoundary.jsx @@ -75,7 +75,7 @@ export default class ParcelBoundary extends React.Component { /* e let parcelDataChanged: boolean = !ParcelBoundaryEquals(this.props.parcel, nextProps.parcel); - if(!parcelDataChanged && (nextProps.debounce || nextProps.hold)) { + if(!parcelDataChanged) { parcelDataChanged = !ParcelBoundaryEquals(this.state.parcel, nextState.parcel); } From b32e7fd56708312c53d7b44aaa7b01ed5e00ce2c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 09:18:05 +1100 Subject: [PATCH 113/120] docs --- .../dataparcels-docs/src/content/Examples.md | 8 - .../src/docs/api/parcel/ParcelAfter.md | 4 +- .../src/docs/api/parcel/key.md | 2 +- .../src/docs/api/parcelHoc/ParcelHoc.md | 2 +- .../src/examples/EditingArrays.jsx | 1 + .../src/examples/ModifierMethods.jsx | 81 ++++++++ .../src/examples/ModifyDownUp.jsx | 32 --- .../dataparcels-docs/src/layouts/index.scss | 5 +- .../dataparcels-docs/src/pages/api/Parcel.jsx | 12 +- ...ifiers-and-updaters.js => data-editing.js} | 2 +- .../src/pages/data-editing.md | 183 ++++++++++++++++++ .../src/pages/examples/editing-arrays.js | 9 - .../src/pages/examples/editing-arrays.md | 147 -------------- .../src/pages/examples/editing-objects.js | 9 - .../src/pages/examples/editing-objects.md | 71 ------- .../managing-your-own-parcel-state.js | 9 - .../managing-your-own-parcel-state.md | 44 ----- .../src/pages/getting-started.md | 15 +- packages/dataparcels-docs/src/pages/index.md | 23 ++- .../src/pages/modifiers-and-updaters.md | 48 ----- .../src/pages/ui-behaviour.js | 11 ++ .../src/pages/ui-behaviour.md | 22 +++ 22 files changed, 333 insertions(+), 407 deletions(-) delete mode 100644 packages/dataparcels-docs/src/content/Examples.md create mode 100644 packages/dataparcels-docs/src/examples/ModifierMethods.jsx delete mode 100644 packages/dataparcels-docs/src/examples/ModifyDownUp.jsx rename packages/dataparcels-docs/src/pages/{modifiers-and-updaters.js => data-editing.js} (84%) create mode 100644 packages/dataparcels-docs/src/pages/data-editing.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-arrays.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-arrays.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-objects.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/editing-objects.md delete mode 100644 packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js delete mode 100644 packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md delete mode 100644 packages/dataparcels-docs/src/pages/modifiers-and-updaters.md create mode 100644 packages/dataparcels-docs/src/pages/ui-behaviour.js create mode 100644 packages/dataparcels-docs/src/pages/ui-behaviour.md diff --git a/packages/dataparcels-docs/src/content/Examples.md b/packages/dataparcels-docs/src/content/Examples.md deleted file mode 100644 index 94323645..00000000 --- a/packages/dataparcels-docs/src/content/Examples.md +++ /dev/null @@ -1,8 +0,0 @@ -import Link from 'gatsby-link'; - -* Editing objects -* Editing arrays (including drag & drop) -* Storing parcel state in the query string -* Confirming deletions -* Debouncing inputs -* Managing your own parcel state diff --git a/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md b/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md index 037fcdc7..798acf09 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/ParcelAfter.md @@ -1,5 +1,5 @@ -import Examples from 'content/Examples.md'; +import Link from 'gatsby-link'; ### Examples - +Many examples can be found on the data editing page. diff --git a/packages/dataparcels-docs/src/docs/api/parcel/key.md b/packages/dataparcels-docs/src/docs/api/parcel/key.md index dde72b43..45e53fd0 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/key.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/key.md @@ -6,7 +6,7 @@ key: string Returns the Parcel's `key`. Dataparcels automatically gives unique keys to all children of a parent parcel. See parcel keys for more info. -Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated in the Editing Arrays example. +Because they are unique, the can be used as keys when rendering an array of elements with React. This is demonstrated here. ```js let value = { diff --git a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md index 40f6c773..39abeba8 100644 --- a/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md +++ b/packages/dataparcels-docs/src/docs/api/parcelHoc/ParcelHoc.md @@ -12,7 +12,7 @@ import IconParcelHoc from 'content/parcelhoc.gif'; ParcelHoc is a React higher order component. Its job is to provide a parcel as a prop, and to handle how the parcel binds to React props and lifecycle events. -It is recommended that you use ParcelHoc, rather than managing your own Parcel state. +It is recommended that you use ParcelHoc, rather than managing your own Parcel state. ```js import ParcelHoc from 'react-dataparcels/ParcelHoc'; diff --git a/packages/dataparcels-docs/src/examples/EditingArrays.jsx b/packages/dataparcels-docs/src/examples/EditingArrays.jsx index 88b3b7d8..4c576725 100644 --- a/packages/dataparcels-docs/src/examples/EditingArrays.jsx +++ b/packages/dataparcels-docs/src/examples/EditingArrays.jsx @@ -23,6 +23,7 @@ const FruitListEditor = (props) => { + key {fruitParcel.key}
} ; })} diff --git a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx new file mode 100644 index 00000000..e5cc6c45 --- /dev/null +++ b/packages/dataparcels-docs/src/examples/ModifierMethods.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import cancel from 'react-dataparcels/cancel'; +import ExampleHoc from 'component/ExampleHoc'; + +const ExampleParcelHoc = ParcelHoc({ + name: "exampleParcel", + valueFromProps: (/* props */) => ({ + alphanumeric: "Abc123", + delimitedString: "abc.def", + number: 123 + }) +}); + +const AlphanumericInput = (props) => { + let alphanumericParcel = props + .alphanumericParcel + .modifyUp(string => string.replace(/[^a-zA-Z0-9]/g, "")); // remove non alpha numeric characters on the way up + + return + {(parcel) => } + ; +}; + +const NumberInput = (props) => { + let numberParcel = props + .numberParcel + .modifyDown(number => `${number}`) // turn value into a string on the way down + .modifyUp(string => { + let number = Number(string); + return isNaN(number) ? cancel() : number; + }); + // turn value back into a number on the way up + // but cancel the change if the string could not be turned into a number + + return + {(parcel) => } + ; +}; + +const DelimitedStringInput = (props) => { + let delimitedStringParcel = props + .delimitedStringParcel + .modifyDown(string => string.split(".")) // turn value into an array on the way down + .modifyUp(array => array.join(".")); // turn value back into a string on the way up + + return
+ {delimitedStringParcel.toArray((segmentParcel) => { + return + {(parcel) =>
+ + + + +
} +
; + })} + +
; +}; + +const ExampleEditor = (props) => { + let {exampleParcel} = props; + return
+

Alphanumeric input

+ + +

Number > string

+

Error: requires debounce, and re-parses valid changes (00000.1 > 0.1 instantly)

+ + +

Delimited string > array of strings

+

Error: "Unmutable update() cannot be called with a value of [object Object]", from prepareChildKeys()

+ + +

Missing objects

+
; +}; + +export default ExampleParcelHoc(ExampleHoc(ExampleEditor)); diff --git a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx b/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx deleted file mode 100644 index 8e0da144..00000000 --- a/packages/dataparcels-docs/src/examples/ModifyDownUp.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ExampleHoc from 'component/ExampleHoc'; - -const PathParcelHoc = ParcelHoc({ - name: "pathParcel", - valueFromProps: (/* props */) => "abc.def" -}); - -const PathEditor = (props) => { - let pathArrayParcel = props - .pathParcel - .modifyDown(string => string.split(".")) // turn value into an array on the way down - .modifyUp(array => array.join(".")); // turn value back into a string on the way up - - return
- {pathArrayParcel.toArray((pathSegmentParcel) => { - return - {(parcel) =>
- - - - -
} -
; - })} - -
; -}; - -export default PathParcelHoc(ExampleHoc(PathEditor)); diff --git a/packages/dataparcels-docs/src/layouts/index.scss b/packages/dataparcels-docs/src/layouts/index.scss index 907824f4..05c03937 100644 --- a/packages/dataparcels-docs/src/layouts/index.scss +++ b/packages/dataparcels-docs/src/layouts/index.scss @@ -35,7 +35,10 @@ @include DcmeBulletList; @include DcmeButton; @include DcmeCenteredLanding; -@include DcmeDivider; +@include DcmeDivider { + border-top: 1px solid #CCC; + margin: 5rem 0 4rem; +} @include DcmeGrid; @include DcmeImage { &-logo { diff --git a/packages/dataparcels-docs/src/pages/api/Parcel.jsx b/packages/dataparcels-docs/src/pages/api/Parcel.jsx index 4a14f557..b4a6f084 100644 --- a/packages/dataparcels-docs/src/pages/api/Parcel.jsx +++ b/packages/dataparcels-docs/src/pages/api/Parcel.jsx @@ -119,12 +119,6 @@ key id path -# Spread methods -spread() -spreadDOM() -onChange() -onChangeDOM() - # Branch methods get() getIn() @@ -132,6 +126,12 @@ children() toObject() toArray() +# Input binding methods +spread() +spreadDOM() +onChange() +onChangeDOM() + # Child methods isFirst() isLast() diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js b/packages/dataparcels-docs/src/pages/data-editing.js similarity index 84% rename from packages/dataparcels-docs/src/pages/modifiers-and-updaters.js rename to packages/dataparcels-docs/src/pages/data-editing.js index fa1d9ef8..887befd8 100644 --- a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.js +++ b/packages/dataparcels-docs/src/pages/data-editing.js @@ -2,7 +2,7 @@ import type {Node} from 'react'; import React from 'react'; import {Wrapper, Text, Typography} from 'dcme-style'; -import Markdown from 'pages/modifiers-and-updaters.md'; +import Markdown from 'pages/data-editing.md'; import PageLayout from 'component/PageLayout'; export default () => Parcel class and methods. It provides methods to let you **traverse data structures** and **bind data to inputs**, so each input is connected to a specific piece of data in the Parcel. Any changes that occur in each input are propagated back to the top level Parcel, which takes care of **merging partial changes** back into the original data structure. + +Say we want to allow the user to edit the fields in the following data structure: + +```js +{ + firstname: "Robert", + lastname: "Clamps", + address: { + postcode: "1234" + } +} +``` + +This example demonstrates a pretty typical React setup to do that. + + + +```js +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; + +const PersonParcelHoc = ParcelHoc({ + name: "personParcel", + valueFromProps: (/* props */) => ({ + firstname: "Robert", + lastname: "Clamps", + address: { + postcode: "1234" + } + }) +}); + +const PersonEditor = (props) => { + let {personParcel} = props; + return
+ + + {(firstname) => } + + + + + {(lastname) => } + + + + + {(postcode) => } + +
; +}; + +export default PersonParcelHoc(PersonEditor); + +``` + +### What's going on + +* `react-dataparcels` is imported. +* It stores the data in a ParcelHoc higher order component, which creates and stores a Parcel in state, and passes it down as props. +* The `.get()` and `getIn()` methods are used on the Parcel to create smaller parcels containing just `firstname`, `lastname` and `postcode` respectively. +* It uses the ParcelBoundary React component to avoid needless re-rendering. This isn't *required*, but it is very recommended. +* Finally `.spreadDOM()` is used to provide the `value` and `onChange` props to the `input` elements. + +For the full list of methods you can use to traverse and change Parcels, see Branch Methods, Input Binding Methods and Change Methods in the Parcel API reference. + +## Indexed data types + +Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. + +Notice how items in the array are given **automatic unique keys**, displayed under each input as `#a`, `#b` ..., which can be used by React to identify each element regardless of how the elements move around. + + + +```js +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import ExampleHoc from 'component/ExampleHoc'; + +const FruitListParcelHoc = ParcelHoc({ + name: "fruitListParcel", + valueFromProps: (/* props */) => [ + "Apple", + "Banana", + "Crumpets" + ] +}); + +const FruitListEditor = (props) => { + let {fruitListParcel} = props; + return
+ {fruitListParcel.toArray((fruitParcel) => { + return + {(parcel) =>
+ + + + + + key {fruitParcel.key} +
} +
; + })} + +
; +}; + +export default FruitListParcelHoc(FruitListEditor); +``` + +### What's going on + +* `fruitListParcel` contains an array. +* `Parcel.toArray()` is used to iterate over the Parcel's elements, and it is passed a `mapper` function to return React elements. +* Each element parcel's `key` property is used to uniquely key each React element. +* `ParcelBoundary` is used to ensure great rendering performance. + +For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. + +## Modifying data to fit the UI + +Sometimes you may hit a situation where a Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. Parcel's modifyDown() and modifyUp() methods let you change data types and shapes between the top level Parcel and the input bindings. + + + +## Managing your own Parcel state + +If you don't want to use the ParcelHoc higher order component and would prefer to manage your Parcel's state yourself, this example deomstrates how. + +This example also serves as an indication on how you might use `dataparcels` with something other than React. + + + +```js +import React from 'react'; +import Parcel from 'react-dataparcels'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; + +export default class ManagingOwnParcelState extends React.Component { + constructor(props) { + super(props); + + let personParcel = new Parcel({ + value: { + firstname: "Robert", + lastname: "Clamps" + }, + handleChange: (personParcel) => this.setState({personParcel}) + }); + + this.state = {personParcel}; + } + + render() { + let {personParcel} = this.state; + return
+ + + {(firstname) => } + + + + + {(lastname) => } + +
; + } +} + +``` diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.js b/packages/dataparcels-docs/src/pages/examples/editing-arrays.js deleted file mode 100644 index 39920acc..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/editing-arrays.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md b/packages/dataparcels-docs/src/pages/examples/editing-arrays.md deleted file mode 100644 index 572440fc..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-arrays.md +++ /dev/null @@ -1,147 +0,0 @@ -import Link from 'gatsby-link'; -import EditingArrays from 'examples/EditingArrays'; -import EditingArraysFlipMove from 'examples/EditingArraysFlipMove'; -import EditingArraysDrag from 'examples/EditingArraysDrag'; - -Dataparcels has a powerful set of methods for manipulating indexed data types, such as arrays. This example demonstrates an editor that allows the user to edit, append to and sort the elements in an array of strings. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ExampleHoc from 'component/ExampleHoc'; - -const FruitListParcelHoc = ParcelHoc({ - name: "fruitListParcel", - valueFromProps: (/* props */) => [ - "Apple", - "Banana", - "Crumpets" - ] -}); - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return
- {fruitListParcel.toArray((fruitParcel) => { - return - {(parcel) =>
- - - - - -
} -
; - })} - -
; -}; - -export default FruitListParcelHoc(FruitListEditor); -``` - -### What's going on - -* `fruitListParcel` contains an array. -* `Parcel.toArray()` is used to iterate over the Parcel's elements, and it is passed a `mapper` function to return React elements. -* Each element parcel's `key` property is used to uniquely key each React element. -* `ParcelBoundary` is used to ensure great rendering performance. - -For the full list of methods you can use on indexed data types, see Indexed Change Methods and Element Change Methods in the Parcel API reference. - -## Drag and drop with react-dataparcels-drag - -Drag and drop is easy using [react-dataparcels-drag](https://www.npmjs.com/package/react-dataparcels-drag), which is a slim wrapper around [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc). Drag items up and fown to change their order. - -The `react-dataparcels-drag` HOC attempts to keep a very similar API to `react-sortable-hoc`, and therefore its usage is a little different compared to the other HOCs in `react-dataparcels`. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import ParcelDrag from 'react-dataparcels-drag'; - -// this is a generic react-sortable-hoc + dataparcels list hoc -// that you can use in your own projects - -const SortableParcelList = ({element, container}) => { - let Container = container || 'div'; - let Element = SortableElement(({parcel, ...rest}) => element(parcel, rest)); - - return SortableContainer(({parcel}) => - {parcel.toArray((elementParcel, index) => )} - ); -}; - -const SortableFruitList = ParcelDrag({ - element: (fruitParcel) => - {(parcel) =>
- - - -
} -
-}); - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return
- - -
; -}; - -export default FruitListParcelHoc(FruitListEditor); -``` - -## Animations with react-flip-move - -Dataparcels' also plays nicely with [react-flip-move](https://github.com/joshwcomeau/react-flip-move) because of its automatic keying. Add, remove and move items to see. - - - -```js -import React from 'react'; -import FlipMove from 'react-flip-move'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const FruitListEditor = (props) => { - let {fruitListParcel} = props; - return - {fruitListParcel.toArray((fruitParcel) => { - return - {(parcel) =>
- - - - - -
} -
; - })} - -
; -}; - -const FruitListParcelHoc = ParcelHoc({ - valueFromProps: (/* props */) => [ - "Apple", - "Banana", - "Crumpets" - ], - name: "fruitListParcel" -}); - -export default FruitListParcelHoc(FruitListEditor); - -``` diff --git a/packages/dataparcels-docs/src/pages/examples/editing-objects.js b/packages/dataparcels-docs/src/pages/examples/editing-objects.js deleted file mode 100644 index 7bce9993..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-objects.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/editing-objects.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/editing-objects.md b/packages/dataparcels-docs/src/pages/examples/editing-objects.md deleted file mode 100644 index 8ae4521b..00000000 --- a/packages/dataparcels-docs/src/pages/examples/editing-objects.md +++ /dev/null @@ -1,71 +0,0 @@ -import EditingObjects from 'examples/EditingObjects'; - -Say we want to allow the user to edit the fields in the following data structure: - -```js -{ - firstname: "Robert", - lastname: "Clamps", - address: { - postcode: "1234" - } -} -``` - -This example demonstrates a pretty typical React setup to do that. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const PersonParcelHoc = ParcelHoc({ - name: "personParcel", - valueFromProps: (/* props */) => ({ - firstname: "Robert", - lastname: "Clamps", - address: { - postcode: "1234" - } - }) -}); - -const PersonEditor = (props) => { - let {personParcel} = props; - - let firstname = personParcel.get('firstname'); - let lastname = personParcel.get('lastname'); - let postcode = personParcel.getIn(['address', 'postcode']); - - return
- - - {(firstname) => } - - - - - {(lastname) => } - - - - - {(postcode) => } - -
; -}; - -export default PersonParcelHoc(PersonEditor); - -``` - -### What's going on - -* `react-dataparcels` is imported. -* It stores the data in a `ParcelHoc` higher order component, which creates and stores a parcel in state, and passes it down as props. -* The `.get()` method is used on the parcel to create smaller parcels containing just `firstname` and `lastname`. -* It uses the `ParcelBoundary` React component to avoid needless re-rendering. This isn't *required*, but it is very recommended. -* Finally `.spreadDOM()` is used to provide the `value` and `onChange` props to the `input` elements. - diff --git a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js deleted file mode 100644 index 817120f2..00000000 --- a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import React from 'react'; -import Markdown from 'pages/examples/managing-your-own-parcel-state.md'; -import Example from 'component/Example'; - -export default () => ; diff --git a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md b/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md deleted file mode 100644 index c85420f0..00000000 --- a/packages/dataparcels-docs/src/pages/examples/managing-your-own-parcel-state.md +++ /dev/null @@ -1,44 +0,0 @@ -import Link from 'gatsby-link'; -import ManagingOwnParcelState from 'examples/ManagingOwnParcelState'; - -If you don't want to use the ParcelHoc higher order component and would prefer to manage your Parcel's state yourself, this example deomstrates how. - - - -```js -import React from 'react'; -import Parcel from 'react-dataparcels'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -export default class ManagingOwnParcelState extends React.Component { - constructor(props) { - super(props); - - let personParcel = new Parcel({ - value: { - firstname: "Robert", - lastname: "Clamps" - }, - handleChange: (personParcel) => this.setState({personParcel}) - }); - - this.state = {personParcel}; - } - - render() { - let {personParcel} = this.state; - return
- - - {(firstname) => } - - - - - {(lastname) => } - -
; - } -} - -``` diff --git a/packages/dataparcels-docs/src/pages/getting-started.md b/packages/dataparcels-docs/src/pages/getting-started.md index 3c5466fe..eb32d492 100644 --- a/packages/dataparcels-docs/src/pages/getting-started.md +++ b/packages/dataparcels-docs/src/pages/getting-started.md @@ -1,8 +1,6 @@ import Link from 'gatsby-link'; -import {Grid, GridItem} from 'dcme-style'; import EditingObjectsBeginner from 'examples/EditingObjectsBeginner'; import EditingObjects from 'examples/EditingObjects'; -import Examples from 'content/Examples.md'; # Getting Started @@ -85,7 +83,7 @@ export default PersonParcelHoc(PersonEditor); ### What's going on * `react-dataparcels` is imported. -* It stores the data in a `ParcelHoc` higher order component, which creates and stores a parcel in state, and passes it down as props. The parcel contains the data. +* It stores the data in a ParcelHoc higher order component, which creates and stores a parcel in state, and passes it down as props. The parcel contains the data. * The `.get()` method is used to branch off and create smaller parcels containing just `firstname`, `lastname` and `postcode`. * The `value` and the `onChangeDOM` functions aree given to each of the `input` elements to bind them to the parcel. @@ -139,13 +137,10 @@ export default PersonParcelHoc(PersonEditor); ### What's better about it? -* It's now using the `ParcelBoundary` React component to make sure that inputs are only re-rendered if their values have changed. This isn't *required*, but it is **very** recommended. Without this, all inputs will re-render any time any data changes. +* It's now using the ParcelBoundary React component to make sure that inputs are only re-rendered if their values have changed. This isn't *required*, but it is **very** recommended. Without this, all inputs will re-render any time any data changes. * `.spreadDOM()` is used to provide the `value` and `onChangeDOM` props to the `input` elements more easily. -## Docs +## More -For more info see the documentation for Parcel, ParcelHoc and ParcelBoundary. - -## More examples - - +- Browse the API +- Continue on to data editing diff --git a/packages/dataparcels-docs/src/pages/index.md b/packages/dataparcels-docs/src/pages/index.md index 0d24b935..b3e22d95 100644 --- a/packages/dataparcels-docs/src/pages/index.md +++ b/packages/dataparcels-docs/src/pages/index.md @@ -11,23 +11,28 @@ You can trigger changes to small parts of your data, and those changes will prop It's designed for use with [React](https://reactjs.org/), and comes with components for easy state management and performant rendering. The heirarchical, componentized nature of React fits perfectly with the heirarchical, componentized nature of dataparcels. -See an example of dataparcels code in action. +See an example of dataparcels code in action. + + ## Getting Started Get started with dataparcels, installation instructions and a first example. + + ## Features ### 1. Data editing Data editing is the ability to manipulate data based on user input, in a way that's expressive to code. This includes: -- Data traversal -- Merging partial changes into larger data structures -- Binding data to inputs -- Methods for working with indexed data types such as arrays -- Automatic unique keying of array elements -- Ability to modify data from its original format to make it suitable for the UI +- Data traversal +- Binding data to inputs +- Merging partial changes into larger data structures +- Methods for working with indexed data types such as arrays +- Automatic unique keying of array elements +- Ability to modify data to fit the UI +- Managing your own Parcel state ### 2. UI behaviour @@ -43,6 +48,8 @@ It's designed for use with [React](https://reactjs.org/), and comes with compone ### 3. Data synchronisation Data synchronisation is how dataparcels interacts with related pieces of external data. This includes: -- Setting up Parcels as a slave to higher state, such as the query string +- Setting up a Parcel as a slave to higher state, such as the query string - Coping with sending failable changes, such as saving data to a server - Caching unsaved changes + + diff --git a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md b/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md deleted file mode 100644 index d810e87b..00000000 --- a/packages/dataparcels-docs/src/pages/modifiers-and-updaters.md +++ /dev/null @@ -1,48 +0,0 @@ -import Link from 'component/Link'; -import {Link as HtmlLink} from 'dcme-style'; -import ModifyDownUp from 'examples/ModifyDownUp'; - -# Modifiers and Updaters - -## modifyDown() and modifyUp() - -The modify methods are particularly useful when your Parcel contains data you want to be able to make an editor for, but the data isn't stored in a format that allows you to do that easily. The `modifyDown()` and `modifyUp()` methods are often used with one another to make a value editable on the way down, and turn it back on the way up. - -This example shows how a string can be turned into an array for the editor, and during changes the array can be turned back into a string. - - - -```js -import React from 'react'; -import ParcelHoc from 'react-dataparcels/ParcelHoc'; -import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; - -const PathParcelHoc = ParcelHoc({ - name: "pathParcel", - valueFromProps: (/* props */) => "abc.def" -}); - -const PathEditor = (props) => { - let pathArrayParcel = props - .pathParcel - .modifyDown(string => string.split(".")) // turn value into an array on the way down - .modifyUp(array => array.join(".")); // turn value back into a string on the way up - - return
- {pathArrayParcel.toArray((pathSegmentParcel) => { - return - {(parcel) =>
- - - - -
} -
; - })} - -
; -}; - -export default PathParcelHoc(PathEditor); - -``` diff --git a/packages/dataparcels-docs/src/pages/ui-behaviour.js b/packages/dataparcels-docs/src/pages/ui-behaviour.js new file mode 100644 index 00000000..c3b8bc5d --- /dev/null +++ b/packages/dataparcels-docs/src/pages/ui-behaviour.js @@ -0,0 +1,11 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/ui-behaviour.md'; +import PageLayout from 'component/PageLayout'; + +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/ui-behaviour.md b/packages/dataparcels-docs/src/pages/ui-behaviour.md new file mode 100644 index 00000000..9e0db37f --- /dev/null +++ b/packages/dataparcels-docs/src/pages/ui-behaviour.md @@ -0,0 +1,22 @@ +import Link from 'gatsby-link'; +import EditingObjects from 'examples/EditingObjects'; +import EditingArrays from 'examples/EditingArrays'; + +# UI Behaviour + +UI behaviour covers features that help the user interact with the data. + +## Submit buttons + +## Validation on user input + +## Confirmation + +## Selections + +## Drag and drop sorting + +## Debouncing changes + +## Pure rendering + From cee444cc4bd967b9bb2278272b95193c2151236c Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 11:26:28 +1100 Subject: [PATCH 114/120] refactor: upgrade unmutable --- packages/dataparcels/package.json | 2 +- packages/react-dataparcels/package.json | 2 +- yarn.lock | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/dataparcels/package.json b/packages/dataparcels/package.json index 6b40436c..140af98d 100644 --- a/packages/dataparcels/package.json +++ b/packages/dataparcels/package.json @@ -25,7 +25,7 @@ "dependencies": { "babel-runtime": "6.23.0", "escape-string-regexp": "^1.0.5", - "unmutable": "^0.39.0" + "unmutable": "^0.41.1" }, "devDependencies": { "size-limit": "^0.21.1" diff --git a/packages/react-dataparcels/package.json b/packages/react-dataparcels/package.json index 91fb4567..969878f8 100644 --- a/packages/react-dataparcels/package.json +++ b/packages/react-dataparcels/package.json @@ -24,7 +24,7 @@ "dependencies": { "babel-runtime": "6.23.0", "dataparcels": "^0.18.0-2", - "unmutable": "^0.39.0" + "unmutable": "^0.41.1" }, "peerDependencies": { "react": "16.4.2" diff --git a/yarn.lock b/yarn.lock index d08aeb59..c3ddf6f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -96,7 +96,7 @@ esutils "^2.0.2" js-tokens "^3.0.0" -"@babel/runtime@^7.2.0": +"@babel/runtime@^7.1.5", "@babel/runtime@^7.2.0": version "7.3.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" dependencies: @@ -13707,6 +13707,15 @@ unmutable@^0.39.0: is-plain-object "^2.0.4" lodash.range "^3.2.0" +unmutable@^0.41.1: + version "0.41.1" + resolved "https://registry.yarnpkg.com/unmutable/-/unmutable-0.41.1.tgz#5d67409c6001108ab7deba236004e40d515dd2c7" + dependencies: + "@babel/runtime" "^7.1.5" + fast-deep-equal "^1.0.0" + is-plain-object "^2.0.4" + lodash.range "^3.2.0" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" From 22387e91d69e772d18b836174a0470e75165aab1 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 11:27:39 +1100 Subject: [PATCH 115/120] amend: bug where reducerparentactions wouldnt run pre and post on last keypathmodifier --- .../src/change/ChangeRequestReducer.js | 19 +++++++---- .../__test__/ChangeRequestReducer-test.js | 34 ++++++++++++++++++- .../__test__/updateChildKeys-test.js | 8 +++++ .../src/parcelData/updateChildKeys.js | 4 +++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index b350c67d..1cd70d84 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -4,9 +4,9 @@ import type Action from './Action'; import type {ParcelData} from '../types/Types'; import type {ParcelDataEvaluator} from '../types/Types'; -import butLast from 'unmutable/lib/butLast'; import identity from 'unmutable/lib/identity'; import last from 'unmutable/lib/last'; +import update from 'unmutable/lib/update'; import pipe from 'unmutable/lib/util/pipe'; import pipeWith from 'unmutable/lib/util/pipeWith'; import composeWith from 'unmutable/lib/util/composeWith'; @@ -28,7 +28,7 @@ import swap from '../parcelData/swap'; import swapNext from '../parcelData/swapNext'; import swapPrev from '../parcelData/swapPrev'; import unshift from '../parcelData/unshift'; -import update from '../parcelData/update'; +import parcelDataUpdate from '../parcelData/update'; const actionMap = { delete: ({lastKey}) => del(lastKey), @@ -70,20 +70,25 @@ const doAction = ({keyPath, type, payload}: Action): ParcelDataEvaluator => { const doDeepAction = (action: Action): ParcelDataEvaluator => { let {keyPathModifiers, type} = action; - let parentActionEmpty: ?Function = parentActionMap[type]; + let isParentAction: boolean = !!(parentActionMap[type]); - if(parentActionEmpty) { + if(isParentAction) { if(action.keyPath.length === 0) { return type === "delete" ? deleteSelfWithMarker : identity(); } - keyPathModifiers = butLast()(keyPathModifiers); + keyPathModifiers = pipeWith( + keyPathModifiers, + update(-1, keyPathModifier => keyPathModifier._addKey(null)) + // ^ if isParentAction set last keyPathModifier to null so that + // next() is called instead of parcelDataUpdate(key, next) + ); } return composeWith( ...keyPathModifiers.map(({key, pre, post}) => (next) => pipe( ...pre, - (key || key === 0) ? update(key, next) : next, - ...post + (key || key === 0) ? parcelDataUpdate(key, next) : next, + ...post, )), doAction(action) ); diff --git a/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js b/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js index 9cbcef7e..9418f6e9 100644 --- a/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js +++ b/packages/dataparcels/src/change/__test__/ChangeRequestReducer-test.js @@ -12,7 +12,7 @@ const makeReducer = (actions) => pipeWith( new ChangeRequest(actions), ChangeRequestReducer ); - +/* test('ChangeRequestReducer should pass through with no actions', () => { var data = { value: 123, @@ -231,4 +231,36 @@ test('ChangeRequestReducer should process aa complicated bunch of pre and post f }; expect(makeReducer(actions)(data).value).toEqual(expectedValue); +});*/ + +test('ChangeRequestReducer should process pre and post on parentActions like "swapNextSelf"', () => { + var data = { + value: "abc.def.ghi", + key: "^" + }; + + let pre = update('value', value => value.split(".")); + let post = update('value', value => value.join(".")); + + let actions = [ + ActionCreators + .swapNextSelf() + ._unget(0) + ._addPre(pre) + ._addPost(post) + ]; + + let expectedData = { + key: "^", + value: "def.abc.ghi" + }; + + let { + child, // throw away child as this is normally dealt with in updaters + // it is the reducers job to execute actions correctly, not to ensure the integrity of the data + // or protect against the setting of invalid data shapes + ...processed + } = makeReducer(actions)(data); + + expect(processed).toEqual(expectedData); }); diff --git a/packages/dataparcels/src/parcelData/__test__/updateChildKeys-test.js b/packages/dataparcels/src/parcelData/__test__/updateChildKeys-test.js index f29a48b8..5ee23a58 100644 --- a/packages/dataparcels/src/parcelData/__test__/updateChildKeys-test.js +++ b/packages/dataparcels/src/parcelData/__test__/updateChildKeys-test.js @@ -165,3 +165,11 @@ test('updateChildKeys() retains deep keys on arrays', () => { expect(expectedData).toEqual(updateChildKeys()(data)); }); + +test('updateChildKeys() should passthrough data that doesnt require keys / data that doesnt have child', () => { + let data = { + value: 123 + }; + + expect(data).toEqual(updateChildKeys()(data)); +}); diff --git a/packages/dataparcels/src/parcelData/updateChildKeys.js b/packages/dataparcels/src/parcelData/updateChildKeys.js index 49f721b5..8dc607ff 100644 --- a/packages/dataparcels/src/parcelData/updateChildKeys.js +++ b/packages/dataparcels/src/parcelData/updateChildKeys.js @@ -31,6 +31,10 @@ function toIntKey(str: ?string): ?number { export default () => (parcelData: ParcelData): ParcelData => { let {value, child} = parcelData; + if(!child) { + return parcelData; + } + if(!isIndexed(value)) { let updateChild = map((node, key) => set('key', key)(node)); From 949b9aeb531d4215a166fdb42e3414bd621728de Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Sun, 3 Feb 2019 11:28:00 +1100 Subject: [PATCH 116/120] docs: rename example --- .../src/examples/{ModifierMethods.jsx => EditingModify.jsx} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename packages/dataparcels-docs/src/examples/{ModifierMethods.jsx => EditingModify.jsx} (91%) diff --git a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx b/packages/dataparcels-docs/src/examples/EditingModify.jsx similarity index 91% rename from packages/dataparcels-docs/src/examples/ModifierMethods.jsx rename to packages/dataparcels-docs/src/examples/EditingModify.jsx index e5cc6c45..2cf576cd 100644 --- a/packages/dataparcels-docs/src/examples/ModifierMethods.jsx +++ b/packages/dataparcels-docs/src/examples/EditingModify.jsx @@ -34,7 +34,7 @@ const NumberInput = (props) => { // turn value back into a number on the way up // but cancel the change if the string could not be turned into a number - return + return {(parcel) => } ; }; @@ -67,11 +67,10 @@ const ExampleEditor = (props) => {

Number > string

-

Error: requires debounce, and re-parses valid changes (00000.1 > 0.1 instantly)

+

re-parses valid changes (00000.1 > 0.1 instantly)

Delimited string > array of strings

-

Error: "Unmutable update() cannot be called with a value of [object Object]", from prepareChildKeys()

Missing objects

From 30184c9ef933a760739d686a59821ff5509558c8 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 4 Feb 2019 10:40:15 +1100 Subject: [PATCH 117/120] add: parcelboundary keepstate and necessary underlying data --- packages/dataparcels/src/parcel/Parcel.js | 8 +++- .../src/parcel/methods/ActionMethods.js | 3 +- packages/dataparcels/src/types/Types.js | 2 + .../react-dataparcels/src/ParcelBoundary.jsx | 21 +++++++-- .../src/__test__/ParcelBoundary-test.js | 43 +++++++++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/packages/dataparcels/src/parcel/Parcel.js b/packages/dataparcels/src/parcel/Parcel.js index 9b15182e..9caf3cdf 100644 --- a/packages/dataparcels/src/parcel/Parcel.js +++ b/packages/dataparcels/src/parcel/Parcel.js @@ -40,6 +40,7 @@ import overload from 'unmutable/lib/util/overload'; const DEFAULT_CONFIG_INTERNAL = () => ({ onDispatch: undefined, child: undefined, + lastOriginId: '', meta: {}, id: new ParcelId(), parent: undefined, @@ -60,12 +61,14 @@ export default class Parcel { let { onDispatch, child, + lastOriginId, meta, id, parent, treeshare } = _configInternal || DEFAULT_CONFIG_INTERNAL(); + this._lastOriginId = lastOriginId; this._onHandleChange = handleChange; this._onDispatch = onDispatch; @@ -131,6 +134,7 @@ export default class Parcel { // from constructor _id: ParcelId; + _lastOriginId: string; _methods: { [key: string]: * }; _onHandleChange: ?Function; _onDispatch: ?Function; @@ -150,7 +154,8 @@ export default class Parcel { handleChange, parent, parcelData = this._parcelData, - treeshare = this._treeshare + treeshare = this._treeshare, + lastOriginId = this._lastOriginId } = createParcelConfig; let { @@ -166,6 +171,7 @@ export default class Parcel { }, { child, + lastOriginId, meta, id, onDispatch, diff --git a/packages/dataparcels/src/parcel/methods/ActionMethods.js b/packages/dataparcels/src/parcel/methods/ActionMethods.js index 084aa90f..92a88460 100644 --- a/packages/dataparcels/src/parcel/methods/ActionMethods.js +++ b/packages/dataparcels/src/parcel/methods/ActionMethods.js @@ -38,7 +38,8 @@ export default (_this: Parcel): Object => ({ let parcelWithChangedData = _this._create({ handleChange: _onHandleChange, - parcelData + parcelData, + lastOriginId: changeRequest.originId }); _onHandleChange(parcelWithChangedData, changeRequestWithBase); diff --git a/packages/dataparcels/src/types/Types.js b/packages/dataparcels/src/types/Types.js index bfba2e66..b707635b 100644 --- a/packages/dataparcels/src/types/Types.js +++ b/packages/dataparcels/src/types/Types.js @@ -25,6 +25,7 @@ export type ParcelConfig = { export type ParcelConfigInternal = { onDispatch?: Function, child: *, + lastOriginId: string, meta: ParcelMeta, id: ParcelId, parent?: ?Parcel, @@ -33,6 +34,7 @@ export type ParcelConfigInternal = { export type ParcelCreateConfigType = { onDispatch?: Function, + lastOriginId: string, id?: ParcelId, parcelData?: ParcelData, parent?: ?Parcel, diff --git a/packages/react-dataparcels/src/ParcelBoundary.jsx b/packages/react-dataparcels/src/ParcelBoundary.jsx index c6e99cbd..4575635f 100644 --- a/packages/react-dataparcels/src/ParcelBoundary.jsx +++ b/packages/react-dataparcels/src/ParcelBoundary.jsx @@ -27,7 +27,8 @@ type Props = { hold: boolean, forceUpdate: Array<*>, parcel: Parcel, - pure: boolean + pure: boolean, + keepState: boolean }; type State = { @@ -46,7 +47,8 @@ export default class ParcelBoundary extends React.Component { /* e debugParcel: false, hold: false, forceUpdate: [], - pure: true + pure: true, + keepState: false }; constructor(props: Props) { @@ -86,13 +88,24 @@ export default class ParcelBoundary extends React.Component { /* e } static getDerivedStateFromProps(props: Props, state: State): * { - let {parcel} = props; + let { + parcel, + keepState + } = props; + let { makeBoundarySplit, parcelFromProps } = state; - if(parcel !== parcelFromProps) { + let updateState = parcel !== parcelFromProps; + + if(keepState && parcel._lastOriginId.startsWith(parcel.id)) { + // if keepState, don't update state if the last change came from within this parcel boundary + updateState = false; + } + + if(updateState) { var newState: any = { parcelFromProps: parcel }; diff --git a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js index 44e71076..d7fb6820 100644 --- a/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js +++ b/packages/react-dataparcels/src/__test__/ParcelBoundary-test.js @@ -315,3 +315,46 @@ test('ParcelBoundary should use an internal boundary split to stop parcel bounda expect(childParcelA2.value).toEqual({abc: 456, def: 123}); expect(childParcelB2.value).toEqual({abc: 123, def: 456}); }); + +test('ParcelBoundary should ignore updates from props for updates caused by themselves if keepState is true', () => { + let childRenderer = jest.fn(); + let handleChange = jest.fn(); + + let parcel = new Parcel({ + value: 123, + handleChange + }); + + let withModify = (parcel) => parcel.modifyUp(value => value + 1); + + let wrapper = shallow( + {childRenderer} + ); + + let childParcel = childRenderer.mock.calls[0][0]; + childParcel.onChange(456); + + let newParcel = handleChange.mock.calls[0][0]; + + // verify that the current value of the parcel has been updated + expect(newParcel.value).toBe(457); + + wrapper.setProps({ + parcel: withModify(newParcel) + }); + + // expect that the value in the parcelboundary has not changed + // because the last change was triggered by this boundary + let childParcel2 = childRenderer.mock.calls[2][0]; + expect(childParcel2.value).toBe(456); + + // make a change externally and ensure that the value in the boundary does update + newParcel.set(789); + let newParcel2 = handleChange.mock.calls[1][0]; + wrapper.setProps({ + parcel: withModify(newParcel2) + }); + + let childParcel3 = childRenderer.mock.calls[3][0]; + expect(childParcel3.value).toBe(789); +}); From 390e5f80d1eed92f67c1af90c2576d0afe71d6d4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 4 Feb 2019 10:40:32 +1100 Subject: [PATCH 118/120] docs: more docs --- .../src/docs/api/parcelBoundary/keepState.md | 31 ++++++++++++ .../src/examples/EditingModify.jsx | 49 +++++++++++++++---- .../src/pages/api/ParcelBoundary.jsx | 3 ++ .../src/pages/data-editing.md | 10 ++-- .../dataparcels-docs/src/pages/sandbox.js | 11 +++++ .../dataparcels-docs/src/pages/sandbox.md | 8 +++ .../src/sandbox/SandboxFrame.jsx | 32 ++++++++++++ 7 files changed, 129 insertions(+), 15 deletions(-) create mode 100644 packages/dataparcels-docs/src/docs/api/parcelBoundary/keepState.md create mode 100644 packages/dataparcels-docs/src/pages/sandbox.js create mode 100644 packages/dataparcels-docs/src/pages/sandbox.md create mode 100644 packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx diff --git a/packages/dataparcels-docs/src/docs/api/parcelBoundary/keepState.md b/packages/dataparcels-docs/src/docs/api/parcelBoundary/keepState.md new file mode 100644 index 00000000..3939942b --- /dev/null +++ b/packages/dataparcels-docs/src/docs/api/parcelBoundary/keepState.md @@ -0,0 +1,31 @@ +import Link from 'component/Link'; + +```flow +keepState?: boolean = false // optional +``` + +The default behaviour of ParcelBoundary is to update its contents whenever the Parcel it receives via props has changed. + +When `keepState` is true, it ensures that any changes that originate from inside the ParcelBoundary are not overwritten by the incoming new props containing the updated value. This won't be a problem for most ParcelBoundaries, but it can be if modify methods are being used above the ParcelBoundary, and if those modify methods subtly change the value that ends up being passed back down into the ParcelBoundary. In this situation you may see inputs change more than what was typed into the input. + +The `keepState` option effectively makes the ParcelBoundary the master of its own state, and *not* the Parcel it receives via props. The one exception is if the change originates from outside the ParcelBoundary, in which case the ParcelBoundary will update its contents like normal. + +```js +let numberParcel = parcel + .modifyDown(number => `${number}`) + // ^ turn value into a string on the way down + .modifyUp(string => Number(string.replace(/[^0-9]/g, ""))); + // ^ turn value back into a number on the way up + +return + {(parcel) => } +; + +// without keepState, if you type "0.10" in the input above it would +// immediately be replaced with "0.1", as the new value is turned +// into a number on the way up, and into a string on the way down, +// which would make typing very frustrating. +// keepState keeps "0.10" in the text field. +``` + +Example diff --git a/packages/dataparcels-docs/src/examples/EditingModify.jsx b/packages/dataparcels-docs/src/examples/EditingModify.jsx index 2cf576cd..173dfc02 100644 --- a/packages/dataparcels-docs/src/examples/EditingModify.jsx +++ b/packages/dataparcels-docs/src/examples/EditingModify.jsx @@ -8,15 +8,17 @@ const ExampleParcelHoc = ParcelHoc({ name: "exampleParcel", valueFromProps: (/* props */) => ({ alphanumeric: "Abc123", + number: 123, delimitedString: "abc.def", - number: 123 + missingValue: undefined }) }); const AlphanumericInput = (props) => { let alphanumericParcel = props .alphanumericParcel - .modifyUp(string => string.replace(/[^a-zA-Z0-9]/g, "")); // remove non alpha numeric characters on the way up + .modifyUp(string => string.replace(/[^a-zA-Z0-9]/g, "")); + // ^ remove non alpha numeric characters on the way up return {(parcel) => } @@ -26,15 +28,23 @@ const AlphanumericInput = (props) => { const NumberInput = (props) => { let numberParcel = props .numberParcel - .modifyDown(number => `${number}`) // turn value into a string on the way down + .modifyDown(number => `${number}`) + // ^ turn value into a string on the way down .modifyUp(string => { let number = Number(string); return isNaN(number) ? cancel() : number; }); - // turn value back into a number on the way up - // but cancel the change if the string could not be turned into a number + // ^ turn value back into a number on the way up + // but cancel the change if the string + // could not be turned into a number - return + // without the keepState prop, typing "0.10" + // would immediately be replaced with "0.1" + // as the new value is turned into a number on the way up, + // and into a string on the way down + // which would make typing very frustrating + + return {(parcel) => } ; }; @@ -42,8 +52,10 @@ const NumberInput = (props) => { const DelimitedStringInput = (props) => { let delimitedStringParcel = props .delimitedStringParcel - .modifyDown(string => string.split(".")) // turn value into an array on the way down - .modifyUp(array => array.join(".")); // turn value back into a string on the way up + .modifyDown(string => string.split(".")) + // ^ turn value into an array on the way down + .modifyUp(array => array.join(".")); + // ^ turn value back into a string on the way up return
{delimitedStringParcel.toArray((segmentParcel) => { @@ -60,6 +72,23 @@ const DelimitedStringInput = (props) => {
; }; +const MissingValueInput = (props) => { + let missingValueParcel = props + .missingValueParcel + .modifyDown(value => value || []) + // ^ turn value into an array if its missing + // so we can always render against an array + + return
+ {missingValueParcel.toArray((segmentParcel) => { + return + {(parcel) => } + ; + })} + +
; +}; + const ExampleEditor = (props) => { let {exampleParcel} = props; return
@@ -67,13 +96,13 @@ const ExampleEditor = (props) => {

Number > string

-

re-parses valid changes (00000.1 > 0.1 instantly)

Delimited string > array of strings

-

Missing objects

+

Coping with missing values

+
; }; diff --git a/packages/dataparcels-docs/src/pages/api/ParcelBoundary.jsx b/packages/dataparcels-docs/src/pages/api/ParcelBoundary.jsx index 84d9e108..63c38203 100644 --- a/packages/dataparcels-docs/src/pages/api/ParcelBoundary.jsx +++ b/packages/dataparcels-docs/src/pages/api/ParcelBoundary.jsx @@ -10,6 +10,7 @@ import Markdown_forceUpdate from 'docs/api/parcelBoundary/forceUpdate.md'; import Markdown_debounce from 'docs/api/parcelBoundary/debounce.md'; import Markdown_hold from 'docs/api/parcelBoundary/hold.md'; import Markdown_pure from 'docs/api/parcelBoundary/pure.md'; +import Markdown_keepState from 'docs/api/parcelBoundary/keepState.md'; import Markdown_debugBuffer from 'docs/api/parcelBoundary/debugBuffer.md'; import Markdown_debugParcel from 'docs/api/parcelBoundary/debugParcel.md'; @@ -22,6 +23,7 @@ const md = { debounce: Markdown_debounce, hold: Markdown_hold, pure: Markdown_pure, + keepState: Markdown_keepState, debugBuffer: Markdown_debugBuffer, debugParcel: Markdown_debugParcel } @@ -36,6 +38,7 @@ debounce pure forceUpdate hold +keepState debugBuffer debugParcel `; diff --git a/packages/dataparcels-docs/src/pages/data-editing.md b/packages/dataparcels-docs/src/pages/data-editing.md index 7f0d3f0d..991a829b 100644 --- a/packages/dataparcels-docs/src/pages/data-editing.md +++ b/packages/dataparcels-docs/src/pages/data-editing.md @@ -1,7 +1,7 @@ import Link from 'gatsby-link'; import EditingObjects from 'examples/EditingObjects'; import EditingArrays from 'examples/EditingArrays'; -import ModifierMethods from 'examples/ModifierMethods'; +import EditingModify from 'examples/EditingModify'; import ManagingOwnParcelState from 'examples/ManagingOwnParcelState'; # Data Editing @@ -24,7 +24,7 @@ Say we want to allow the user to edit the fields in the following data structure This example demonstrates a pretty typical React setup to do that. - +EditingObjects /> ```js import React from 'react'; @@ -82,7 +82,7 @@ Dataparcels has a powerful set of methods for manipulating indexed data types, s Notice how items in the array are given **automatic unique keys**, displayed under each input as `#a`, `#b` ..., which can be used by React to identify each element regardless of how the elements move around. - +EditingArrays /> ```js import React from 'react'; @@ -134,7 +134,7 @@ For the full list of methods you can use on indexed data types, see modifyDown() and modifyUp() methods let you change data types and shapes between the top level Parcel and the input bindings. - + ## Managing your own Parcel state @@ -142,7 +142,7 @@ If you don't want to use the ParcelHoc higher order co This example also serves as an indication on how you might use `dataparcels` with something other than React. - +ManagingOwnParcelState /> ```js import React from 'react'; diff --git a/packages/dataparcels-docs/src/pages/sandbox.js b/packages/dataparcels-docs/src/pages/sandbox.js new file mode 100644 index 00000000..f697fa10 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/sandbox.js @@ -0,0 +1,11 @@ +// @flow +import type {Node} from 'react'; +import React from 'react'; +import {Wrapper, Text, Typography} from 'dcme-style'; +import Markdown from 'pages/sandbox.md'; +import PageLayout from 'component/PageLayout'; + +export default () => } +/>; diff --git a/packages/dataparcels-docs/src/pages/sandbox.md b/packages/dataparcels-docs/src/pages/sandbox.md new file mode 100644 index 00000000..8a1b05f3 --- /dev/null +++ b/packages/dataparcels-docs/src/pages/sandbox.md @@ -0,0 +1,8 @@ +import Link from 'gatsby-link'; +import SandboxFrame from 'sandbox/SandboxFrame'; + +# Sandbox + +## Frames + + diff --git a/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx b/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx new file mode 100644 index 00000000..be034fa4 --- /dev/null +++ b/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx @@ -0,0 +1,32 @@ +import React from 'react'; +import ParcelHoc from 'react-dataparcels/ParcelHoc'; +import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; +import cancel from 'react-dataparcels/cancel'; +import ExampleHoc from 'component/ExampleHoc'; + +const ExampleParcelHoc = ParcelHoc({ + name: "exampleParcel", + valueFromProps: (/* props */) => ({ + abc: 123, + def: 123 + }) +}); + +const ExampleEditor = ({exampleParcel}) => { + return
+

Frames: {exampleParcel._frame}

+ + {(parcel, {release}) =>
+

Frames: {parcel._frame}

+ + +
} +
+ + + {(parcel) => } + +
; +}; + +export default ExampleParcelHoc(ExampleHoc(ExampleEditor)); From e604a4d6d2c043b7b7f45f13510094b7d08552be Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 4 Feb 2019 12:19:06 +1100 Subject: [PATCH 119/120] amend: change() is now callewd CancelActionMarker --- .../dataparcels-docs/src/docs/api/parcel/modifyUp.md | 8 ++++---- .../dataparcels-docs/src/examples/EditingModify.jsx | 4 ++-- packages/dataparcels/CancelActionMarker.js | 2 ++ packages/dataparcels/__test__/Exports-test.js | 8 ++++---- packages/dataparcels/cancel.js | 2 -- .../src/change/{cancel.js => CancelActionMarker.js} | 2 +- .../dataparcels/src/change/ChangeRequestReducer.js | 2 +- .../src/parcel/__test__/ModifyMethods-test.js | 10 +++++----- .../dataparcels/src/parcel/methods/ModifyMethods.js | 2 +- packages/react-dataparcels/CancelActionMarker.js | 2 ++ packages/react-dataparcels/__test__/Exports-test.js | 12 ++++-------- packages/react-dataparcels/cancel.js | 2 -- 12 files changed, 26 insertions(+), 30 deletions(-) create mode 100644 packages/dataparcels/CancelActionMarker.js delete mode 100644 packages/dataparcels/cancel.js rename packages/dataparcels/src/change/{cancel.js => CancelActionMarker.js} (91%) create mode 100644 packages/react-dataparcels/CancelActionMarker.js delete mode 100644 packages/react-dataparcels/cancel.js diff --git a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md index 843c22ee..75e0e782 100644 --- a/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md +++ b/packages/dataparcels-docs/src/docs/api/parcel/modifyUp.md @@ -31,18 +31,18 @@ The modify methods are particularly useful when your Parcel contains data you wa #### Cancelling a change -You can also cancel a change by returning `cancel()` from `modifyUp()`'s updater. This allows you to programatically prevent certain changes from being applied to the data in the top level Parcel. This example shows an input that cancels any changes that would set the value to `null`: +You can also cancel a change by returning `CancelActionMarker` from `modifyUp()`'s updater. This allows you to programatically prevent certain changes from being applied to the data in the top level Parcel. This example shows an input that cancels any changes that would set the value to `null`: ```js -import cancel from 'dataparcels/cancel'; +import CancelActionMarker from 'dataparcels/CancelActionMarker'; // or -import cancel from 'react-dataparcels/cancel'; +import CancelActionMarker from 'react-dataparcels/CancelActionMarker'; let parcel = new Parcel({ value: 123 }) -parcel = parcel.modifyUp(value => value === null ? cancel() : value); +parcel = parcel.modifyUp(value => value === null ? CancelActionMarker : value); parcel.set(456); // this would work, value becomes 123 parcel.set(null); // this would cause no change diff --git a/packages/dataparcels-docs/src/examples/EditingModify.jsx b/packages/dataparcels-docs/src/examples/EditingModify.jsx index 173dfc02..695db161 100644 --- a/packages/dataparcels-docs/src/examples/EditingModify.jsx +++ b/packages/dataparcels-docs/src/examples/EditingModify.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import cancel from 'react-dataparcels/cancel'; +import CancelActionMarker from 'react-dataparcels/CancelActionMarker'; import ExampleHoc from 'component/ExampleHoc'; const ExampleParcelHoc = ParcelHoc({ @@ -32,7 +32,7 @@ const NumberInput = (props) => { // ^ turn value into a string on the way down .modifyUp(string => { let number = Number(string); - return isNaN(number) ? cancel() : number; + return isNaN(number) ? CancelActionMarker : number; }); // ^ turn value back into a number on the way up // but cancel the change if the string diff --git a/packages/dataparcels/CancelActionMarker.js b/packages/dataparcels/CancelActionMarker.js new file mode 100644 index 00000000..a2df6dd0 --- /dev/null +++ b/packages/dataparcels/CancelActionMarker.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('./lib/change/CancelActionMarker.js').default; diff --git a/packages/dataparcels/__test__/Exports-test.js b/packages/dataparcels/__test__/Exports-test.js index dd26415d..35c467bd 100644 --- a/packages/dataparcels/__test__/Exports-test.js +++ b/packages/dataparcels/__test__/Exports-test.js @@ -7,7 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; -import cancel from '../cancel'; +import CancelActionMarker from '../CancelActionMarker'; // internal files import InternalParcel from '../src/parcel/Parcel'; @@ -18,7 +18,7 @@ import InternalChangeRequest from '../lib/change/ChangeRequest'; import InternalDeletedParcelMarker from '../lib/parcelData/DeletedParcelMarker'; import InternalParcelShape from '../lib/parcelShape/ParcelShape'; import InternalShape from '../lib/parcelShape/shape'; -import InternalCancel from '../lib/change/cancel'; +import InternalCancelActionMarker from '../lib/change/CancelActionMarker'; test('index should export Parcel', () => { expect(Parcel).toBe(InternalParcel); @@ -44,6 +44,6 @@ test('/shape should export shape', () => { expect(shape).toBe(InternalShape); }); -test('/cancel should export cancel', () => { - expect(cancel).toBe(InternalCancel); +test('/CancelActionMarker should export CancelActionMarker', () => { + expect(CancelActionMarker).toBe(InternalCancelActionMarker); }); diff --git a/packages/dataparcels/cancel.js b/packages/dataparcels/cancel.js deleted file mode 100644 index 61dac2b1..00000000 --- a/packages/dataparcels/cancel.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -module.exports = require('./lib/change/cancel.js').default; diff --git a/packages/dataparcels/src/change/cancel.js b/packages/dataparcels/src/change/CancelActionMarker.js similarity index 91% rename from packages/dataparcels/src/change/cancel.js rename to packages/dataparcels/src/change/CancelActionMarker.js index 31030c7b..1e39688d 100644 --- a/packages/dataparcels/src/change/cancel.js +++ b/packages/dataparcels/src/change/CancelActionMarker.js @@ -4,7 +4,7 @@ import type {ParcelData} from '../types/Types'; const CANCELLED_ACTION_MARKER = Symbol('CANCELLED_ACTION_MARKER'); const CANCELLED_ERROR_MESSAGE = 'CANCELLED_ERROR_MESSAGE'; -export default () => CANCELLED_ACTION_MARKER; +export default CANCELLED_ACTION_MARKER; export const checkCancellation = (parcelData: ParcelData): ParcelData => { if(parcelData.value === CANCELLED_ACTION_MARKER) { diff --git a/packages/dataparcels/src/change/ChangeRequestReducer.js b/packages/dataparcels/src/change/ChangeRequestReducer.js index 1cd70d84..78147a59 100644 --- a/packages/dataparcels/src/change/ChangeRequestReducer.js +++ b/packages/dataparcels/src/change/ChangeRequestReducer.js @@ -12,7 +12,7 @@ import pipeWith from 'unmutable/lib/util/pipeWith'; import composeWith from 'unmutable/lib/util/composeWith'; import {ReducerInvalidActionError} from '../errors/Errors'; -import {isCancelledError} from './cancel'; +import {isCancelledError} from './CancelActionMarker'; import del from '../parcelData/delete'; import deleteSelfWithMarker from '../parcelData/deleteSelfWithMarker'; diff --git a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js index 55adad87..3a0063b6 100644 --- a/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js +++ b/packages/dataparcels/src/parcel/__test__/ModifyMethods-test.js @@ -4,7 +4,7 @@ import update from 'unmutable/lib/update'; import Parcel from '../Parcel'; import ParcelShape from '../../parcelShape/ParcelShape'; -import cancel from '../../change/cancel'; +import CancelActionMarker from '../../change/CancelActionMarker'; import shape from '../../parcelShape/shape'; import TestValidateValueUpdater from '../../util/__test__/TestValidateValueUpdater-testUtil'; @@ -150,10 +150,10 @@ test('Parcel.modifyUp() should allow changes to meta through', () => { )); }); -test('Parcel.modifyUp() should cancel a change if cancel() is returned', () => { +test('Parcel.modifyUp() should cancel a change if CancelActionMarker is returned', () => { let handleChange = jest.fn(); - let updater = jest.fn(() => cancel()); + let updater = jest.fn(() => CancelActionMarker); let parcel = new Parcel({ handleChange, @@ -329,10 +329,10 @@ test('Parcel.modifyUp(parcelShapeUpdater) should work with a returned collection expect(handleChange.mock.calls[0][0].data.value).toEqual([4,3,2,1]); }); -test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if cancel() is returned', () => { +test('Parcel.modifyUp(parcelShapeUpdater) should cancel a change if CancelActionMarker is returned', () => { let handleChange = jest.fn(); - let updater = jest.fn(() => cancel()); + let updater = jest.fn(() => CancelActionMarker); let parcel = new Parcel({ handleChange, diff --git a/packages/dataparcels/src/parcel/methods/ModifyMethods.js b/packages/dataparcels/src/parcel/methods/ModifyMethods.js index f550f220..4cc429cc 100644 --- a/packages/dataparcels/src/parcel/methods/ModifyMethods.js +++ b/packages/dataparcels/src/parcel/methods/ModifyMethods.js @@ -7,7 +7,7 @@ import type {ParcelMeta} from '../../types/Types'; import type {ParcelValueUpdater} from '../../types/Types'; import type {ParcelShapeUpdateFunction} from '../../types/Types'; -import {checkCancellation} from '../../change/cancel'; +import {checkCancellation} from '../../change/CancelActionMarker'; import Types from '../../types/Types'; import setSelf from '../../parcelData/setSelf'; import setMetaDefault from '../../parcelData/setMetaDefault'; diff --git a/packages/react-dataparcels/CancelActionMarker.js b/packages/react-dataparcels/CancelActionMarker.js new file mode 100644 index 00000000..1fb6c363 --- /dev/null +++ b/packages/react-dataparcels/CancelActionMarker.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +module.exports = require('dataparcels/CancelActionMarker.js'); diff --git a/packages/react-dataparcels/__test__/Exports-test.js b/packages/react-dataparcels/__test__/Exports-test.js index 823777b5..d5300435 100644 --- a/packages/react-dataparcels/__test__/Exports-test.js +++ b/packages/react-dataparcels/__test__/Exports-test.js @@ -7,7 +7,7 @@ import ChangeRequest from '../ChangeRequest'; import DeletedParcelMarker from '../DeletedParcelMarker'; import ParcelShape from '../ParcelShape'; import shape from '../shape'; -import cancel from '../cancel'; +import CancelActionMarker from '../CancelActionMarker'; // react-dataparcels import ParcelHoc from '../ParcelHoc'; @@ -21,7 +21,7 @@ import InternalChangeRequest from 'dataparcels/ChangeRequest'; import InternalDeletedParcelMarker from 'dataparcels/DeletedParcelMarker'; import InternalParcelShape from 'dataparcels/ParcelShape'; import InternalShape from 'dataparcels/shape'; -import InternalCancel from 'dataparcels/cancel'; +import InternalCancelActionMarker from 'dataparcels/CancelActionMarker'; // internal react-dataparcels import InternalParcelHoc from '../lib/ParcelHoc'; @@ -52,14 +52,10 @@ test('/shape should export shape', () => { expect(shape).toBe(InternalShape); }); -test('/cancel should export cancel', () => { - expect(cancel).toBe(InternalCancel); +test('/CancelActionMarker should export CancelActionMarker', () => { + expect(CancelActionMarker).toBe(InternalCancelActionMarker); }); -// test('/cancel should export cancel', () => { -// expect(cancel).toBe(InternalCancel); -// }); - test('/ParcelHoc should export ParcelHoc', () => { expect(ParcelHoc).toBe(InternalParcelHoc); }); diff --git a/packages/react-dataparcels/cancel.js b/packages/react-dataparcels/cancel.js deleted file mode 100644 index a85864ed..00000000 --- a/packages/react-dataparcels/cancel.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -module.exports = require('dataparcels/cancel.js'); From cf0e80d3a24122981a67a2f29e030e88c0ab19d4 Mon Sep 17 00:00:00 2001 From: Damien Clarke Date: Mon, 4 Feb 2019 12:22:53 +1100 Subject: [PATCH 120/120] docs: remove cancel import from sandbox --- packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx b/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx index be034fa4..9ccbd36a 100644 --- a/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx +++ b/packages/dataparcels-docs/src/sandbox/SandboxFrame.jsx @@ -1,7 +1,6 @@ import React from 'react'; import ParcelHoc from 'react-dataparcels/ParcelHoc'; import ParcelBoundary from 'react-dataparcels/ParcelBoundary'; -import cancel from 'react-dataparcels/cancel'; import ExampleHoc from 'component/ExampleHoc'; const ExampleParcelHoc = ParcelHoc({