diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..94bde1a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: ianwalter +tidelift: "npm/@ianwalter/decision-tree" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a73168..ee31e8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,9 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: jobs: build: runs-on: ubuntu-latest diff --git a/LICENSE b/LICENSE index 1e47d68..85a9fd3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,35 +1,28 @@ -Copyright (c) Ian Walter (https://iankwalter.com) - -Licensed under the Apache License, Version 2.0 (the "License") modified with -Commons Clause Restriction; you may not use this file except in compliance with -the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. - -"Commons Clause" License Condition v1.0 - -The Software is provided to you by the Licensor under the License, as defined -below, subject to the following condition. - -Without limiting other conditions in the License, the grant of rights under the -License will not include, and the License does not grant to you, the right to -Sell the Software. - -For purposes of the foregoing, "Sell" means practicing any or all of the rights -granted to you under the License to provide to third parties, for a fee or other -consideration (including without limitation fees for hosting or -consulting/support services related to the Software), a product or service whose -value derives, entirely or substantially, from the functionality of the -Software. Any license notice or attribution required by the License must also -include this Commons Clause License Condition notice. - -Software: @ianwalter/decision-tree - -License: Apache 2.0 - -Licensor: Ian Walter +Copyright 2019 Ian Walter + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + +* The software may not be used by individuals, corporations, governments, or + other groups for systems or activities that actively and knowingly endanger, + harm, or otherwise threaten the physical, mental, economic, or general + well-being of individuals or groups in violation of the United Nations + Universal Declaration of Human Rights + (https://www.un.org/en/universal-declaration-human-rights/). + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This license is derived from the MIT License, as amended to limit the impact of +the unethical use of open source software. diff --git a/index.js b/index.js index ede03b6..137d1ad 100644 --- a/index.js +++ b/index.js @@ -1,21 +1,29 @@ import BaseError from '@ianwalter/base-error' -function findItemByKey (items = [], key) { - for (const item of items) { - if (item.key === key) { - return item - } +const findItemByKey = (items = [], key) => items.find(item => item.key === key) + +class NoChildrenError extends BaseError { + constructor (node) { + super('No children found to move to', { node }) + } +} + +class NoLeadToError extends BaseError { + constructor (key, option) { + super('Cannot determine which child to move to', { key, option }) } } -export default class { +class NoParentError extends BaseError { + constructor () { + super('No parent node found to move to') + } +} + +class DecisionTree { constructor (tree = {}, path = [tree], state = {}) { this.path = path this.state = state - - this.noChildren = 'No children found to move to' - this.noLead = "Can't determine which child to move to" - this.noParent = 'No parent node found to move to' } set (key, value) { @@ -56,7 +64,7 @@ export default class { // Move to the next node. if (currentNode.children.length < 1) { // No children to move to! - throw new BaseError(this.noChildren, currentNode) + throw new NoChildrenError(currentNode) } else if (currentNode.children.length === 1) { // Move to the only child. return this.goToNode(currentNode.children[0]) @@ -70,7 +78,7 @@ export default class { } // Throw an error if the next node to move to can't be determined. - throw new BaseError(this.noLead, selectedOptionKey, selectedOption) + throw new NoLeadToError(selectedOptionKey, selectedOption) } prev () { @@ -78,10 +86,18 @@ export default class { if (parentNode) { return this.path.pop() } - throw new BaseError(this.noParent) + throw new NoParentError() } pathKeys () { return this.path.map(({ key }) => key) } } + + +export { + NoChildrenError, + NoLeadToError, + NoParentError, + DecisionTree +} diff --git a/package.json b/package.json index 6f63bdf..bef33aa 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,11 @@ "name": "@ianwalter/decision-tree", "version": "4.0.1", "description": "A utility for traversing decision trees by selecting options", + "license": "SEE LICENSE IN LICENSE", + "author": { + "name": "Ian Walter", + "url": "https://ianwalter.dev" + }, "main": "dist/decision-tree.js", "module": "dist/decision-tree.m.js", "scripts": { @@ -24,8 +29,6 @@ "quiz", "survey" ], - "author": "Ian Walter (https://iankwalter.com)", - "license": "SEE LICENSE IN LICENSE", "bugs": { "url": "https://github.com/ianwalter/decision-tree/issues" }, diff --git a/tests.js b/tests.js index b2dc352..0b406cd 100644 --- a/tests.js +++ b/tests.js @@ -1,5 +1,5 @@ const { test } = require('@ianwalter/bff') -const DecisionTree = require('.') +const { DecisionTree, NoLeadToError } = require('.') const proficiency = { key: 'proficiency', @@ -187,3 +187,13 @@ test('can support multiple choice options where multiple are selected', ctx => { decisionTree.next() ctx.expect(decisionTree.current()).toBe(sorcerer) }) + +test('NoLeadToError', ctx => { + const decisionTree = new DecisionTree(tree) + try { + decisionTree.next() + decisionTree.next() + } catch (err) { + ctx.expect(err instanceof NoLeadToError).toBe(true) + } +})