From c8ecccaa51a1bb29e5f8f07dd4dfdcf74330be62 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:06:10 +0900 Subject: [PATCH 01/55] github actions workflow wip --- .circleci/config.yml | 143 ----------------------------- .github/workiflows/python.yaml | 60 ++++++++++++ .github/workiflows/typescript.yaml | 63 +++++++++++++ README.rst | 4 - python/ci_requirements.txt | 4 +- python/pytest.ini | 3 + python/tox.ini | 44 --------- 7 files changed, 129 insertions(+), 192 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workiflows/python.yaml create mode 100644 .github/workiflows/typescript.yaml create mode 100644 python/pytest.ini delete mode 100644 python/tox.ini diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index e420640..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,143 +0,0 @@ -version: 2 -jobs: - -# python_test: -# docker: -# - image: cimg/python:3.11.2 -# steps: -# - checkout -# - restore_cache: -# keys: -# - venv-{{ checksum "python/ci_requirements.txt"}} -# - tox-{{ checksum "python/tox.ini" }} -# -# - run: -# name: install dependencies -# command: | -# cd python/ -# python3 -m venv venv || true -# python3 -m pip install -U pip -# python3 -m pip install -r ci_requirements.txt -# -# - save_cache: -# paths: -# - python/venv -# key: venv-{{ checksum "python/ci_requirements.txt"}} -# -# - save_cache: -# paths: -# - python/.tox -# key: tox-{{ checksum "python/tox.ini" }} -# -# - run: -# name: run python tests -# command: | -# cd python/ -# venv/bin/tox -e py3112 -e black-check -e cov -e codecov -# -# python_deploy: -# docker: -# - image: cimg/python:3.11.2 -# steps: -# - checkout -# - restore_cache: -# keys: -# - venv-{{ checksum "python/ci_requirements.txt"}} -# -# - run: -# name: install dependencies -# command: | -# cd python/ -# python3 -m venv venv || true -# python3 -m pip install -U pip -# python3 -m pip install -r ci_requirements.txt -# -# - save_cache: -# paths: -# - python/venv -# key: venv-{{ checksum "python/ci_requirements.txt"}} -# -# - run: -# name: build and push -# command: | -# cd python/ -# source venv/bin/activate -# python ./setup.py sdist bdist_wheel -# venv/bin/twine upload dist/* --non-interactive --skip-existing - - node_test: - docker: - - image: circleci/node:stretch - steps: - - checkout - - restore_cache: - keys: - - node_modules-{{ checksum "typescript/package.json" }} - - - run: - name: install dependencies - command: | - cd typescript/ - npm install - - - save_cache: - paths: - - typescript/node_modules - key: node_modules-{{ checksum "typescript/package.json" }} - - - run: - name: run node tests - command: | - cd typescript/ - npm test -- --coverage - npm run codecov - - node_deploy: - docker: - - image: circleci/node:stretch - steps: - - checkout - - restore_cache: - keys: - - node_modules-{{ checksum "typescript/package.json" }} - - - run: - name: install dependencies - command: | - cd typescript/ - npm install - - - save_cache: - paths: - - typescript/node_modules - key: node_modules-{{ checksum "typescript/package.json" }} - - - run: - name: Authenticate with registry - command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > typescript/.npmrc - - - run: - name: build and push - command: | - cd typescript/ - npm run build - npm publish || true - -workflows: - version: 2 - test_deploy: - jobs: - - python_test - - node_test - - python_deploy: - filters: - branches: - only: master - requires: - - python_test - - node_deploy: - filters: - branches: - only: master - requires: - - node_test \ No newline at end of file diff --git a/.github/workiflows/python.yaml b/.github/workiflows/python.yaml new file mode 100644 index 0000000..68e2fbc --- /dev/null +++ b/.github/workiflows/python.yaml @@ -0,0 +1,60 @@ +name: python +on: + push: + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.7", "3.11"] + defaults: + run: + working-directory: python + + steps: + - uses: actions/checkout@v3 + - name: setup + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: install + run: | + python -m pip install --upgrade pip + python -m pip install -r ci_requirements.txt + - name: test + run: | + pytest --cov=covertable + - name: codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + + release: + needs: tests + runs-on: ubuntu-latest + defaults: + run: + working-directory: python + if: github.ref == 'refs/heads/master' + name: npm upload + steps: + - uses: actions/checkout@v3 + - name: setup + uses: actions/setup-python@v4 + with: + python-version: 3.11 + - name: install + run: | + python -m pip install --upgrade pip + python -m pip install -r ci_requirements.txt + - name: build + run: | + python ./setup.py sdist bdist_wheel + twine upload dist/* --non-interactive --skip-existing + - name: upload + run: twine upload dist/* --non-interactive --skip-existing + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workiflows/typescript.yaml b/.github/workiflows/typescript.yaml new file mode 100644 index 0000000..480de1a --- /dev/null +++ b/.github/workiflows/typescript.yaml @@ -0,0 +1,63 @@ +name: typescript +on: + push: + +jobs: + tests: + runs-on: ubuntu-latest + defaults: + run: + working-directory: typescript + + steps: + - uses: actions/checkout@v3 + - name: setup + uses: actions/setup-node@v3 + with: + node-version: "16" + - name: cache + uses: actions/cache@v3 + with: + path: | + node_modules + key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} + - name: install + run: | + npm install + - name: test + run: | + npm test -- --coverage + npm run codecov + - name: codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + + release: + needs: tests + runs-on: ubuntu-latest + defaults: + run: + working-directory: typescript + + if: github.ref == 'refs/heads/master' + name: npm upload + steps: + - uses: actions/checkout@v3 + - name: setup + uses: actions/setup-node@v3 + with: + node-version: "16" + - name: cache + uses: actions/cache@v3 + with: + path: | + node_modules + key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} + - name: upload + run: | + npm install + npm run build + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc + npm run publish || true diff --git a/README.rst b/README.rst index 4b554e8..fd3d597 100644 --- a/README.rst +++ b/README.rst @@ -200,7 +200,3 @@ History :1.0.x: - First release 🎉 - -.. note:: - - It moved from `twopairs`. diff --git a/python/ci_requirements.txt b/python/ci_requirements.txt index 8091e2b..03914f4 100644 --- a/python/ci_requirements.txt +++ b/python/ci_requirements.txt @@ -1,4 +1,6 @@ -tox +pytest +pytest-cov setuptools wheel twine +black diff --git a/python/pytest.ini b/python/pytest.ini new file mode 100644 index 0000000..b42ddf9 --- /dev/null +++ b/python/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +python_files = tests.py + diff --git a/python/tox.ini b/python/tox.ini deleted file mode 100644 index 460300e..0000000 --- a/python/tox.ini +++ /dev/null @@ -1,44 +0,0 @@ -[tox] -envlist = py37, blacken -skipsdist = True - -[pytest] -addopts = --durations=10 -python_paths = . -python_files = tests.py - -[testenv] -deps = - pytest - pytest-pythonpath -commands = py.test {posargs} - -[testenv:cov] -deps = - pytest - pytest-pythonpath - pytest-cov - coverage -commands = py.test {posargs} \ - --junitxml={toxinidir}/.junit.xml \ - --cov="covertable" --cov="sorters/" --cov="criteria" --cov="exceptions" - -[testenv:blacken] -basepython = python3.7 -deps = black -commands = - black . - -[testenv:black-check] -basepython = python3.7 -deps = black -commands = - black . --check - -[testenv:codecov] -passenv = - TOXENV - CI - CODECOV_* -deps = codecov -commands = codecov From 73f300013c5579b738e8060754fa96dba3355afd Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:07:38 +0900 Subject: [PATCH 02/55] typo --- .github/{workiflows => workflows}/python.yaml | 0 .github/{workiflows => workflows}/typescript.yaml | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .github/{workiflows => workflows}/python.yaml (100%) rename .github/{workiflows => workflows}/typescript.yaml (100%) diff --git a/.github/workiflows/python.yaml b/.github/workflows/python.yaml similarity index 100% rename from .github/workiflows/python.yaml rename to .github/workflows/python.yaml diff --git a/.github/workiflows/typescript.yaml b/.github/workflows/typescript.yaml similarity index 100% rename from .github/workiflows/typescript.yaml rename to .github/workflows/typescript.yaml From 63e17b5fd3e96cab4de546a38fa1e34069e19a10 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:27:38 +0900 Subject: [PATCH 03/55] update readme --- .github/workflows/python.yaml | 2 +- README.rst | 9 +++++---- python/README.rst | 4 ++-- typescript/README.md | 1 + 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 68e2fbc..4a02d0e 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -38,7 +38,7 @@ jobs: run: working-directory: python if: github.ref == 'refs/heads/master' - name: npm upload + name: pypi upload steps: - uses: actions/checkout@v3 - name: setup diff --git a/README.rst b/README.rst index fd3d597..fa58202 100644 --- a/README.rst +++ b/README.rst @@ -1,10 +1,6 @@ .. image:: ./covertable.png :alt: covertable logo - -.. image:: https://circleci.com/gh/walkframe/covertable.svg?style=shield - :target: https://circleci.com/gh/walkframe/covertable - Time is limited. It is not realistic to create a test case that satisfies all the multiple factors, @@ -19,13 +15,18 @@ Now it has 2 implementations. - .. image:: https://badge.fury.io/py/covertable.svg :target: https://badge.fury.io/py/covertable + - .. image:: https://github.com/walkframe/covertable/actions/workflows/python.yaml/badge.svg + :target: https://github.com/walkframe/covertable/actions/workflows/python.yaml - `README `__ - `Code `__ + :TypeScript: - .. image:: https://badge.fury.io/js/covertable.svg :target: https://badge.fury.io/js/covertable + - .. image:: https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg + :target: https://github.com/walkframe/covertable/actions/workflows/typescript.yaml - `README `__ - `Code `__ diff --git a/python/README.rst b/python/README.rst index c06c2d3..30154ec 100644 --- a/python/README.rst +++ b/python/README.rst @@ -1,8 +1,8 @@ .. image:: https://badge.fury.io/py/covertable.svg :target: https://badge.fury.io/py/covertable -.. image:: https://circleci.com/gh/walkframe/covertable.svg?style=shield - :target: https://circleci.com/gh/walkframe/covertable +.. image:: https://github.com/walkframe/covertable/actions/workflows/python.yaml/badge.svg + :target: https://github.com/walkframe/covertable/actions/workflows/python.yaml .. image:: https://codecov.io/gh/walkframe/covertable/branch/master/graph/badge.svg :target: https://codecov.io/gh/walkframe/covertable diff --git a/typescript/README.md b/typescript/README.md index 7259b70..dcdaace 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -1,4 +1,5 @@ [![npm version](https://badge.fury.io/js/covertable.svg)](https://badge.fury.io/js/covertable) +[![Workflow](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) [![CircleCI](https://circleci.com/gh/walkframe/covertable.svg?style=shield)](https://circleci.com/gh/walkframe/covertable) [![codecov](https://codecov.io/gh/walkframe/covertable/branch/master/graph/badge.svg)](https://codecov.io/gh/walkframe/covertable) From 8a39e5d7d27133a9db05bab981d3c04bfbccf8f8 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:33:00 +0900 Subject: [PATCH 04/55] username --- .github/workflows/python.yaml | 2 +- python/README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 4a02d0e..08a3b24 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -56,5 +56,5 @@ jobs: - name: upload run: twine upload dist/* --non-interactive --skip-existing env: - TWINE_USERNAME: __token__ + TWINE_USERNAME: righ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} diff --git a/python/README.rst b/python/README.rst index 30154ec..d983654 100644 --- a/python/README.rst +++ b/python/README.rst @@ -17,7 +17,7 @@ Requirements ============ - Python: 3.3 or later. - - Tested with 3.7 + - Tested with 3.7, 3.11 Installation From a9b000afb0fa487270202aa695b0a384ae435699 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:39:41 +0900 Subject: [PATCH 05/55] delete badge --- typescript/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/typescript/README.md b/typescript/README.md index dcdaace..f655ee6 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -1,6 +1,5 @@ [![npm version](https://badge.fury.io/js/covertable.svg)](https://badge.fury.io/js/covertable) [![Workflow](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) -[![CircleCI](https://circleci.com/gh/walkframe/covertable.svg?style=shield)](https://circleci.com/gh/walkframe/covertable) [![codecov](https://codecov.io/gh/walkframe/covertable/branch/master/graph/badge.svg)](https://codecov.io/gh/walkframe/covertable) # Installation From a86be1bcab0db8e865033f081c9e1deb449a845e Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:42:18 +0900 Subject: [PATCH 06/55] publish --- .github/workflows/typescript.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/typescript.yaml b/.github/workflows/typescript.yaml index 480de1a..4b43e7e 100644 --- a/.github/workflows/typescript.yaml +++ b/.github/workflows/typescript.yaml @@ -60,4 +60,4 @@ jobs: npm install npm run build echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc - npm run publish || true + npm publish || true From 85bd7e050fb25b5df179e87da7ae855ee496c977 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:47:08 +0900 Subject: [PATCH 07/55] token --- .github/workflows/python.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 08a3b24..00a4d88 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -56,5 +56,5 @@ jobs: - name: upload run: twine upload dist/* --non-interactive --skip-existing env: - TWINE_USERNAME: righ + TWINE_USERNAME: token TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} From 678eb30e37675bc225b32cf1c197032b936eeeb1 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 18:55:40 +0900 Subject: [PATCH 08/55] delete --- .github/workflows/python.yaml | 1 - .github/workflows/typescript.yaml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 00a4d88..5047626 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -52,7 +52,6 @@ jobs: - name: build run: | python ./setup.py sdist bdist_wheel - twine upload dist/* --non-interactive --skip-existing - name: upload run: twine upload dist/* --non-interactive --skip-existing env: diff --git a/.github/workflows/typescript.yaml b/.github/workflows/typescript.yaml index 4b43e7e..f57b8ff 100644 --- a/.github/workflows/typescript.yaml +++ b/.github/workflows/typescript.yaml @@ -61,3 +61,4 @@ jobs: npm run build echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc npm publish || true + From 2a01cd431a92c574bd228969898e006b916430d7 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 20:24:04 +0900 Subject: [PATCH 09/55] make async and rename --- .github/workflows/python.yaml | 3 +- python/.gitignore | 3 +- python/covertable/criteria/greedy.py | 10 ++-- python/covertable/criteria/simple.py | 4 +- python/covertable/main.py | 86 +++++++++++++++++----------- python/covertable/sorters/hash.py | 4 +- python/covertable/sorters/random.py | 4 +- typescript/src/criteria/greedy.ts | 14 ++--- typescript/src/criteria/simple.ts | 6 +- typescript/src/index.ts | 24 ++++---- typescript/src/types.ts | 4 +- 11 files changed, 93 insertions(+), 69 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 5047626..8a57765 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -24,11 +24,12 @@ jobs: python -m pip install -r ci_requirements.txt - name: test run: | - pytest --cov=covertable + pytest --cov=covertable --cov-report=xml - name: codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml verbose: true release: diff --git a/python/.gitignore b/python/.gitignore index 5f5970b..ba7e8c5 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -3,9 +3,10 @@ __pycache__/ .tox/ venv/ .coverage +coverage.xml .junit.xml htmlcov/ pip-wheel-metadata *.egg-info build/ -dist/ \ No newline at end of file +dist/ diff --git a/python/covertable/criteria/greedy.py b/python/covertable/criteria/greedy.py index 389a2d6..27953be 100644 --- a/python/covertable/criteria/greedy.py +++ b/python/covertable/criteria/greedy.py @@ -3,19 +3,19 @@ from itertools import combinations -def get_num_removable_pairs(indexes, incompleted, length): +def get_num_removable_pairs(indexes, incomplete, length): removing_keys = combinations(indexes, length) - return len(incompleted.intersection(removing_keys)) + return len(incomplete.intersection(removing_keys)) def extract( - sorted_incompleted, row, parents, length, incompleted, tolerance=0, **kwargs + sorted_incomplete, row, parents, length, incomplete, tolerance=0, **kwargs ): while True: max_num_pairs = None efficient_pair = None - for pair in sorted_incompleted: + for pair in sorted_incomplete: if not row: yield pair continue @@ -31,7 +31,7 @@ def extract( continue num_pairs = get_num_removable_pairs( - sorted({*row.values(), *pair}), incompleted, length + sorted({*row.values(), *pair}), incomplete, length ) if num_pairs + tolerance > len(row) * storable: efficient_pair = pair diff --git a/python/covertable/criteria/simple.py b/python/covertable/criteria/simple.py index b14f5ea..66517a8 100644 --- a/python/covertable/criteria/simple.py +++ b/python/covertable/criteria/simple.py @@ -1,5 +1,5 @@ -def extract(sorted_incompleted, row, parents, **kwargs): - for pair in sorted_incompleted: +def extract(sorted_incomplete, row, parents, **kwargs): + for pair in sorted_incomplete: storable = row.storable([(parents[p], p) for p in pair]) if storable is None: continue diff --git a/python/covertable/main.py b/python/covertable/main.py index 1e5c490..7fb519c 100644 --- a/python/covertable/main.py +++ b/python/covertable/main.py @@ -29,12 +29,12 @@ def convert_factors_to_serials(factors): return serials, parents -def make_incompleted(serials, length): - incompleted = set() +def make_incomplete(serials, length): + incomplete = set() for keys in combinations([k for k, _ in get_items(serials)], length): for pair in product(*[serials[keys[i]] for i in range(length)]): - incompleted.add(pair) - return incompleted + incomplete.add(pair) + return incomplete class Row(dict): @@ -65,7 +65,7 @@ def storable(self, candidate=[]): if self.pre_filter is None: return num nxt = self.new({**self, **dict(candidate)}) - if not self.pre_filter(nxt.restore()): + if not self.pre_filter(nxt.resolve()): return None return num @@ -79,14 +79,21 @@ def complement(self): raise InvalidCondition(InvalidCondition.message) return self - def restore(self): + def resolve(self): return self.new( [key, self.factors[key][serial - self.serials[key][0]]] for key, serial in self.items() ) + def restore(self): + resolved = self.resolve() + if issubclass(self.type, list): + return [r for _, r in sorted(resolved.items())] + if issubclass(self.type, dict): + return dict(resolved) + -def make( +def make_async( factors, length=2, progress=False, @@ -97,20 +104,21 @@ def make( **params, ): serials, parents = convert_factors_to_serials(factors) - incompleted = make_incompleted(serials, length) - len_incompleted = float(len(incompleted)) + incomplete = make_incomplete(serials, length) + len_incomplete = float(len(incomplete)) md5_cache = {} - rows, row = [], Row(None, factors, serials, pre_filter) + row = Row(None, factors, serials, pre_filter) # When pre_filter is specified, - # it will be applied to incompleted through `row.storable` beforehand. - for pair in list(filter(lambda _: pre_filter, incompleted)): + # it will be applied to incomplete through `row.storable` beforehand. + for pair in list(filter(lambda _: pre_filter, incomplete)): ######### if not row.storable([(parents[p], p) for p in pair]): - incompleted.discard(pair) + incomplete.discard(pair) - while incompleted: + while incomplete: if row.filled(): - rows.append(row) + if post_filter is None or post_filter(row.resolve()): + yield row.restore() row = row.new() common_kwargs = { @@ -118,34 +126,48 @@ def make( "row": row, "parents": parents, "length": length, - "incompleted": incompleted, + "incomplete": incomplete, "md5_cache": md5_cache, } - sorted_incompleted = sorter.sort(**common_kwargs) - for pair in criterion.extract(sorted_incompleted, **common_kwargs): + sorted_incomplete = sorter.sort(**common_kwargs) + for pair in criterion.extract(sorted_incomplete, **common_kwargs): if row.filled(): break row.update((parents[p], p) for p in pair) for vs in combinations(sorted(row.values()), length): - incompleted.discard(vs) + incomplete.discard(vs) else: if not row.filled(): row.complement() if progress: - rate = (len_incompleted - len(incompleted)) / len_incompleted + rate = (len_incomplete - len(incomplete)) / len_incomplete print("{0:.2%}\r".format(rate), end="") if row: - rows.append(row.complement()) - - result = [] - for row in rows: - restored = row.restore() - if post_filter and not post_filter(restored): - continue - if issubclass(row.type, list): - result.append([r for _, r in sorted(restored.items())]) - elif issubclass(row.type, dict): - result.append(dict(restored)) - return result + row.complement() + if post_filter is None or post_filter(row.resolve()): + yield row.restore() + + +def make( + factors, + length=2, + progress=False, + sorter=sorters.hash, + criterion=criteria.greedy, + pre_filter=None, + post_filter=None, + **params, +): + gen = make_async( + factors, + length=length, + progress=progress, + sorter=sorter, + criterion=criterion, + pre_filter=pre_filter, + post_filter=post_filter, + **params, + ) + return list(gen) diff --git a/python/covertable/sorters/hash.py b/python/covertable/sorters/hash.py index ec2238d..4e433d8 100644 --- a/python/covertable/sorters/hash.py +++ b/python/covertable/sorters/hash.py @@ -4,7 +4,7 @@ import hashlib -def sort(incompleted, md5_cache, seed="", use_cache=True, *args, **kwargs): +def sort(incomplete, md5_cache, seed="", use_cache=True, *args, **kwargs): def comparer(v): if use_cache and v in md5_cache: return md5_cache[v] @@ -15,4 +15,4 @@ def comparer(v): md5_cache[v] = value return value - return sorted(incompleted, key=comparer) + return sorted(incomplete, key=comparer) diff --git a/python/covertable/sorters/random.py b/python/covertable/sorters/random.py index 67cbfcf..8851b1f 100644 --- a/python/covertable/sorters/random.py +++ b/python/covertable/sorters/random.py @@ -8,5 +8,5 @@ def random_comparer(_): return random.random() -def sort(incompleted, *args, **kwargs): - return sorted(incompleted, key=random_comparer) +def sort(incomplete, *args, **kwargs): + return sorted(incomplete, key=random_comparer) diff --git a/typescript/src/criteria/greedy.ts b/typescript/src/criteria/greedy.ts index 46c92ae..688d2cf 100644 --- a/typescript/src/criteria/greedy.ts +++ b/typescript/src/criteria/greedy.ts @@ -1,12 +1,12 @@ -import {CriterionArgsType, IncompletedType, PairType} from '../types'; +import {CriterionArgsType, IncompleteType, PairType} from '../types'; import {getCandidate, combinations, ascOrder, unique} from '../utils'; -const getNumRemovablePairs = (indexes: Set, incompleted: IncompletedType, length: number) => { +const getNumRemovablePairs = (indexes: Set, incomplete: IncompleteType, length: number) => { let num = 0; const removingKeys = combinations([... indexes], length); for (let pair of removingKeys) { const key = unique(pair); - if (incompleted.has(key)) { + if (incomplete.has(key)) { num++; } } @@ -14,7 +14,7 @@ const getNumRemovablePairs = (indexes: Set, incompleted: IncompletedType }; export default function* ( - incompleted: IncompletedType, + incomplete: IncompleteType, criterionArgs: CriterionArgsType, ): Generator { let {row, parents, length, tolerance} = criterionArgs; @@ -23,7 +23,7 @@ export default function* ( let maxNumPairs: number | null = null; let efficientPair: PairType | null = null; - for (let [pairKey, pair] of incompleted.entries()) { + for (let [pairKey, pair] of incomplete.entries()) { const rowSize = row.size; if (rowSize === 0) { yield pair; @@ -39,12 +39,12 @@ export default function* ( } if (storable === 0) { - incompleted.delete(pairKey); + incomplete.delete(pairKey); continue; } const numPairs = getNumRemovablePairs( - new Set([... row.values(), ...pair]), incompleted, length + new Set([... row.values(), ...pair]), incomplete, length ); if (numPairs + tolerance > rowSize * storable) { diff --git a/typescript/src/criteria/simple.ts b/typescript/src/criteria/simple.ts index 8ec9515..f42cee6 100644 --- a/typescript/src/criteria/simple.ts +++ b/typescript/src/criteria/simple.ts @@ -1,12 +1,12 @@ -import {CriterionArgsType, IncompletedType, PairType} from '../types'; +import {CriterionArgsType, IncompleteType, PairType} from '../types'; import {getCandidate} from '../utils'; export default function* ( - incompleted: IncompletedType, + incomplete: IncompleteType, criterionArgs: CriterionArgsType, ): Generator { const {row, parents} = criterionArgs; - for (let pair of incompleted.values()) { + for (let pair of incomplete.values()) { const storable = row.storable(getCandidate(pair, parents)); if (storable === null || storable === 0) { continue; diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 2f9949f..41234c5 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -19,7 +19,7 @@ import { MappingTypes, Scalar, Dict, - IncompletedType, + IncompleteType, ParentsType, CandidateType, RowType, @@ -52,12 +52,12 @@ const serialize = (factors: FactorsType): MappingTypes => { return { serials, parents, indices }; }; -const makeIncompleted = ( +const makeIncomplete = ( mappings: MappingTypes, length: number, sorter: SorterType, seed: Scalar -): IncompletedType => { +): IncompleteType => { const { serials, indices } = mappings; const pairs: PairType[] = []; const allKeys = getItems(serials).map(([k, _]) => k); @@ -68,11 +68,11 @@ const makeIncompleted = ( pairs.push(pair); } } - const incompleted: IncompletedType = new Map(); + const incomplete: IncompleteType = new Map(); for (let pair of sorter(pairs, { seed, indices })) { - incompleted.set(unique(pair), pair); + incomplete.set(unique(pair), pair); } - return incompleted; + return incomplete; }; class Row extends Map implements RowType { @@ -183,16 +183,16 @@ const makeAsync = function* ( const { preFilter, postFilter } = options; const mappings = serialize(factors); const { parents } = mappings; - const incompleted = makeIncompleted(mappings, length, sorter, seed); // {"1,2": [1,2], "3,4": [3,4]} + const incomplete = makeIncomplete(mappings, length, sorter, seed); // {"1,2": [1,2], "3,4": [3,4]} let row: Row = new Row([], mappings, factors, preFilter); - for (let [pairKey, pair] of incompleted.entries()) { + for (let [pairKey, pair] of incomplete.entries()) { if (!row.storable(getCandidate(pair, parents))) { - incompleted.delete(pairKey); + incomplete.delete(pairKey); } } - while (incompleted.size) { + while (incomplete.size) { if (row.filled()) { if (!postFilter || postFilter(row.toObject())) { yield row.restore() as SuggestRowType; @@ -200,7 +200,7 @@ const makeAsync = function* ( row = row.New([]); } let finished = true; - for (let pair of criterion(incompleted, { + for (let pair of criterion(incomplete, { row, parents, length, @@ -216,7 +216,7 @@ const makeAsync = function* ( } for (let p of combinations([...row.values()], length)) { - incompleted.delete(unique(p)); + incomplete.delete(unique(p)); } } if (finished && !row.filled()) { diff --git a/typescript/src/types.ts b/typescript/src/types.ts index 787f31f..c55d536 100644 --- a/typescript/src/types.ts +++ b/typescript/src/types.ts @@ -19,7 +19,7 @@ export type FilterType = (row: { export type PairType = number[]; -export type IncompletedType = Map; +export type IncompleteType = Map; export type CandidateType = [Scalar, number][]; @@ -52,7 +52,7 @@ export interface CriterionArgsType { export interface OptionsType { length?: number; sorter?: SorterType; - criterion?: (incompleted: IncompletedType, options: CriterionArgsType) => IterableIterator; + criterion?: (incomplete: IncompleteType, options: CriterionArgsType) => IterableIterator; seed?: Scalar; tolerance?: number; preFilter?: FilterType; From 665eeb42cbb0838a84b906c95319498b1bc14442 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 20:38:53 +0900 Subject: [PATCH 10/55] version 2.1.0 for python --- python/README.rst | 2 +- python/setup.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/README.rst b/python/README.rst index d983654..07e5389 100644 --- a/python/README.rst +++ b/python/README.rst @@ -158,7 +158,7 @@ Development (venv) $ pip install -r dev_requirements.txt # testing - (venv) $ tox # -e py37 -e cov -e black + (venv) $ pytest Publish diff --git a/python/setup.cfg b/python/setup.cfg index ceb5e32..65df6ed 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = covertable -version = 2.0.1 +version = 2.1.0 author = righ author_email = righ.m9@gmail.com url = https://github.com/walkframe/covertable/ @@ -36,5 +36,5 @@ keywords = covering-arrays pict -description = It makes combinations covering pairs for pairwise testing. +description = A flexible pairwise tool written in Python. long_description = file: README.rst From 036026eccb9e2ad8cb1649ed945c07ac6cd56c62 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 20:42:27 +0900 Subject: [PATCH 11/55] use action --- .github/workflows/python.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 8a57765..9e9e4e9 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -54,7 +54,7 @@ jobs: run: | python ./setup.py sdist bdist_wheel - name: upload - run: twine upload dist/* --non-interactive --skip-existing - env: - TWINE_USERNAME: token - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} From 04ab0ac2346ab7b34096a978aed4761f66e70ee5 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 20:45:00 +0900 Subject: [PATCH 12/55] update version --- .github/workflows/python.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 9e9e4e9..41fdf40 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -54,7 +54,7 @@ jobs: run: | python ./setup.py sdist bdist_wheel - name: upload - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} From b8bcfd90eec42f15bc796a7cf46e0d78ccf55de6 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 20:55:21 +0900 Subject: [PATCH 13/55] update --- .github/workflows/python.yaml | 2 ++ python/ci_requirements.txt | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 41fdf40..ef6e610 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -53,8 +53,10 @@ jobs: - name: build run: | python ./setup.py sdist bdist_wheel + ls -l dist/ - name: upload uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} + skip_existing: true diff --git a/python/ci_requirements.txt b/python/ci_requirements.txt index 03914f4..3fbff8a 100644 --- a/python/ci_requirements.txt +++ b/python/ci_requirements.txt @@ -2,5 +2,3 @@ pytest pytest-cov setuptools wheel -twine -black From 6a915a8ef3e2834ed56edda2dbeeece47b146775 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 21:10:03 +0900 Subject: [PATCH 14/55] update --- .github/workflows/python.yaml | 5 ++--- python/ci_requirements.txt | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index ef6e610..6537057 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -45,15 +45,14 @@ jobs: - name: setup uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: 3.10 - name: install run: | python -m pip install --upgrade pip python -m pip install -r ci_requirements.txt - name: build run: | - python ./setup.py sdist bdist_wheel - ls -l dist/ + python -m build --sdist --wheel --outdir dist/ . - name: upload uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/python/ci_requirements.txt b/python/ci_requirements.txt index 3fbff8a..15c1add 100644 --- a/python/ci_requirements.txt +++ b/python/ci_requirements.txt @@ -1,4 +1,3 @@ pytest pytest-cov -setuptools -wheel +build From 11e55600ecffd50aa3e75cb5e85e7eb1cb62994c Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 21:12:08 +0900 Subject: [PATCH 15/55] stringify --- .github/workflows/python.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 6537057..908880c 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -45,7 +45,7 @@ jobs: - name: setup uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: "3.10" - name: install run: | python -m pip install --upgrade pip From 2624af24875b4f844c5b440e3c294694cb08784a Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 22:10:02 +0900 Subject: [PATCH 16/55] specify dist --- .github/workflows/python.yaml | 1 + python/covertable/main.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 908880c..7a33ae0 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -58,4 +58,5 @@ jobs: with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} + package: dist/* skip_existing: true diff --git a/python/covertable/main.py b/python/covertable/main.py index 7fb519c..7d86b9b 100644 --- a/python/covertable/main.py +++ b/python/covertable/main.py @@ -111,7 +111,7 @@ def make_async( row = Row(None, factors, serials, pre_filter) # When pre_filter is specified, # it will be applied to incomplete through `row.storable` beforehand. - for pair in list(filter(lambda _: pre_filter, incomplete)): ######### + for pair in list(filter(lambda _: pre_filter, incomplete)): if not row.storable([(parents[p], p) for p in pair]): incomplete.discard(pair) From 691b237b6a7df88df48045207b8d41efc34d7c5f Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 22:18:36 +0900 Subject: [PATCH 17/55] debug --- .github/workflows/python.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 7a33ae0..f13142b 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -53,6 +53,9 @@ jobs: - name: build run: | python -m build --sdist --wheel --outdir dist/ . + ls -la + ls -la dist + pwd - name: upload uses: pypa/gh-action-pypi-publish@release/v1 with: From ecc97e19f69443c9fdfee15a563aa6d6964d928e Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 22:32:54 +0900 Subject: [PATCH 18/55] upload by twine --- .github/workflows/python.yaml | 7 +++++++ python/ci_requirements.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index f13142b..5b70702 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -53,9 +53,16 @@ jobs: - name: build run: | python -m build --sdist --wheel --outdir dist/ . + - name: Upload + run: | ls -la ls -la dist pwd + twine upload dist/* --non-interactive --skip-existing + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + - name: upload uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/python/ci_requirements.txt b/python/ci_requirements.txt index 15c1add..e577f2f 100644 --- a/python/ci_requirements.txt +++ b/python/ci_requirements.txt @@ -1,3 +1,4 @@ pytest pytest-cov build +twine From 174802912af7008dc3c04e3ad566627489cb3a2a Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 22:36:20 +0900 Subject: [PATCH 19/55] do not use pypa/gh-action-pypi-publish@release/v1 --- .github/workflows/python.yaml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 5b70702..27fd6d1 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -53,20 +53,9 @@ jobs: - name: build run: | python -m build --sdist --wheel --outdir dist/ . - - name: Upload + - name: upload run: | - ls -la - ls -la dist - pwd twine upload dist/* --non-interactive --skip-existing env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - - - name: upload - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} - package: dist/* - skip_existing: true From 737ae17b37742afb58ef8dbb1e3e1fe0ae9d7ff8 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 22:47:48 +0900 Subject: [PATCH 20/55] codecov --- .github/workflows/python.yaml | 1 + python/ci_requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 27fd6d1..c4e2f01 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -25,6 +25,7 @@ jobs: - name: test run: | pytest --cov=covertable --cov-report=xml + codecov - name: codecov uses: codecov/codecov-action@v3 with: diff --git a/python/ci_requirements.txt b/python/ci_requirements.txt index e577f2f..2e4f605 100644 --- a/python/ci_requirements.txt +++ b/python/ci_requirements.txt @@ -1,4 +1,5 @@ pytest pytest-cov +codecov build twine From 6f99e8567b8801478c61c305fc115dc4e83d2a75 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 23:10:26 +0900 Subject: [PATCH 21/55] use action --- .github/workflows/python.yaml | 3 +-- .github/workflows/typescript.yaml | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index c4e2f01..67b27bc 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -25,12 +25,11 @@ jobs: - name: test run: | pytest --cov=covertable --cov-report=xml - codecov - name: codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} - file: ./coverage.xml + file: ./python/coverage.xml verbose: true release: diff --git a/.github/workflows/typescript.yaml b/.github/workflows/typescript.yaml index f57b8ff..bd7b039 100644 --- a/.github/workflows/typescript.yaml +++ b/.github/workflows/typescript.yaml @@ -27,11 +27,12 @@ jobs: - name: test run: | npm test -- --coverage - npm run codecov + # npm run codecov - name: codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} + file: ./python/coverage/lcov.info verbose: true release: From 2e66202c36318608dd03a6e73574a721d6a0f4b7 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 19 Feb 2023 23:14:28 +0900 Subject: [PATCH 22/55] fix path --- .github/workflows/typescript.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/typescript.yaml b/.github/workflows/typescript.yaml index bd7b039..536e942 100644 --- a/.github/workflows/typescript.yaml +++ b/.github/workflows/typescript.yaml @@ -32,7 +32,7 @@ jobs: uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} - file: ./python/coverage/lcov.info + file: ./typescript/coverage/lcov.info verbose: true release: From f0ea342bea3977383a597b22371e11c05a4798e9 Mon Sep 17 00:00:00 2001 From: righ Date: Mon, 5 Aug 2024 03:25:16 +0900 Subject: [PATCH 23/55] pict constraints --- typescript/src/__tests__/pict.test.ts | 250 +++++++++++++++++ typescript/src/types.ts | 6 +- typescript/src/utils/pict.ts | 378 ++++++++++++++++++++++++++ 3 files changed, 632 insertions(+), 2 deletions(-) create mode 100644 typescript/src/__tests__/pict.test.ts create mode 100644 typescript/src/utils/pict.ts diff --git a/typescript/src/__tests__/pict.test.ts b/typescript/src/__tests__/pict.test.ts new file mode 100644 index 0000000..808057e --- /dev/null +++ b/typescript/src/__tests__/pict.test.ts @@ -0,0 +1,250 @@ +import { PictConstraintsLexer } from "../utils/pict"; + +describe('PictConstraintsLexer with single constraints', () => { + it('should filter correctly with LIKE and IN conditions', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] LIKE "Alic?" THEN [STATUS] IN {"Active", "Pending"} ELSE [AGE] > 20 OR [COUNTRY] = "USA"; + `, false); + const row1 = { NAME: 'Alice', STATUS: 'Active' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', STATUS: 'Inactive' }; + expect(lexer.filter(row2)).toBe(false); + }); + + it('should filter correctly with numeric conditions', () => { + const lexer = new PictConstraintsLexer(` + IF [PRICE] > 100 THEN [DISCOUNT] = "YES" ELSE [DISCOUNT] = "NO"; + `, false); + const row1 = { PRICE: 150, DISCOUNT: 'YES' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { PRICE: 90, DISCOUNT: 'NO' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { PRICE: 90, DISCOUNT: 'YES' }; + expect(lexer.filter(row3)).toBe(false); + }); + + it('should handle NOT conditions correctly', () => { + const lexer = new PictConstraintsLexer(` + IF NOT [PRODUCT] = "Book" THEN [AVAILABLE] = "Yes" ELSE [AVAILABLE] = "No"; + `, false); + const row1 = { PRODUCT: 'Pen', AVAILABLE: 'Yes' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { PRODUCT: 'Book', AVAILABLE: 'No' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { PRODUCT: 'Pen', AVAILABLE: 'No' }; + expect(lexer.filter(row3)).toBe(false); + }); + + it('should filter with AND conditions', () => { + const lexer = new PictConstraintsLexer(` + IF [CATEGORY] = "Electronics" AND [BRAND] = "Sony" THEN [WARRANTY] = "Included" ELSE [WARRANTY] = "Not Included"; + `, false); + const row1 = { CATEGORY: 'Electronics', BRAND: 'Sony', WARRANTY: 'Included' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { CATEGORY: 'Electronics', BRAND: 'Samsung', WARRANTY: 'Not Included' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { CATEGORY: 'Electronics', BRAND: 'Sony', WARRANTY: 'Not Included' }; + expect(lexer.filter(row3)).toBe(false); + }); + + it('should handle nested conditions with parentheses', () => { + const lexer = new PictConstraintsLexer(` + IF ([CATEGORY] = "Electronics" AND [BRAND] = "Sony") OR [BRAND] = "Apple" THEN [WARRANTY] = "Included" ELSE [WARRANTY] = "Not Included"; + `, false); + const row1 = { CATEGORY: 'Electronics', BRAND: 'Sony', WARRANTY: 'Included' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { CATEGORY: 'Electronics', BRAND: 'Apple', WARRANTY: 'Included' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { CATEGORY: 'Furniture', BRAND: 'IKEA', WARRANTY: 'Not Included' }; + expect(lexer.filter(row3)).toBe(true); + + const row4 = { CATEGORY: 'Electronics', BRAND: 'Samsung', WARRANTY: 'Included' }; + expect(lexer.filter(row4)).toBe(false); + }); + + it('should handle string equality conditions', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE [STATUS] = "Active"; + `, false); + const row1 = { NAME: 'Bob', STATUS: 'Inactive' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', STATUS: 'Active' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { NAME: 'Bob', STATUS: 'Active' }; + expect(lexer.filter(row3)).toBe(false); + }); + + it('should handle IN conditions', () => { + const lexer = new PictConstraintsLexer(` + IF [COLOR] IN {"Red", "Blue", "Green"} THEN [CATEGORY] = "Primary" ELSE [CATEGORY] = "Secondary"; + `, false); + const row1 = { COLOR: 'Red', CATEGORY: 'Primary' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { COLOR: 'Yellow', CATEGORY: 'Secondary' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { COLOR: 'Red', CATEGORY: 'Secondary' }; + expect(lexer.filter(row3)).toBe(false); + }); + + it('should handle complex conditions with nested parentheses', () => { + const lexer = new PictConstraintsLexer(` + IF ([AGE] > 20 AND ([COUNTRY] = "USA" OR [COUNTRY] = "Canada")) THEN [STATUS] = "Allowed" ELSE [STATUS] = "Denied"; + `, false); + const row1 = { AGE: 25, COUNTRY: 'USA', STATUS: 'Allowed' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { AGE: 18, COUNTRY: 'USA', STATUS: 'Denied' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { AGE: 25, COUNTRY: 'UK', STATUS: 'Denied' }; + expect(lexer.filter(row3)).toBe(true); + + const row4 = { AGE: 25, COUNTRY: 'Canada', STATUS: 'Allowed' }; + expect(lexer.filter(row4)).toBe(true); + + const row5 = { AGE: 25, COUNTRY: 'Canada', STATUS: 'Denied' }; + expect(lexer.filter(row5)).toBe(false); + }); +}); + +describe('PictConstraintsLexer with multiple constraints', () => { + it('should handle multiple constraints correctly (Test Case 1)', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Alice" THEN [AGE] > 20 ELSE [AGE] < 20; + IF [COUNTRY] = "USA" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"; + `, false); + + const row1 = { NAME: 'Alice', AGE: 25, COUNTRY: 'USA', STATUS: 'Active' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', AGE: 25, COUNTRY: 'Canada', STATUS: 'Inactive' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { NAME: 'Alice', AGE: 18, COUNTRY: 'USA', STATUS: 'Active' }; + expect(lexer.filter(row3)).toBe(false); + + const row4 = { NAME: 'Bob', AGE: 15, COUNTRY: 'USA', STATUS: 'Inactive' }; + expect(lexer.filter(row4)).toBe(false); + }); + + it('should handle multiple constraints correctly (Test Case 2)', () => { + const lexer = new PictConstraintsLexer(` + IF [SCORE] >= 90 THEN [GRADE] = "A" ELSE [GRADE] = "B"; + IF [MEMBER] = "YES" THEN [DISCOUNT] = "20%" ELSE [DISCOUNT] = "10%"; + `, false); + + const row1 = { SCORE: 95, GRADE: 'A', MEMBER: 'YES', DISCOUNT: '20%' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { SCORE: 85, GRADE: 'B', MEMBER: 'NO', DISCOUNT: '10%' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { SCORE: 85, GRADE: 'B', MEMBER: 'YES', DISCOUNT: '20%' }; + expect(lexer.filter(row3)).toBe(true); + + const row4 = { SCORE: 85, GRADE: 'A', MEMBER: 'YES', DISCOUNT: '10%' }; + expect(lexer.filter(row4)).toBe(false); + }); + + it('should handle multiple constraints correctly (Test Case 3)', () => { + const lexer = new PictConstraintsLexer(` + IF [TEMP] > 30 THEN [STATE] = "HOT" ELSE [STATE] = "COLD"; + IF [HUMIDITY] < 50 THEN [COMFORT] = "DRY" ELSE [COMFORT] = "HUMID"; + `, false); + + const row1 = { TEMP: 35, STATE: 'HOT', HUMIDITY: 45, COMFORT: 'DRY' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { TEMP: 25, STATE: 'COLD', HUMIDITY: 55, COMFORT: 'HUMID' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { TEMP: 25, STATE: 'HOT', HUMIDITY: 55, COMFORT: 'DRY' }; + expect(lexer.filter(row3)).toBe(false); + + const row4 = { TEMP: 35, STATE: 'HOT', HUMIDITY: 55, COMFORT: 'HUMID' }; + expect(lexer.filter(row4)).toBe(true); + }); + + it('should handle multiple constraints correctly (Test Case 4)', () => { + const lexer = new PictConstraintsLexer(` + IF [CATEGORY] = "Electronics" THEN [WARRANTY] = "Included" ELSE [WARRANTY] = "Not Included"; + IF [PRICE] > 100 THEN [DISCOUNT] = "YES" ELSE [DISCOUNT] = "NO"; + `, false); + + const row1 = { CATEGORY: 'Electronics', WARRANTY: 'Included', PRICE: 150, DISCOUNT: 'YES' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { CATEGORY: 'Furniture', WARRANTY: 'Not Included', PRICE: 90, DISCOUNT: 'NO' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { CATEGORY: 'Electronics', WARRANTY: 'Not Included', PRICE: 150, DISCOUNT: 'NO' }; + expect(lexer.filter(row3)).toBe(false); + + const row4 = { CATEGORY: 'Furniture', WARRANTY: 'Not Included', PRICE: 150, DISCOUNT: 'YES' }; + expect(lexer.filter(row4)).toBe(true); + }); + + it('should handle multiple constraints correctly (Test Case 5)', () => { + const lexer = new PictConstraintsLexer(` + IF [COLOR] = "Red" THEN [CATEGORY] = "Primary" ELSE [CATEGORY] = "Secondary"; + IF [QUANTITY] < 10 THEN [STOCK] = "Low" ELSE [STOCK] = "High"; + `, false); + + const row1 = { COLOR: 'Red', CATEGORY: 'Primary', QUANTITY: 5, STOCK: 'Low' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { COLOR: 'Blue', CATEGORY: 'Secondary', QUANTITY: 20, STOCK: 'High' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { COLOR: 'Red', CATEGORY: 'Secondary', QUANTITY: 5, STOCK: 'High' }; + expect(lexer.filter(row3)).toBe(false); + + const row4 = { COLOR: 'Red', CATEGORY: 'Primary', QUANTITY: 20, STOCK: 'High' }; + expect(lexer.filter(row4)).toBe(true); + }); + + it('should handle multiple constraints correctly (Test Case 6)', () => { + const lexer = new PictConstraintsLexer(` + IF [SIZE] = "Large" THEN [AVAILABILITY] = "In Stock" ELSE [AVAILABILITY] = "Out of Stock"; + IF ([DISCOUNT] = "YES" AND [MEMBER] = "YES") THEN [PRICE] < 100 ELSE [PRICE] >= 100; + `, false); + + const row1 = { SIZE: 'Large', AVAILABILITY: 'In Stock', DISCOUNT: 'YES', MEMBER: 'YES', PRICE: 90 }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { SIZE: 'Medium', AVAILABILITY: 'Out of Stock', DISCOUNT: 'NO', MEMBER: 'NO', PRICE: 120 }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { SIZE: 'Large', AVAILABILITY: 'In Stock', DISCOUNT: 'YES', MEMBER: 'NO', PRICE: 110 }; + expect(lexer.filter(row3)).toBe(true); + }); + + it('should handle multiple constraints correctly (Test Case 7)', () => { + const lexer = new PictConstraintsLexer(` + IF [SEASON] = "Winter" THEN [CLOTHING] = "Coat" ELSE [CLOTHING] = "Shirt"; + IF ([TEMP] < 0 AND [WEATHER] = "Snowy") THEN [ACTIVITY] = "Skiing" ELSE [ACTIVITY] = "Running"; + `, false); + + const row1 = { SEASON: 'Winter', CLOTHING: 'Coat', TEMP: -5, WEATHER: 'Snowy', ACTIVITY: 'Skiing' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { SEASON: 'Summer', CLOTHING: 'Shirt', TEMP: 25, WEATHER: 'Sunny', ACTIVITY: 'Running' }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { SEASON: 'Winter', CLOTHING: 'Coat', TEMP: 5, WEATHER: 'Sunny', ACTIVITY: 'Running' }; + expect(lexer.filter(row3)).toBe(true); + }); +}); diff --git a/typescript/src/types.ts b/typescript/src/types.ts index c55d536..340da9a 100644 --- a/typescript/src/types.ts +++ b/typescript/src/types.ts @@ -12,10 +12,12 @@ export type MappingTypes = { indices: IndicesType; }; -export type FilterType = (row: { +export type FilterRowType = { [key: string]: any; [index: number]: any; -}) => boolean; +} + +export type FilterType = (row: FilterRowType) => boolean; export type PairType = number[]; diff --git a/typescript/src/utils/pict.ts b/typescript/src/utils/pict.ts new file mode 100644 index 0000000..c9a38f3 --- /dev/null +++ b/typescript/src/utils/pict.ts @@ -0,0 +1,378 @@ +import { FilterType, FilterRowType } from "../types"; + +type Token = { + type: string; + value: string; +} + +type CacheType = { + [key: string]: any; +}; + +export class PictConstraintsLexer { + private tokens: Token[] = []; + private cache: CacheType = {}; + public filters: (FilterType | null)[] = []; + public errors: string[][] = []; + + constructor(private input: string, private debug=false) { + this.input = input; + this.debug = debug; + this.tokenize(); + this.analyze(); + } + private tokenize(): Token[] { + const constraints = this.input; + const tokens: Token[] = []; + let buffer = ''; + let insideQuotes = false; + let insideBraces = false; + + const addToken = (type: string, value: string) => { + tokens.push({ type, value }); + }; + + for (let i = 0; i < constraints.length; i++) { + const char = constraints[i]; + + if (char === '"') { + insideQuotes = !insideQuotes; + buffer += char; + if (!insideQuotes) { + addToken('STRING', buffer); + buffer = ''; + } + } else if (insideQuotes) { + buffer += char; + } else if (char === '[') { + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + buffer += char; + } else if (char === ']') { + buffer += char; + tokens.push(classifyToken(buffer)); + buffer = ''; + } else if (char === '{') { + insideBraces = true; + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + addToken('LBRACE', char); + } else if (char === '}') { + insideBraces = false; + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + addToken('RBRACE', char); + } else if (char === ',' && insideBraces) { + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + addToken('COMMA', char); + } else if ('[]=<>!();:'.includes(char) && !insideBraces) { + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + if (char === '<' || char === '>' || char === '!' || char === '=') { + const nextChar = constraints[i + 1]; + if (nextChar === '=') { + tokens.push(classifyToken(char + '=')); + i++; + } else if (char === '<' && nextChar === '>') { + tokens.push(classifyToken('<>')); + i++; + } else { + tokens.push(classifyToken(char)); + } + } else { + tokens.push(classifyToken(char)); + } + } else if (isWhiteSpace(char) && !insideBraces) { + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + let whitespaceBuffer = char; + while (i + 1 < constraints.length && isWhiteSpace(constraints[i + 1])) { + whitespaceBuffer += constraints[++i]; + } + addToken('WHITESPACE', whitespaceBuffer); + } else if (isWhiteSpace(char) && insideBraces) { + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + buffer = ''; + } + addToken('WHITESPACE', char); + } else { + buffer += char; + } + } + + if (buffer.length > 0) { + tokens.push(classifyToken(buffer)); + } + this.tokens = tokens; + return tokens; + } + + private analyze() { + let tokenIndex = 0; + let setIndex = 0; + let regexIndex = 0; + let errorMessages: string[] = []; + const errors: string[][] = []; + const tokens = this.tokens; + const filters: (FilterType | null)[] = []; + + const nextToken = () => { + while (tokenIndex < tokens.length && tokens[tokenIndex].type === 'WHITESPACE') { + tokenIndex++; + } + return tokenIndex < tokens.length ? tokens[tokenIndex++] : null; + } + + const parseExpression: () => string = () => { + let expr = parseTerm(); + let token = nextToken(); + while (token && token.type === 'OPERATOR' && token.value === 'OR') { + const right = parseTerm(); + expr = `(${expr} || ${right})`; + token = nextToken(); + } + tokenIndex--; // Go back one token + return expr; + } + + const parseTerm: () => string = () => { + let term = parseFactor(); + let token = nextToken(); + while (token && token.type === 'OPERATOR' && token.value === 'AND') { + const right = parseFactor(); + term = `(${term} && ${right})`; + token = nextToken(); + } + tokenIndex--; // Go back one token + return term; + } + + const parseFactor: () => string = () => { + let token = nextToken(); + if (token && token.type === 'OPERATOR' && token.value === 'NOT') { + const factor = parseFactor(); + return `!(${factor})`; + } else if (token && token.type === 'LPAREN') { + const expr = parseExpression(); + token = nextToken(); + if (!token || token.type !== 'RPAREN') { + errorMessages.push('Expected closing parenthesis'); + return 'false'; + } + return `(${expr})`; + } else { + tokenIndex--; // Go back one token + return parseCondition(); + } + } + + const parseCondition: () => string = () => { + const left = parseOperand(); + const comparerToken = nextToken(); + if (!comparerToken || comparerToken.type !== 'COMPARER') { + errorMessages.push('Expected comparer'); + return 'false'; + } + const comparer = comparerToken.value; + if (comparer === 'IN') { + const right = parseSet(); + return `${right}.has(${left})`; + } + const right = parseOperand(); + switch (comparer) { + case '=': + return `${left} === ${right}`; + case '<>': + return `${left} !== ${right}`; + case '>': + return `${left} > ${right}`; + case '<': + return `${left} < ${right}`; + case '>=': + return `${left} >= ${right}`; + case '<=': + return `${left} <= ${right}`; + case 'LIKE': + const regexPattern = right.slice(1, -1).replace(/\*/g, '.*').replace(/\?/g, '.'); // remove quotes and replace wildcards + const regexKey = `re_${regexIndex++}`; + if (!this.cache[regexKey]) { + this.cache[regexKey] = new RegExp('^' + regexPattern + '$'); + } + return `this.cache['${regexKey}'].test(${left})`; + default: + errorMessages.push(`Unknown comparer: ${comparer}`); + return 'false'; + } + } + + const parseSet: () => string = () => { + const elements: string[] = []; + let token = nextToken(); + if (token && token.type === 'LBRACE') { + token = nextToken(); + while (token && token.type !== 'RBRACE') { + if (token.type === 'STRING') { + elements.push(token.value.slice(1, -1)); // remove quotes + } else if (token.type !== 'COMMA' && token.type !== 'WHITESPACE') { + errorMessages.push(`Unexpected token: ${token.value}`); + } + token = nextToken(); + } + } else { + errorMessages.push(`Expected '{' but found ${token ? token.value : 'null'}`); + } + const setKey = `set_${setIndex++}`; + if (!this.cache[setKey]) { + this.cache[setKey] = new Set(elements); + } + return `this.cache['${setKey}']`; + } + + const parseOperand: () => string = () => { + const token = nextToken(); + if (token == null) { + errorMessages.push('Unexpected end of input'); + return 'false'; + } + if (token.type === 'REF') { + const key = token.value.slice(1, -1); // remove [ and ] + return `row["${key}"]`; + } else if (token.type === 'STRING') { + const value = token.value; // keep quotes for string literals + return `${value}`; + } else if (token.type === 'NUMBER') { + return token.value; + } else if (token.type === 'BOOLEAN') { + return token.value === 'TRUE' ? 'true' : 'false'; + } else if (token.type === 'NULL') { + return 'null'; + } else { + errorMessages.push(`Unexpected token: ${token.value}`); + return 'false'; + } + } + + while (tokenIndex < tokens.length) { + const token = nextToken(); + if (token == null) { + break; + } + if (token.type === 'IF') { + const condition = parseExpression(); + const thenToken = nextToken(); + if (!thenToken || thenToken.type !== 'THEN') { + errorMessages.push('Expected THEN'); + break; + } + const action = parseExpression(); + let elseAction = 'false'; + const elseToken = nextToken(); + if (elseToken && elseToken.type === 'ELSE') { + elseAction = parseExpression(); + } else { + tokenIndex--; // Go back one token if ELSE is not found + } + + const filterCode = `return (${condition} ? (${action}) : (${elseAction}));`; + try { + if (this.debug) { + console.log(`code[${filters.length}]:`, filterCode); + } + const f = this.makeClosure(filterCode); + filters.push(f as FilterType); + } catch (e) { + filters.push(null); + // @ts-ignore + errorMessages.push(e.message); + } + errors.push(errorMessages); + errorMessages = []; + } else if (token.type === 'SEMICOLON') { + // do nothing + } else { + errorMessages.push(`Unexpected token: ${token.value}`); + errors.push(errorMessages); + break; + } + } + this.filters = filters; + this.errors = errors; + } + + private makeClosure (code: string) { + return new Function('row', code).bind(this) as FilterType; + } + + filter(row: FilterRowType, ...additionalFilters: FilterType[]): boolean { + for (const f of this.filters) { + if (f == null) { + continue; + } + if (!f(row)) { + return false; + } + } + for (const f of additionalFilters) { + if (!f(row)) { + return false; + } + } + return true; + } +} + +function classifyToken(token: string): Token { + if (token.startsWith('[') && token.endsWith(']')) { + return { type: 'REF', value: token }; + } + if (token.startsWith('"') && token.endsWith('"')) { + return { type: 'STRING', value: token }; + } + if (!isNaN(parseFloat(token))) { + return { type: 'NUMBER', value: token }; + } + if (['TRUE', 'FALSE'].includes(token.toUpperCase())) { + return { type: 'BOOLEAN', value: token.toUpperCase() }; + } + if (token.toUpperCase() === 'NULL') { + return { type: 'NULL', value: token.toUpperCase() }; + } + if (['IF', 'ELSE', 'THEN'].includes(token.toUpperCase())) { + return { type: token.toUpperCase(), value: token.toUpperCase() }; + } + if (['=', '<>', '>', '<', '>=', '<=', 'IN', 'LIKE'].includes(token.toUpperCase())) { + return { type: 'COMPARER', value: token.toUpperCase() }; + } + if (['AND', 'OR', 'NOT'].includes(token.toUpperCase())) { + return { type: 'OPERATOR', value: token.toUpperCase() }; + } else { + switch (token) { + case '(': return { type: 'LPAREN', value: token }; + case ')': return { type: 'RPAREN', value: token }; + case '{': return { type: 'LBRACE', value: token }; + case '}': return { type: 'RBRACE', value: token }; + case ',': return { type: 'COMMA', value: token }; + case ':': return { type: 'COLON', value: token }; + case ';': return { type: 'SEMICOLON', value: token }; + default: throw new Error(`Unknown token: ${token}`); + } + } +} + +const isWhiteSpace = (char: string) => { + return char === ' ' || char === '\n' || char === '\t'; +}; From 7d37688960ee89a282c55ddb24acac4bc2b57112 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 01:25:20 +0900 Subject: [PATCH 24/55] v2.3.0 alpha --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 10c3bf3..188a67f 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.2.6", + "version": "2.3.0-alpha.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.2.6", + "version": "2.3.0-alpha.0", "license": "ISC", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index ebce18c..c2fd18f 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.2.6", + "version": "2.3.0-alpha.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From b3ddf83c09f35d2e834a6e24f8e1370e669519f8 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 02:05:29 +0900 Subject: [PATCH 25/55] exports --- typescript/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/typescript/package.json b/typescript/package.json index c2fd18f..3d065f2 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -70,5 +70,8 @@ }, "dependencies": { "js-md5": "^0.7.3" + }, + "exports": { + "./utils/pict": "./dist/utils/pict.js" } } From 19a8856c8535fd602bec1f17d855b3aa97bc28e4 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 02:06:40 +0900 Subject: [PATCH 26/55] version --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 188a67f..616cf62 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.0-alpha.0", + "version": "2.3.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.0-alpha.0", + "version": "2.3.0-alpha.1", "license": "ISC", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 3d065f2..16bcd8c 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.0-alpha.0", + "version": "2.3.0-alpha.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From d7544771296a3b7f8c75ca399e6243f0208bee2b Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 03:14:18 +0900 Subject: [PATCH 27/55] export --- typescript/package.json | 3 --- typescript/src/index.ts | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/typescript/package.json b/typescript/package.json index 16bcd8c..1a9d7eb 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -70,8 +70,5 @@ }, "dependencies": { "js-md5": "^0.7.3" - }, - "exports": { - "./utils/pict": "./dist/utils/pict.js" } } diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 41234c5..460bdee 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -236,3 +236,5 @@ const make = (factors: T, options: OptionsType = {}) => { }; export { make as default, make, makeAsync, sorters, criteria }; + +export { PictConstraintsLexer } from "./utils/pict"; From 197e86bdf6dd005aebdedcf8fd2d35ec192aaac7 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 03:15:04 +0900 Subject: [PATCH 28/55] alpha2 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 616cf62..71d644d 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.0-alpha.1", + "version": "2.3.0-alpha.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.0-alpha.1", + "version": "2.3.0-alpha.2", "license": "ISC", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 1a9d7eb..84c9aee 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.0-alpha.1", + "version": "2.3.0-alpha.2", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From fde798d1f85422da419a869a7e7167cf9976fcc0 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 03:21:12 +0900 Subject: [PATCH 29/55] v2.3.0 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 71d644d..15c6bc7 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.0-alpha.2", + "version": "2.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.0-alpha.2", + "version": "2.3.0", "license": "ISC", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 84c9aee..09bd836 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.0-alpha.2", + "version": "2.3.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { @@ -69,6 +69,8 @@ "typescript": "^3.9.3" }, "dependencies": { - "js-md5": "^0.7.3" + "covertable": "^2.3.0-alpha.2", + "js-md5": "^0.7.3", + "ts-node": "^10.9.2" } } From 5f8434dbcb3865b635fc7955f919c1fea042cadc Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 19:22:33 +0900 Subject: [PATCH 30/55] fix: Remove covertable from dependencies --- typescript/package-lock.json | 272 +++++++++++++++++++++++++++++++++-- typescript/package.json | 1 - 2 files changed, 261 insertions(+), 12 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 15c6bc7..7281719 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -7,9 +7,10 @@ "": { "name": "covertable", "version": "2.3.0", - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "js-md5": "^0.7.3" + "js-md5": "^0.7.3", + "ts-node": "^10.9.2" }, "devDependencies": { "@types/jest": "^25.2.3", @@ -570,6 +571,17 @@ "node": ">=0.1.95" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1186,6 +1198,28 @@ "node": ">= 8.3" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -1216,6 +1250,26 @@ "node": ">= 6" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "node_modules/@types/babel__core": { "version": "7.1.12", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", @@ -1321,7 +1375,6 @@ "version": "14.14.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", - "dev": true, "license": "MIT" }, "node_modules/@types/normalize-package-data": { @@ -1518,6 +1571,11 @@ "dev": true, "license": "MIT" }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2217,6 +2275,11 @@ "node": ">=0.10.0" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -2433,6 +2496,14 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", @@ -6042,7 +6113,6 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, "license": "ISC" }, "node_modules/makeerror": { @@ -8069,6 +8139,70 @@ "node": ">=10" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -8115,7 +8249,6 @@ "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -8237,6 +8370,11 @@ "uuid": "bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/v8-to-istanbul": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz", @@ -8496,6 +8634,14 @@ "engines": { "node": ">=6" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } } }, "dependencies": { @@ -8932,6 +9078,14 @@ "minimist": "^1.2.0" } }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -9414,6 +9568,25 @@ "chalk": "^3.0.0" } }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -9438,6 +9611,26 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, + "@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "@types/babel__core": { "version": "7.1.12", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", @@ -9532,8 +9725,7 @@ "@types/node": { "version": "14.14.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", - "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", - "dev": true + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -9672,6 +9864,11 @@ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -10173,6 +10370,11 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -10329,6 +10531,11 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, "diff-sequences": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", @@ -12960,8 +13167,7 @@ "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "makeerror": { "version": "1.0.11", @@ -14457,6 +14663,41 @@ } } }, + "ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==" + }, + "acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "requires": { + "acorn": "^8.11.0" + } + } + } + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -14490,8 +14731,7 @@ "typescript": { "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "dev": true + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==" }, "union-value": { "version": "1.0.1", @@ -14575,6 +14815,11 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "v8-to-istanbul": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz", @@ -14772,6 +15017,11 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/typescript/package.json b/typescript/package.json index 09bd836..bff9cf7 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -69,7 +69,6 @@ "typescript": "^3.9.3" }, "dependencies": { - "covertable": "^2.3.0-alpha.2", "js-md5": "^0.7.3", "ts-node": "^10.9.2" } From 47c59da9c8253f297573e5f95723069cc920aebe Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 19:22:51 +0900 Subject: [PATCH 31/55] v2.3.1 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 7281719..fb82d22 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.0", + "version": "2.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.0", + "version": "2.3.1", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3", diff --git a/typescript/package.json b/typescript/package.json index bff9cf7..e80dde6 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.0", + "version": "2.3.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From b566e8d4932b14fe3bfaa383ede67e9c707e654b Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 22:39:37 +0900 Subject: [PATCH 32/55] 2.3.2-alpha.0 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- typescript/src/__tests__/index.test.ts | 2 +- typescript/src/criteria/greedy.ts | 2 +- typescript/src/criteria/index.ts | 2 -- typescript/src/criteria/simple.ts | 2 +- typescript/src/index.ts | 32 ++++++++++++++++++-------- typescript/src/{utils.ts => lib.ts} | 4 +++- typescript/src/sorters/hash.ts | 2 +- typescript/src/sorters/index.ts | 3 --- typescript/src/utils/pict.ts | 8 +++++-- 11 files changed, 39 insertions(+), 24 deletions(-) delete mode 100644 typescript/src/criteria/index.ts rename typescript/src/{utils.ts => lib.ts} (97%) delete mode 100644 typescript/src/sorters/index.ts diff --git a/typescript/package-lock.json b/typescript/package-lock.json index fb82d22..b5e8a9e 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.1", + "version": "2.3.2-alpha.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.1", + "version": "2.3.2-alpha.0", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3", diff --git a/typescript/package.json b/typescript/package.json index e80dde6..68a59d2 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.1", + "version": "2.3.2-alpha.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { diff --git a/typescript/src/__tests__/index.test.ts b/typescript/src/__tests__/index.test.ts index 6de8151..70e439a 100644 --- a/typescript/src/__tests__/index.test.ts +++ b/typescript/src/__tests__/index.test.ts @@ -1,5 +1,5 @@ import { default as make, sorters, criteria } from '../index'; -import { product, combinations, range, len, all, getItems } from '../utils'; +import { product, combinations, range, len, all, getItems } from '../lib'; import { FactorsType, Scalar, Dict, PairType } from '../types'; const getPairs = function* (factors: FactorsType, length = 2) { diff --git a/typescript/src/criteria/greedy.ts b/typescript/src/criteria/greedy.ts index 688d2cf..36cde63 100644 --- a/typescript/src/criteria/greedy.ts +++ b/typescript/src/criteria/greedy.ts @@ -1,5 +1,5 @@ import {CriterionArgsType, IncompleteType, PairType} from '../types'; -import {getCandidate, combinations, ascOrder, unique} from '../utils'; +import {getCandidate, combinations, ascOrder, unique} from '../lib'; const getNumRemovablePairs = (indexes: Set, incomplete: IncompleteType, length: number) => { let num = 0; diff --git a/typescript/src/criteria/index.ts b/typescript/src/criteria/index.ts deleted file mode 100644 index 76a88d0..0000000 --- a/typescript/src/criteria/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {default as simple} from './simple'; -export {default as greedy} from './greedy'; diff --git a/typescript/src/criteria/simple.ts b/typescript/src/criteria/simple.ts index f42cee6..c9a4b83 100644 --- a/typescript/src/criteria/simple.ts +++ b/typescript/src/criteria/simple.ts @@ -1,5 +1,5 @@ import {CriterionArgsType, IncompleteType, PairType} from '../types'; -import {getCandidate} from '../utils'; +import {getCandidate} from '../lib'; export default function* ( incomplete: IncompleteType, diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 460bdee..be96db5 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -1,6 +1,11 @@ -import * as sorters from "./sorters/index"; -import * as criteria from "./criteria/index"; -import * as exceptions from "./exceptions"; + +import hash from "./sorters/hash"; +import random from "./sorters/random"; + +import greedy from "./criteria/greedy"; +import simple from "./criteria/simple"; + +import {InvalidCondition} from "./exceptions"; import { range, product, @@ -11,7 +16,8 @@ import { ascOrder, primeGenerator, unique, -} from "./utils"; +} from "./lib"; + import { IndicesType, FactorsType, @@ -162,7 +168,7 @@ class Row extends Map implements RowType { } }); if (!this.filled()) { - throw new exceptions.InvalidCondition(); + throw new InvalidCondition(); } return this; } @@ -174,8 +180,8 @@ const makeAsync = function* ( ) { let { length = 2, - sorter = sorters.hash, - criterion = criteria.greedy, + sorter = hash, + criterion = greedy, seed = "", tolerance = 0, } = options; @@ -235,6 +241,14 @@ const make = (factors: T, options: OptionsType = {}) => { return [...makeAsync(factors, options)]; }; -export { make as default, make, makeAsync, sorters, criteria }; +const sorters = { hash, random }; +const criteria = { greedy, simple }; + +export { + make as default, + make, + makeAsync, + sorters, + criteria, +}; -export { PictConstraintsLexer } from "./utils/pict"; diff --git a/typescript/src/utils.ts b/typescript/src/lib.ts similarity index 97% rename from typescript/src/utils.ts rename to typescript/src/lib.ts index 24a904b..aeb5c6c 100644 --- a/typescript/src/utils.ts +++ b/typescript/src/lib.ts @@ -1,6 +1,8 @@ // @ts-ignore 2307 export { hex as md5 } from 'js-md5'; -import { FactorsType, Scalar, ParentsType, CandidateType, PairType } from './types'; +import { + FactorsType, Scalar, ParentsType, CandidateType, PairType, +} from './types'; // https://gist.github.com/righ/71e32be8e33f74bde516c06f80c941e8 diff --git a/typescript/src/sorters/hash.ts b/typescript/src/sorters/hash.ts index 39228e1..dda0b2e 100644 --- a/typescript/src/sorters/hash.ts +++ b/typescript/src/sorters/hash.ts @@ -1,4 +1,4 @@ -import {md5} from '../utils'; +import {md5} from '../lib'; import { PairType, SortArgsType, diff --git a/typescript/src/sorters/index.ts b/typescript/src/sorters/index.ts deleted file mode 100644 index 31e8ed9..0000000 --- a/typescript/src/sorters/index.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export {default as random} from './random'; -export {default as hash} from './hash'; diff --git a/typescript/src/utils/pict.ts b/typescript/src/utils/pict.ts index c9a38f3..603e31a 100644 --- a/typescript/src/utils/pict.ts +++ b/typescript/src/utils/pict.ts @@ -1,5 +1,9 @@ -import { FilterType, FilterRowType } from "../types"; +type FilterRowType = { + [key: string]: any; + [index: number]: any; +} +type FilterType = (row: FilterRowType) => boolean; type Token = { type: string; value: string; @@ -317,7 +321,7 @@ export class PictConstraintsLexer { return new Function('row', code).bind(this) as FilterType; } - filter(row: FilterRowType, ...additionalFilters: FilterType[]): boolean { + filter = (row: FilterRowType, ...additionalFilters: FilterType[]) => { for (const f of this.filters) { if (f == null) { continue; From 9da9250fd7818846bf90cd7bf37a0389694d8d6c Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 7 Aug 2024 22:59:10 +0900 Subject: [PATCH 33/55] 2.3.2-alpha.1 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 8 +++++++- typescript/src/criteria/greedy.ts | 2 +- typescript/src/criteria/simple.ts | 2 +- typescript/src/lib.ts | 2 +- typescript/src/sorters/hash.ts | 2 +- typescript/src/sorters/random.ts | 2 +- typescript/src/utils/pict.ts | 6 +----- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index b5e8a9e..afb65a2 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.2-alpha.0", + "version": "2.3.2-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.2-alpha.0", + "version": "2.3.2-alpha.1", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3", diff --git a/typescript/package.json b/typescript/package.json index 68a59d2..1ae8670 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.2-alpha.0", + "version": "2.3.2-alpha.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { @@ -71,5 +71,11 @@ "dependencies": { "js-md5": "^0.7.3", "ts-node": "^10.9.2" + }, + "exports": { + "./utils/pict": { + "import": "./dist/utils/pict.js", + "types": "./dist/utils/pict.d.ts" + } } } diff --git a/typescript/src/criteria/greedy.ts b/typescript/src/criteria/greedy.ts index 36cde63..5dddc4d 100644 --- a/typescript/src/criteria/greedy.ts +++ b/typescript/src/criteria/greedy.ts @@ -1,4 +1,4 @@ -import {CriterionArgsType, IncompleteType, PairType} from '../types'; +import type {CriterionArgsType, IncompleteType, PairType} from '../types'; import {getCandidate, combinations, ascOrder, unique} from '../lib'; const getNumRemovablePairs = (indexes: Set, incomplete: IncompleteType, length: number) => { diff --git a/typescript/src/criteria/simple.ts b/typescript/src/criteria/simple.ts index c9a4b83..5f187fc 100644 --- a/typescript/src/criteria/simple.ts +++ b/typescript/src/criteria/simple.ts @@ -1,4 +1,4 @@ -import {CriterionArgsType, IncompleteType, PairType} from '../types'; +import type {CriterionArgsType, IncompleteType, PairType} from '../types'; import {getCandidate} from '../lib'; export default function* ( diff --git a/typescript/src/lib.ts b/typescript/src/lib.ts index aeb5c6c..2f083c0 100644 --- a/typescript/src/lib.ts +++ b/typescript/src/lib.ts @@ -1,6 +1,6 @@ // @ts-ignore 2307 export { hex as md5 } from 'js-md5'; -import { +import type { FactorsType, Scalar, ParentsType, CandidateType, PairType, } from './types'; diff --git a/typescript/src/sorters/hash.ts b/typescript/src/sorters/hash.ts index dda0b2e..be75f52 100644 --- a/typescript/src/sorters/hash.ts +++ b/typescript/src/sorters/hash.ts @@ -1,5 +1,5 @@ import {md5} from '../lib'; -import { +import type { PairType, SortArgsType, } from '../types'; diff --git a/typescript/src/sorters/random.ts b/typescript/src/sorters/random.ts index 82c17e6..b43c453 100644 --- a/typescript/src/sorters/random.ts +++ b/typescript/src/sorters/random.ts @@ -1,4 +1,4 @@ -import {PairType, SortArgsType} from '../types'; +import type {PairType, SortArgsType} from '../types'; const comparer = (a: any, b: any) => { return Math.random() > 0.5 ? 1 : -1; diff --git a/typescript/src/utils/pict.ts b/typescript/src/utils/pict.ts index 603e31a..661806d 100644 --- a/typescript/src/utils/pict.ts +++ b/typescript/src/utils/pict.ts @@ -1,9 +1,5 @@ -type FilterRowType = { - [key: string]: any; - [index: number]: any; -} +import type { FilterRowType, FilterType } from '../types'; -type FilterType = (row: FilterRowType) => boolean; type Token = { type: string; value: string; From f60e1e894f3be17953cd8b4942919ebb61b157fb Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 8 Aug 2024 01:15:02 +0900 Subject: [PATCH 34/55] webpack --- typescript/package-lock.json | 1973 ++++++++++++++++++++++++++++++++-- typescript/package.json | 21 +- typescript/src/index.ts | 5 +- typescript/tsconfig.json | 6 +- typescript/webpack.config.js | 23 + 5 files changed, 1911 insertions(+), 117 deletions(-) create mode 100644 typescript/webpack.config.js diff --git a/typescript/package-lock.json b/typescript/package-lock.json index afb65a2..d394bb6 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,16 +1,15 @@ { "name": "covertable", - "version": "2.3.2-alpha.1", + "version": "2.3.2-alpha.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.2-alpha.1", + "version": "2.3.2-alpha.3", "license": "Apache-2.0", "dependencies": { - "js-md5": "^0.7.3", - "ts-node": "^10.9.2" + "js-md5": "^0.7.3" }, "devDependencies": { "@types/jest": "^25.2.3", @@ -20,7 +19,11 @@ "jest": "^26.0.1", "nyc": "^15.1.0", "ts-jest": "^26.1.0", - "typescript": "^3.9.3" + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^4.9.3", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4" } }, "node_modules/@babel/code-frame": { @@ -575,6 +578,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -582,6 +586,15 @@ "node": ">=12" } }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1198,23 +1211,79 @@ "node": ">= 8.3" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -1253,22 +1322,26 @@ "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.1.12", @@ -1315,6 +1388,32 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -1371,10 +1470,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/node": { "version": "14.14.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", + "dev": true, "license": "MIT" }, "node_modules/@types/normalize-package-data": { @@ -1415,6 +1521,208 @@ "dev": true, "license": "MIT" }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "node_modules/abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -1483,6 +1791,31 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/ansi-escapes": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", @@ -1574,7 +1907,8 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "node_modules/argparse": { "version": "1.0.10", @@ -1917,9 +2251,9 @@ "license": "BSD-2-Clause" }, "node_modules/browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -1929,14 +2263,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -2033,9 +2370,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001331", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001331.tgz", - "integrity": "sha512-Y1xk6paHpUXKP/P6YjQv1xqyTbgAP05ycHBcRdQjTcyXlWol868sJJPlmk5ylOekw2BrucWes5jk+LvVd7WZ5Q==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "dev": true, "funding": [ { @@ -2045,6 +2382,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -2085,6 +2426,15 @@ "node": ">=10" } }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -2150,6 +2500,20 @@ "wrap-ansi": "^6.2.0" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -2222,6 +2586,12 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2234,6 +2604,12 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2278,7 +2654,8 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "node_modules/cross-spawn": { "version": "6.0.5", @@ -2500,6 +2877,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -2538,9 +2916,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.107", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.107.tgz", - "integrity": "sha512-Huen6taaVrUrSy8o7mGStByba8PfOWWluHNxSHGBrCgEdFVLtvdQDBr9LBCF9Uci8SYxh28QNNMO0oC17wbGAg==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz", + "integrity": "sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==", "dev": true }, "node_modules/emittery": { @@ -2573,6 +2951,31 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2583,6 +2986,12 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2591,11 +3000,10 @@ "license": "MIT" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -2632,6 +3040,28 @@ "source-map": "~0.6.1" } }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -2646,6 +3076,18 @@ "node": ">=4" } }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -2664,6 +3106,15 @@ "node": ">=0.10.0" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/exec-sh": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", @@ -2947,6 +3398,12 @@ "node": ">=0.10.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2960,6 +3417,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -3015,6 +3481,15 @@ "node": ">=8" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3253,6 +3728,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -3264,11 +3745,10 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true, - "license": "ISC" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/growly": { "version": "1.3.0", @@ -3549,6 +4029,15 @@ "dev": true, "license": "ISC" }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -5987,6 +6476,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -6053,6 +6548,15 @@ "dev": true, "license": "MIT" }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -6113,6 +6617,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, "license": "ISC" }, "node_modules/makeerror": { @@ -6296,6 +6801,12 @@ "dev": true, "license": "MIT" }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -6437,9 +6948,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/normalize-package-data": { @@ -6810,9 +7321,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -6943,9 +7454,18 @@ "node": ">=6" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, "license": "MIT" @@ -6994,6 +7514,18 @@ "node": ">=8" } }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -7360,6 +7892,24 @@ "node": ">=10" } }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -7370,6 +7920,15 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -7406,6 +7965,18 @@ "node": ">=0.10.0" } }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -7654,11 +8225,10 @@ } }, "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7934,6 +8504,15 @@ "dev": true, "license": "MIT" }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/teeny-request": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", @@ -7965,6 +8544,109 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/terser": { + "version": "5.31.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.5.tgz", + "integrity": "sha512-YPmas0L0rE1UyLL/llTWA0SiDOqIcAQYLeUj7cJYzXHlRTAnMSg9pPe4VJ5PlKvTrPQsdVFuiRiwyeNlYgwh2Q==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -8139,10 +8821,68 @@ "node": ">=10" } }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -8185,6 +8925,7 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -8196,6 +8937,7 @@ "version": "8.3.3", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, "dependencies": { "acorn": "^8.11.0" }, @@ -8246,10 +8988,10 @@ } }, "node_modules/typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "license": "Apache-2.0", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8335,6 +9077,45 @@ "node": ">=0.10.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -8373,7 +9154,8 @@ "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/v8-to-istanbul": { "version": "7.1.0", @@ -8444,6 +9226,19 @@ "makeerror": "1.0.x" } }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -8454,6 +9249,210 @@ "node": ">=10.4" } }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-cli/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webpack-cli/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-cli/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-cli/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-cli/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -8505,6 +9504,12 @@ "dev": true, "license": "ISC" }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -8639,6 +9644,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, "engines": { "node": ">=6" } @@ -9082,10 +10088,17 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "requires": { "@jridgewell/trace-mapping": "0.3.9" } }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -9568,20 +10581,74 @@ "chalk": "^3.0.0" } }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, "@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } }, "@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -9614,22 +10681,26 @@ "@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==" + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true }, "@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true }, "@types/babel__core": { "version": "7.1.12", @@ -9672,6 +10743,32 @@ "@babel/types": "^7.3.0" } }, + "@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -9722,10 +10819,17 @@ "integrity": "sha512-FUPoQkpQTzA5wz9ebrdVRjsjQsFehr+cW1CVhLcI2UwD/SO/4NHPO1esrXPPbx7ux762U0POmWFSrUjQq2ophw==", "dev": true }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "@types/node": { "version": "14.14.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", - "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==" + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", + "dev": true }, "@types/normalize-package-data": { "version": "2.4.0", @@ -9754,10 +10858,189 @@ "@types/yargs-parser": "*" } }, - "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "@types/yargs-parser": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", + "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "requires": {} + }, + "@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, "abab": { @@ -9807,6 +11090,25 @@ "indent-string": "^4.0.0" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, "ansi-escapes": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", @@ -9867,7 +11169,8 @@ "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "argparse": { "version": "1.0.10", @@ -10118,16 +11421,15 @@ "dev": true }, "browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" } }, "bs-logger": { @@ -10196,9 +11498,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001331", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001331.tgz", - "integrity": "sha512-Y1xk6paHpUXKP/P6YjQv1xqyTbgAP05ycHBcRdQjTcyXlWol868sJJPlmk5ylOekw2BrucWes5jk+LvVd7WZ5Q==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "dev": true }, "capture-exit": { @@ -10226,6 +11528,12 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true }, + "chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -10278,6 +11586,17 @@ "wrap-ansi": "^6.2.0" } }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -10328,6 +11647,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -10337,6 +11662,12 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -10373,7 +11704,8 @@ "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "cross-spawn": { "version": "6.0.5", @@ -10534,7 +11866,8 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "diff-sequences": { "version": "25.2.6", @@ -10560,9 +11893,9 @@ } }, "electron-to-chromium": { - "version": "1.4.107", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.107.tgz", - "integrity": "sha512-Huen6taaVrUrSy8o7mGStByba8PfOWWluHNxSHGBrCgEdFVLtvdQDBr9LBCF9Uci8SYxh28QNNMO0oC17wbGAg==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz", + "integrity": "sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==", "dev": true }, "emittery": { @@ -10586,6 +11919,22 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -10595,6 +11944,12 @@ "is-arrayish": "^0.2.1" } }, + "es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -10602,9 +11957,9 @@ "dev": true }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true }, "escape-string-regexp": { @@ -10626,12 +11981,39 @@ "source-map": "~0.6.1" } }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -10644,6 +12026,12 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, "exec-sh": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", @@ -10861,6 +12249,12 @@ } } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -10873,6 +12267,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, "fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -10912,6 +12312,12 @@ "path-exists": "^4.0.0" } }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -11063,6 +12469,12 @@ "path-is-absolute": "^1.0.0" } }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -11070,9 +12482,9 @@ "dev": true }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "growly": { @@ -11279,6 +12691,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -13082,6 +14500,12 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -13125,6 +14549,12 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -13167,7 +14597,8 @@ "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "makeerror": { "version": "1.0.11", @@ -13303,6 +14734,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -13408,9 +14845,9 @@ } }, "node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "normalize-package-data": { @@ -13676,9 +15113,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "picomatch": { @@ -13770,6 +15207,15 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -13807,6 +15253,15 @@ "type-fest": "^0.8.1" } }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "requires": { + "resolve": "^1.20.0" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -14079,12 +15534,32 @@ "xmlchars": "^2.2.0" } }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -14114,6 +15589,15 @@ } } }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -14302,9 +15786,9 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -14515,6 +15999,12 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, "teeny-request": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", @@ -14538,6 +16028,71 @@ "supports-hyperlinks": "^2.0.0" } }, + "terser": { + "version": "5.31.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.5.tgz", + "integrity": "sha512-YPmas0L0rE1UyLL/llTWA0SiDOqIcAQYLeUj7cJYzXHlRTAnMSg9pPe4VJ5PlKvTrPQsdVFuiRiwyeNlYgwh2Q==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -14663,10 +16218,48 @@ } } }, + "ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, "ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -14686,12 +16279,14 @@ "acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==" + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true }, "acorn-walk": { "version": "8.3.3", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, "requires": { "acorn": "^8.11.0" } @@ -14729,9 +16324,10 @@ } }, "typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==" + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true }, "union-value": { "version": "1.0.1", @@ -14791,6 +16387,25 @@ } } }, + "update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "requires": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -14818,7 +16433,8 @@ "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "v8-to-istanbul": { "version": "7.1.0", @@ -14876,12 +16492,156 @@ "makeerror": "1.0.x" } }, + "watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true }, + "webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true + }, + "acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "requires": {} + } + } + }, + "webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -14923,6 +16683,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -15021,7 +16787,8 @@ "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/typescript/package.json b/typescript/package.json index 1ae8670..b1bbddd 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.2-alpha.1", + "version": "2.3.2-alpha.3", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { @@ -36,8 +36,8 @@ "main": "dist/index.js", "scripts": { "test": "jest", - "build": "$(npm bin)/tsc", - "watch": "$(npm bin)/tsc -w", + "build": "rm -rf dist/ && $(npm bin)/webpack", + "watch": "$(npm bin)/webpack --watch", "codecov": "$(npm bin)/codecov" }, "jest": { @@ -66,16 +66,13 @@ "jest": "^26.0.1", "nyc": "^15.1.0", "ts-jest": "^26.1.0", - "typescript": "^3.9.3" + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^4.9.3", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4" }, "dependencies": { - "js-md5": "^0.7.3", - "ts-node": "^10.9.2" - }, - "exports": { - "./utils/pict": { - "import": "./dist/utils/pict.js", - "types": "./dist/utils/pict.d.ts" - } + "js-md5": "^0.7.3" } } diff --git a/typescript/src/index.ts b/typescript/src/index.ts index be96db5..68862a0 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -5,6 +5,8 @@ import random from "./sorters/random"; import greedy from "./criteria/greedy"; import simple from "./criteria/simple"; +import {PictConstraintsLexer} from "./utils/pict"; + import {InvalidCondition} from "./exceptions"; import { range, @@ -245,10 +247,11 @@ const sorters = { hash, random }; const criteria = { greedy, simple }; export { - make as default, make, makeAsync, sorters, criteria, + PictConstraintsLexer, }; +export default make; diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 8bf419f..0707532 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -46,7 +46,7 @@ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ @@ -59,5 +59,9 @@ /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + "baseUrl": ".", + "paths": { + "covertable/utils/pict": ["./dist/utils/pict"] + } } } diff --git a/typescript/webpack.config.js b/typescript/webpack.config.js new file mode 100644 index 0000000..2d4cf5f --- /dev/null +++ b/typescript/webpack.config.js @@ -0,0 +1,23 @@ +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + resolve: { + extensions: ['.ts', '.js'], + }, + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: 'umd', + }, + target: 'node', +}; From 2bdab409820117620443a2e04f97da8c4e3b6f55 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 21 Aug 2024 22:07:23 +0900 Subject: [PATCH 35/55] 2.3.2-alpha.4 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index d394bb6..01e3b63 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.2-alpha.3", + "version": "2.3.2-alpha.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.2-alpha.3", + "version": "2.3.2-alpha.4", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index b1bbddd..0d24d3a 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.2-alpha.3", + "version": "2.3.2-alpha.4", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From 7cf71ac0cbd497a5a14caab2df3d695de458227e Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 22 Aug 2024 00:51:43 +0900 Subject: [PATCH 36/55] fix: set default true --- typescript/src/utils/pict.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/typescript/src/utils/pict.ts b/typescript/src/utils/pict.ts index 661806d..ca1cf50 100644 --- a/typescript/src/utils/pict.ts +++ b/typescript/src/utils/pict.ts @@ -174,6 +174,8 @@ export class PictConstraintsLexer { return 'false'; } return `(${expr})`; + } else if (token && token.type === 'BOOLEAN') { + return token.value.toUpperCase() === 'TRUE' ? 'true' : 'false'; } else { tokenIndex--; // Go back one token return parseCondition(); @@ -278,19 +280,19 @@ export class PictConstraintsLexer { errorMessages.push('Expected THEN'); break; } - const action = parseExpression(); - let elseAction = 'false'; + const thenAction = parseExpression(); + const elseToken = nextToken(); + let elseAction = 'true'; if (elseToken && elseToken.type === 'ELSE') { elseAction = parseExpression(); } else { tokenIndex--; // Go back one token if ELSE is not found } - - const filterCode = `return (${condition} ? (${action}) : (${elseAction}));`; + const filterCode = `return (${condition} ? (${thenAction}) : (${elseAction}));`; try { if (this.debug) { - console.log(`code[${filters.length}]:`, filterCode); + console.debug(`code[${filters.length}]:`, filterCode); } const f = this.makeClosure(filterCode); filters.push(f as FilterType); From 84f670da8229d4201271622e6bc2ffc9718207ff Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 22 Aug 2024 00:52:16 +0900 Subject: [PATCH 37/55] 2.3.2-alpha.5 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 01e3b63..a20f25e 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.2-alpha.4", + "version": "2.3.2-alpha.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.2-alpha.4", + "version": "2.3.2-alpha.5", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 0d24d3a..c08a825 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.2-alpha.4", + "version": "2.3.2-alpha.5", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From 014aa00f6588cb2f837226bea75f20ed8b4c3339 Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 25 Aug 2024 01:24:05 +0900 Subject: [PATCH 38/55] fix: conditions for application of prefilter --- typescript/src/__tests__/filter.test.ts | 62 ++++++ typescript/src/__tests__/index.test.ts | 17 -- typescript/src/controller.ts | 277 ++++++++++++++++++++++++ typescript/src/criteria/greedy.ts | 32 +-- typescript/src/criteria/simple.ts | 14 +- typescript/src/exceptions.ts | 11 +- typescript/src/index.ts | 246 +++------------------ typescript/src/lib.ts | 14 ++ typescript/src/types.ts | 44 ++-- 9 files changed, 427 insertions(+), 290 deletions(-) create mode 100644 typescript/src/__tests__/filter.test.ts create mode 100644 typescript/src/controller.ts diff --git a/typescript/src/__tests__/filter.test.ts b/typescript/src/__tests__/filter.test.ts new file mode 100644 index 0000000..7354042 --- /dev/null +++ b/typescript/src/__tests__/filter.test.ts @@ -0,0 +1,62 @@ +import { Dict, SuggestRowType } from "../types"; +import { make, makeAsync, sorters, criteria } from "../index"; + +const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; +const os = ["iOS", "Android"]; +const browser = ["FireFox", "Chrome", "Safari"]; + +test('exclude impossible combinations', () => { + const factors = {machine, os, browser}; + const preFilter = (row: Dict) => { + return !( + (row.machine === 'iPhone' && row.os !== 'iOS') || + (row.machine !== 'iPhone' && row.os === 'iOS') + ); + }; + const rows = make(factors, { preFilter }); + expect(rows.filter(row => row.machine === 'iPhone' && row.os === 'iOS').length).toBe(browser.length); + expect(rows.filter(row => row.machine === 'iPhone' && row.os !== 'iOS').length).toBe(0); + expect(rows.filter(row => row.machine !== 'iPhone' && row.os === 'iOS').length).toBe(0); + + expect(rows.filter(row => row.machine === 'Pixel' && row.os === 'Android').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'XPERIA' && row.os === 'Android').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'ZenFone' && row.os === 'Android').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'Galaxy' && row.os === 'Android').length).toBeGreaterThanOrEqual(1); + + expect(rows.filter(row => row.machine === 'iPhone' && row.browser === 'FireFox').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'iPhone' && row.browser === 'Chrome').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'iPhone' && row.browser === 'Safari').length).toBeGreaterThanOrEqual(1); + + expect(rows.filter(row => row.machine === 'Pixel' && row.browser === 'FireFox').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'Pixel' && row.browser === 'Chrome').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.machine === 'Pixel' && row.browser === 'Safari').length).toBeGreaterThanOrEqual(1); + + expect(rows.filter(row => row.os === 'iOS' && row.browser === 'FireFox').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.os === 'iOS' && row.browser === 'Chrome').length).toBeGreaterThanOrEqual(1); + expect(rows.filter(row => row.os === 'iOS' && row.browser === 'Safari').length).toBeGreaterThanOrEqual(1); +}); + +test('Limited to iphone and iOS combinations only.', () => { + const factors = {machine, os, browser}; + const preFilter = (row: SuggestRowType) => row.machine === 'iPhone' && row.os === 'iOS'; + const rows = make(factors, { preFilter }); + expect(rows.length).toBe(browser.length); + expect(rows.filter(row => row.machine === 'iPhone' && row.os === 'iOS').length).toBe(browser.length); + expect(rows.filter(row => row.machine === 'Pixel').length).toBe(0); + expect(rows.filter(row => row.os == 'Android').length).toBe(0); +}); + + +test('Use a constant-false function for preFilter', () => { + const factors = {machine, os, browser}; + const preFilter = (row: Dict) => false; + const rows = make(factors, { preFilter }); + expect(rows).toEqual([]); +}); + +test('Use the wrong conditional function for preFilter', () => { + const factors = {machine, os, browser}; + const preFilter = (row: Dict) => row.machine === 'WindowsPhone'; + const rows = make(factors, { preFilter }); + expect(rows).toEqual([]); +}); diff --git a/typescript/src/__tests__/index.test.ts b/typescript/src/__tests__/index.test.ts index 70e439a..904ab6f 100644 --- a/typescript/src/__tests__/index.test.ts +++ b/typescript/src/__tests__/index.test.ts @@ -89,23 +89,6 @@ test('prefilter excludes specified pairs before', () => { } }); -test('never matching prefilter throws an exception', () => { - const factors = [ - ["a", "b", "c"], - ["d", "e"], - ["f"], - ]; - const preFilter = (row: Dict) => { - if (row[2] === "f") { - return false; - } - return true; - } - expect(() => { - make(factors, { preFilter }) - }).toThrow(); -}); - test("greedy sorter should make rows less than seed's one with 2", () => { const factors = [ ["a", "b", "c"], diff --git a/typescript/src/controller.ts b/typescript/src/controller.ts new file mode 100644 index 0000000..dc7c071 --- /dev/null +++ b/typescript/src/controller.ts @@ -0,0 +1,277 @@ + +import hash from "./sorters/hash"; +import { + range, + product, + combinations, + len, + getItems, + getCandidate, + ascOrder, + primeGenerator, + unique, + proxyHandler, +} from "./lib"; + +import { + IndicesType, + FactorsType, + SerialsType, + Scalar, + Dict, + PairByKey, + ParentsType, + CandidateType, + RowType, + OptionsType, + PairType, + SuggestRowType, +} from "./types"; +import { NeverMatch, NotReady } from "./exceptions"; + +export class Row extends Map implements RowType { + // index: number + public consumed: PairByKey = new Map(); + + constructor(row: CandidateType) { + super(); + for (const [k, v] of row) { + this.set(k, v); + } + } + getPairKey(...newPair: number[]) { + const pair = [...this.values(), ...newPair]; + return unique(pair); + } + copy(row: Row) { + for (let [k, v] of row.entries()) { + this.set(k, v); + } + } +} + +export class Controller { + public factorLength: number; + public factorIsArray: Boolean; + + private serials: SerialsType = new Map(); + private parents: ParentsType = new Map(); + private indices: IndicesType = new Map(); + public incomplete: PairByKey = new Map(); + + private rejected: Set = new Set(); + public row: Row; + + constructor(public factors: FactorsType, public options: OptionsType) { + this.serialize(factors); + this.setIncomplete(); + this.row = new Row([]); + this.factorLength = len(factors); + this.factorIsArray = factors instanceof Array; + + // Delete initial pairs that do not satisfy preFilter + for (const [pairKey, pair] of this.incomplete.entries()) { + const cand = this.getCandidate(pair); + const storable = this.storable(cand); + if (storable == null) { + this.incomplete.delete(pairKey); + } + } + } + + private serialize(factors: FactorsType) { + let origin = 0; + const primer = primeGenerator(); + getItems(factors).map(([subscript, elements]) => { + const lenElements = len(elements); + const serialList: number[] = []; + range(origin, origin + lenElements).map((index) => { + const serial = primer.next().value; + serialList.push(serial); + this.parents.set(serial, subscript); + this.indices.set(serial, index); + }); + this.serials.set(subscript, serialList); + origin += lenElements; + }); + }; + + private setIncomplete() { + const { sorter = hash, seed = "" } = this.options; + const pairs: PairType[] = []; + const allKeys = getItems(this.serials).map(([k, _]) => k); + for (const keys of combinations(allKeys, this.pairwiseCount)) { + const comb = range(0, this.pairwiseCount).map((i) => this.serials.get(keys[i]) as PairType); + for (let pair of product(...comb)) { + pair = pair.sort(ascOrder); + pairs.push(pair); + } + } + for (let pair of sorter(pairs, { seed, indices: this.indices })) { + this.incomplete.set(unique(pair), pair); + } + } + + setPair(pair: PairType) { + for (let [key, value] of this.getCandidate(pair)) { + this.row.set(key, value); + } + //this.consume(pair); + for (let p of combinations([...this.row.values()], this.pairwiseCount)) { + this.consume(p); + } + } + + consume(pair: PairType) { + const pairKey = unique(pair); + const deleted = this.incomplete.delete(pairKey); + if (deleted) { + this.row.consumed.set(pairKey, pair); + } + } + + getCandidate(pair: PairType) { + return getCandidate(pair, this.parents); + } + + // Returns a negative value if it is unknown if it can be stored. + storable(candidate: CandidateType) { + let num = 0; + for (let [key, el] of candidate) { + let existing: number | undefined = this.row.get(key); + if (typeof existing === "undefined") { + num++; + } else if (existing != el) { + return null; + } + } + if (!this.options.preFilter) { + return num; + } + const candidates: CandidateType = [...this.row.entries()].concat(candidate); + const nxt = new Row(candidates); + const proxy = this.toProxy(nxt); + try { + const ok = this.options.preFilter(proxy); + if (!ok) { + return null; + } + } catch (e) { + if (e instanceof NotReady) { + return -num; + } + throw e + } + return num; + } + + isFilled(row: Row): boolean { + return row.size === this.factorLength; + } + + toMap(row: Row): Map { + const result: Map = new Map(); + for (let [key, serial] of row.entries()) { + const index = this.indices.get(serial) as number; + const first = this.indices.get((this.serials.get(key) as PairType)[0]); + // @ts-ignore TS7015 + result.set(key, this.factors[key][index - first]); + } + return result; + } + + toProxy(row: Row) { + const obj: Dict = {}; + for (let [key, value] of this.toMap(row).entries()) { + obj[key] = value; + } + return new Proxy(obj, proxyHandler) as SuggestRowType; + } + + toObject(row: Row) { + const obj: Dict = {}; + for (let [key, value] of this.toMap(row).entries()) { + obj[key] = value; + } + return obj as SuggestRowType; + } + + reset() { + this.row.consumed.forEach((pair, pairKey) => { + this.incomplete.set(pairKey, pair); + }); + this.row = new Row([]); + } + + discard() { + this.rejected.add(this.row.getPairKey()); + this.row = new Row([]); + } + + restore() { + const row = this.row; + this.row = new Row([]); + if (this.factorIsArray) { + const map = this.toMap(row); + return getItems(map) + .sort((a, b) => (a[0] > b[0] ? 1 : -1)) + .map(([_, v]) => v); + } + return this.toObject(row); + } + + close() { + const trier = new Row([...this.row.entries()]); + const kvs = getItems(this.serials); + for (let [k, vs] of kvs) { + for (let v of vs) { + const pairKey = trier.getPairKey(v); + if (this.rejected.has(pairKey)) { + continue; + } + const cand: CandidateType = [[k, v]]; + const storable = this.storable(cand); + if (storable == null) { + this.rejected.add(pairKey); + continue; + } + trier.set(k, v); + break; + } + } + this.row.copy(trier); + if (this.isComplete) { + return true; + } + if (trier.size === 0) { + return false; + } + const pairKey = trier.getPairKey(); + if (this.rejected.has(pairKey)) { + throw new NeverMatch(); + } + this.rejected.add(pairKey); + this.reset(); + return false; + } + + get pairwiseCount() { + return this.options.length || 2; + } + + get isComplete() { + const filled = this.isFilled(this.row); + if (!filled) { + return false; + } + const proxy = this.toProxy(this.row); + try { + return this.options.preFilter ? this.options.preFilter(proxy) : true; + } catch (e) { + if (e instanceof NotReady) { + return false; + } + throw e; + } + } +} diff --git a/typescript/src/criteria/greedy.ts b/typescript/src/criteria/greedy.ts index 5dddc4d..b5529c0 100644 --- a/typescript/src/criteria/greedy.ts +++ b/typescript/src/criteria/greedy.ts @@ -1,7 +1,8 @@ -import type {CriterionArgsType, IncompleteType, PairType} from '../types'; -import {getCandidate, combinations, ascOrder, unique} from '../lib'; +import type {FactorsType, PairByKey, PairType} from '../types'; +import { combinations, unique } from '../lib'; +import { Controller } from '../controller'; -const getNumRemovablePairs = (indexes: Set, incomplete: IncompleteType, length: number) => { +const getNumRemovablePairs = (indexes: Set, incomplete: PairByKey, length: number) => { let num = 0; const removingKeys = combinations([... indexes], length); for (let pair of removingKeys) { @@ -13,41 +14,40 @@ const getNumRemovablePairs = (indexes: Set, incomplete: IncompleteType, return num; }; -export default function* ( - incomplete: IncompleteType, - criterionArgs: CriterionArgsType, -): Generator { - let {row, parents, length, tolerance} = criterionArgs; - +export default function* (ctrl: Controller): Generator { while (true) { let maxNumPairs: number | null = null; let efficientPair: PairType | null = null; - for (let [pairKey, pair] of incomplete.entries()) { - const rowSize = row.size; + for (const [pairKey, pair] of ctrl.incomplete.entries()) { + const rowSize = ctrl.row.size; if (rowSize === 0) { yield pair; continue; } - if (row.filled()) { + if (ctrl.isFilled(ctrl.row)) { break; } - const storable = row.storable(getCandidate(pair, parents)); + const storable = ctrl.storable(ctrl.getCandidate(pair)); if (storable === null) { continue; } if (storable === 0) { - incomplete.delete(pairKey); + ctrl.consume(pair); continue; } + const storableAbs = Math.abs(storable); + const { tolerance = 0 } = ctrl.options!; const numPairs = getNumRemovablePairs( - new Set([... row.values(), ...pair]), incomplete, length + new Set([...ctrl.row.values(), ...pair]), + ctrl.incomplete, + ctrl.pairwiseCount, ); - if (numPairs + tolerance > rowSize * storable) { + if (numPairs + tolerance > rowSize * storableAbs) { efficientPair = pair; break; } diff --git a/typescript/src/criteria/simple.ts b/typescript/src/criteria/simple.ts index 5f187fc..e3000d6 100644 --- a/typescript/src/criteria/simple.ts +++ b/typescript/src/criteria/simple.ts @@ -1,13 +1,11 @@ -import type {CriterionArgsType, IncompleteType, PairType} from '../types'; -import {getCandidate} from '../lib'; +import type {FactorsType, PairType} from '../types'; +import { Controller } from '../controller'; -export default function* ( - incomplete: IncompleteType, - criterionArgs: CriterionArgsType, -): Generator { - const {row, parents} = criterionArgs; +export default function* (ctrl: Controller): Generator { + const incomplete = ctrl.incomplete; for (let pair of incomplete.values()) { - const storable = row.storable(getCandidate(pair, parents)); + const cand = ctrl.getCandidate(pair); + const storable = ctrl.storable(cand); if (storable === null || storable === 0) { continue; } diff --git a/typescript/src/exceptions.ts b/typescript/src/exceptions.ts index ca6e51e..9450bac 100644 --- a/typescript/src/exceptions.ts +++ b/typescript/src/exceptions.ts @@ -1,5 +1,10 @@ +import { Scalar } from "./types"; -export class InvalidCondition { - public name = 'InvalidCondition'; - public message = 'It will never meet the condition'; +export class NotReady extends Error { + constructor(public key: Scalar) { + super(`Not yet '${key}' in the object`); + } +} + +export class NeverMatch extends Error { }; diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 68862a0..f3be2af 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -6,240 +6,46 @@ import greedy from "./criteria/greedy"; import simple from "./criteria/simple"; import {PictConstraintsLexer} from "./utils/pict"; - -import {InvalidCondition} from "./exceptions"; -import { - range, - product, - combinations, - len, - getItems, - getCandidate, - ascOrder, - primeGenerator, - unique, -} from "./lib"; - -import { - IndicesType, - FactorsType, - SerialsType, - MappingTypes, - Scalar, - Dict, - IncompleteType, - ParentsType, - CandidateType, - RowType, - OptionsType, - FilterType, - PairType, - SorterType, - SuggestRowType, -} from "./types"; - -const serialize = (factors: FactorsType): MappingTypes => { - let origin = 0; - const serials: SerialsType = new Map(); - const indices: IndicesType = new Map(); - const parents: ParentsType = new Map(); - - const primer = primeGenerator(); - getItems(factors).map(([subscript, factorList]) => { - const length = len(factorList); - const serialList: number[] = []; - range(origin, origin + length).map((index) => { - const serial = primer.next().value; - serialList.push(serial); - parents.set(serial, subscript); - indices.set(serial, index); - }); - serials.set(subscript, serialList); - origin += length; - }); - return { serials, parents, indices }; -}; - -const makeIncomplete = ( - mappings: MappingTypes, - length: number, - sorter: SorterType, - seed: Scalar -): IncompleteType => { - const { serials, indices } = mappings; - const pairs: PairType[] = []; - const allKeys = getItems(serials).map(([k, _]) => k); - for (const keys of combinations(allKeys, length)) { - const comb = range(0, length).map((i) => serials.get(keys[i]) as PairType); - for (let pair of product(...comb)) { - pair = pair.sort(ascOrder); - pairs.push(pair); - } - } - const incomplete: IncompleteType = new Map(); - for (let pair of sorter(pairs, { seed, indices })) { - incomplete.set(unique(pair), pair); - } - return incomplete; -}; - -class Row extends Map implements RowType { - // index: number - private length: number; - public isArray: Boolean; - constructor( - row: CandidateType, - private mappings: MappingTypes, - private factors: FactorsType, - public preFilter?: FilterType - ) { - super(); - for (const [k, v] of row) { - this.set(k, v); - } - this.length = len(factors); - this.isArray = factors instanceof Array; - } - - filled(): boolean { - return this.size === this.length; - } - - New(row?: CandidateType) { - return new Row(row || [], this.mappings, this.factors, this.preFilter); - } - - storable(candidate: CandidateType) { - let num = 0; - for (let [key, el] of candidate) { - let existing: number | undefined = this.get(key); - if (typeof existing === "undefined") { - num++; - } else if (existing != el) { - return null; - } - } - if (!this.preFilter) { - return num; - } - const candidates: CandidateType = [...this.entries()].concat(candidate); - const nxt: Row = this.New(candidates); - if (!this.preFilter(nxt.toObject())) { - return null; - } - return num; - } - - toMap(): Map { - const result: Map = new Map(); - const { indices, serials } = this.mappings; - for (let [key, serial] of this.entries()) { - const index = indices.get(serial) as number; - const first = indices.get((serials.get(key) as PairType)[0]); - // @ts-ignore TS7015 - result.set(key, this.factors[key][index - first]); - } - return result; - } - - toObject() { - const obj: Dict = {}; - for (let [key, value] of this.toMap().entries()) { - obj[key] = value; - } - return obj; - } - - restore() { - if (this.isArray) { - const map = this.toMap(); - return getItems(map) - .sort((a, b) => (a[0] > b[0] ? 1 : -1)) - .map(([_, v]) => v); - } - return this.toObject(); - } - - complement(): Row { - getItems(this.mappings.serials).map(([k, vs]) => { - for (let v of vs) { - if (this.storable([[k, v]])) { - this.set(k, v); - break; - } - } - }); - if (!this.filled()) { - throw new InvalidCondition(); - } - return this; - } -} +import { FactorsType, OptionsType, SuggestRowType } from "./types"; +import { Controller } from "./controller"; +import { NeverMatch } from "./exceptions"; const makeAsync = function* ( factors: T, - options: OptionsType = {} + options: OptionsType = {} ) { - let { - length = 2, - sorter = hash, + const { criterion = greedy, - seed = "", - tolerance = 0, + postFilter, } = options; - const { preFilter, postFilter } = options; - const mappings = serialize(factors); - const { parents } = mappings; - const incomplete = makeIncomplete(mappings, length, sorter, seed); // {"1,2": [1,2], "3,4": [3,4]} - - let row: Row = new Row([], mappings, factors, preFilter); - - for (let [pairKey, pair] of incomplete.entries()) { - if (!row.storable(getCandidate(pair, parents))) { - incomplete.delete(pairKey); - } - } - while (incomplete.size) { - if (row.filled()) { - if (!postFilter || postFilter(row.toObject())) { - yield row.restore() as SuggestRowType; - } - row = row.New([]); - } - let finished = true; - for (let pair of criterion(incomplete, { - row, - parents, - length, - tolerance, - })) { - if (row.filled()) { - finished = false; + const ctrl = new Controller(factors, options); + do { + for (let pair of criterion(ctrl)) { + if (ctrl.isFilled(ctrl.row)) { break; } - - for (let [key, value] of getCandidate(pair, parents)) { - row.set(key, value); + ctrl.setPair(pair); + } + try { + const complete = ctrl.close(); + if (complete) { + if (!postFilter || postFilter(ctrl.toObject(ctrl.row))) { + yield ctrl.restore() as SuggestRowType; + } else { + ctrl.discard(); + } } - - for (let p of combinations([...row.values()], length)) { - incomplete.delete(unique(p)); + } catch (e) { + if (e instanceof NeverMatch) { + break; } + throw e; } - if (finished && !row.filled()) { - row.complement(); - } - } - if (row.size) { - row = row.complement(); - if (!postFilter || postFilter(row.toObject())) { - yield row.restore() as SuggestRowType; - } - } + } while (ctrl.incomplete.size); }; -const make = (factors: T, options: OptionsType = {}) => { +const make = (factors: T, options: OptionsType = {}) => { return [...makeAsync(factors, options)]; }; diff --git a/typescript/src/lib.ts b/typescript/src/lib.ts index 2f083c0..cd9d0cc 100644 --- a/typescript/src/lib.ts +++ b/typescript/src/lib.ts @@ -1,7 +1,9 @@ // @ts-ignore 2307 export { hex as md5 } from 'js-md5'; +import { NotReady } from './exceptions'; import type { FactorsType, Scalar, ParentsType, CandidateType, PairType, + Dict, } from './types'; // https://gist.github.com/righ/71e32be8e33f74bde516c06f80c941e8 @@ -125,3 +127,15 @@ export function* primeGenerator(): Generator { } } } + + + +export const proxyHandler = { + get(obj: Dict, key: string, receiver: any) { + if (key in obj) { + return obj[key]; + } + throw new NotReady(key); + }, +}; + diff --git a/typescript/src/types.ts b/typescript/src/types.ts index 340da9a..c5058b6 100644 --- a/typescript/src/types.ts +++ b/typescript/src/types.ts @@ -1,3 +1,5 @@ +import type { Controller } from "./controller"; + export type Scalar = number | string; export type Dict = { [s: string]: any }; export type List = { [index: number]: any[] }; @@ -6,32 +8,31 @@ export type SerialsType = Map; export type ParentsType = Map; export type IndicesType = Map; -export type MappingTypes = { - serials: SerialsType; - parents: ParentsType; - indices: IndicesType; -}; - export type FilterRowType = { [key: string]: any; [index: number]: any; } +export type ArrayTuple = any[][]; +export type ArrayObject = { [s: string]: any[] }; +export type FactorsType = ArrayTuple | ArrayObject; + +export type SuggestRowType = T extends ArrayTuple + ? T[number][number][] + : T extends ArrayObject ? { [K in keyof T]: T[K][number] } + : unknown; + export type FilterType = (row: FilterRowType) => boolean; +export type SuggestFilterType = (row: SuggestRowType) => boolean; export type PairType = number[]; -export type IncompleteType = Map; - +export type PairByKey = Map; export type CandidateType = [Scalar, number][]; export interface RowType { - size: number; - isArray: Boolean; - filled: () => Boolean; - values: () => IterableIterator; - storable: (candidate: CandidateType) => number | null; + consumed: PairByKey; }; export type SorterType = ( @@ -51,21 +52,12 @@ export interface CriterionArgsType { tolerance: number; }; -export interface OptionsType { +export interface OptionsType { length?: number; sorter?: SorterType; - criterion?: (incomplete: IncompleteType, options: CriterionArgsType) => IterableIterator; + criterion?: (ctrl: Controller) => IterableIterator; seed?: Scalar; tolerance?: number; - preFilter?: FilterType; - postFilter?: FilterType; + preFilter?: FilterType | SuggestFilterType; + postFilter?: FilterType | SuggestFilterType; }; - -export type ArrayTuple = any[][]; -export type ArrayObject = { [s: string]: any[] }; -export type FactorsType = ArrayTuple | ArrayObject; - -export type SuggestRowType = T extends ArrayTuple - ? T[number][number][] - : T extends ArrayObject ? { [K in keyof T]: T[K][number] } - : unknown; From 4a3ec74adfe03a6c26781bf83ba6bdc31dadc4bf Mon Sep 17 00:00:00 2001 From: righ Date: Tue, 27 Aug 2024 03:18:02 +0900 Subject: [PATCH 39/55] 2.4.0-alpha.0 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index a20f25e..38fefbd 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.3.2-alpha.5", + "version": "2.4.0-alpha.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.3.2-alpha.5", + "version": "2.4.0-alpha.0", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index c08a825..24f03df 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.3.2-alpha.5", + "version": "2.4.0-alpha.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From 8faaedff911dfbb97e510e388a6271929294fbe4 Mon Sep 17 00:00:00 2001 From: righ Date: Wed, 28 Aug 2024 01:32:59 +0900 Subject: [PATCH 40/55] test: add tests --- typescript/src/__tests__/pict.test.ts | 149 ++++++++++- typescript/src/utils/pict.ts | 349 ++++++++++++++++---------- 2 files changed, 358 insertions(+), 140 deletions(-) diff --git a/typescript/src/__tests__/pict.test.ts b/typescript/src/__tests__/pict.test.ts index 808057e..5e8c279 100644 --- a/typescript/src/__tests__/pict.test.ts +++ b/typescript/src/__tests__/pict.test.ts @@ -28,7 +28,7 @@ describe('PictConstraintsLexer with single constraints', () => { it('should handle NOT conditions correctly', () => { const lexer = new PictConstraintsLexer(` - IF NOT [PRODUCT] = "Book" THEN [AVAILABLE] = "Yes" ELSE [AVAILABLE] = "No"; + IF NOT [PRODUCT] = "Book" THEN [AVAILABLE] <> "No" ELSE [AVAILABLE] = "No"; `, false); const row1 = { PRODUCT: 'Pen', AVAILABLE: 'Yes' }; expect(lexer.filter(row1)).toBe(true); @@ -47,7 +47,7 @@ describe('PictConstraintsLexer with single constraints', () => { const row1 = { CATEGORY: 'Electronics', BRAND: 'Sony', WARRANTY: 'Included' }; expect(lexer.filter(row1)).toBe(true); - const row2 = { CATEGORY: 'Electronics', BRAND: 'Samsung', WARRANTY: 'Not Included' }; + const row2 = { CATEGORY: 'Electronics', BRAND: 'General Electric Company', WARRANTY: 'Not Included' }; expect(lexer.filter(row2)).toBe(true); const row3 = { CATEGORY: 'Electronics', BRAND: 'Sony', WARRANTY: 'Not Included' }; @@ -71,17 +71,17 @@ describe('PictConstraintsLexer with single constraints', () => { expect(lexer.filter(row4)).toBe(false); }); - it('should handle string equality conditions', () => { + it('should handle fields containing spaces', () => { const lexer = new PictConstraintsLexer(` - IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE [STATUS] = "Active"; + IF [PRODUCT NAME] = "Laptop" THEN [PRICE] > 500 ELSE [PRICE] <= 500; `, false); - const row1 = { NAME: 'Bob', STATUS: 'Inactive' }; + const row1 = { 'PRODUCT NAME': 'Laptop', PRICE: 600 }; expect(lexer.filter(row1)).toBe(true); - const row2 = { NAME: 'Alice', STATUS: 'Active' }; - expect(lexer.filter(row2)).toBe(true); + const row2 = { 'PRODUCT NAME': 'Laptop', PRICE: 400 }; + expect(lexer.filter(row2)).toBe(false); - const row3 = { NAME: 'Bob', STATUS: 'Active' }; + const row3 = { 'PRODUCT NAME': 'Desktop', PRICE: 600 }; expect(lexer.filter(row3)).toBe(false); }); @@ -118,6 +118,40 @@ describe('PictConstraintsLexer with single constraints', () => { const row5 = { AGE: 25, COUNTRY: 'Canada', STATUS: 'Denied' }; expect(lexer.filter(row5)).toBe(false); }); + it('should handle false in ELSE condition', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE FALSE; + `, false); + const row1 = { NAME: 'Bob', STATUS: 'Inactive' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', STATUS: 'Active' }; + expect(lexer.filter(row2)).toBe(false); + }); + + it('should handle true in ELSE condition', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Bob" THEN [STATUS] = "Inactive" ELSE true; + `, false); + const row1 = { NAME: 'Bob', STATUS: 'Inactive' }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', STATUS: 'Active' }; + expect(lexer.filter(row2)).toBe(true); + }); + it('Compare with other fields', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = [ALIAS] THEN [AGE] <= 26; + `, false); + const row1 = { NAME: 'Bob', ALIAS: 'Bob', AGE: 18 }; + expect(lexer.filter(row1)).toBe(true); + + const row2 = { NAME: 'Alice', ALIAS: 'Lissie', AGE: 25 }; + expect(lexer.filter(row2)).toBe(true); + + const row3 = { NAME: 'Shohei', ALIAS: 'Shohei', AGE: 30 }; + expect(lexer.filter(row3)).toBe(false); + }); }); describe('PictConstraintsLexer with multiple constraints', () => { @@ -248,3 +282,102 @@ describe('PictConstraintsLexer with multiple constraints', () => { expect(lexer.filter(row3)).toBe(true); }); }); + +describe('PictConstraintsLexer with invalid constraints', () => { + it('Unknown comparer', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] @ "Alice" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"; + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Unknown comparison operator: @'); + }); + + it('Comparison operator missing, got a value', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] "Alice" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"; + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Expected comparison operator but found value: "Alice"'); + }); + + it('Comparison operator missing, got an operator', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] AND TRUE THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"; + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Expected comparison operator but found operator: AND'); + }); + + it('Comparison operator and value missing, got then', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive" + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('A comparison operator and value are required after the field.'); + }); + it('Nothing after IF', () => { + const lexer = new PictConstraintsLexer(` + IF THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive" + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Expected field or value after "IF", "THEN", "ELSE"'); + }); + + it('Nothing after THEN', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Summer" THEN ELSE [STATUS] = "Active" + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Expected field or value after "IF", "THEN", "ELSE"'); + }); + + it('Nothing after ELSE', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] = "Summer" THEN [STATUS] = "Active" ELSE + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Expected field or value after "IF", "THEN", "ELSE"'); + }); + + + it('IF is missing, typo', () => { + const lexer = new PictConstraintsLexer(` + F [NAME] = "Summer" THEN [STATUS] = "Active" + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('Unknown token: F'); + }); + + it('IF is nothing', () => { + const lexer = new PictConstraintsLexer(` + [NAME] = "Summer" THEN [STATUS] = "Active" + `, false); + expect(lexer.errors.length).toBe(1); + expect(lexer.errors[0]).toBe('The leading "IF" is missing, found [NAME]'); + }); + + + it('Multiple invalid expressions', () => { + const lexer = new PictConstraintsLexer(` + IF [NAME] THEN [STATUS] = "Active"; + IF [NAME] = "Summer" THEN [STATUS] = "Active"; + IF [NAME] = "Summer" THEN [STATUS] = "Active" ELSE; + IF [NAME] = "Summer" THEN [STATUS] = "Active"; + IF [NAME] @ "Summer" THEN [STATUS] = "Active" ELSE [STATUS] = "Inactive"; + `, false); + + expect(lexer.errors.length).toBe(5); + + expect(lexer.errors[0]).toBe('A comparison operator and value are required after the field.' ); + expect(lexer.errors[1]).toBe(null); + expect(lexer.errors[2]).toBe('Expected field or value after "IF", "THEN", "ELSE"' ); + expect(lexer.errors[3]).toBe(null); + expect(lexer.errors[4]).toBe('Unknown comparison operator: @'); + + expect(lexer.filters[0]).toBeNull(); + expect(lexer.filters[1]).not.toBeNull(); + expect(lexer.filters[2]).toBeNull(); + expect(lexer.filters[3]).not.toBeNull(); + expect(lexer.filters[4]).toBeNull(); + }); +}); \ No newline at end of file diff --git a/typescript/src/utils/pict.ts b/typescript/src/utils/pict.ts index ca1cf50..5ebef26 100644 --- a/typescript/src/utils/pict.ts +++ b/typescript/src/utils/pict.ts @@ -1,7 +1,7 @@ import type { FilterRowType, FilterType } from '../types'; type Token = { - type: string; + type: TokenType; value: string; } @@ -9,15 +9,76 @@ type CacheType = { [key: string]: any; }; +enum TokenType { + REF = 'REF', + STRING = 'STRING', + NUMBER = 'NUMBER', + BOOLEAN = 'BOOLEAN', + NULL = 'NULL', + IF = 'IF', + ELSE = 'ELSE', + THEN = 'THEN', + COMPARER = 'COMPARER', + OPERATOR = 'OPERATOR', + LPAREN = 'LPAREN', + RPAREN = 'RPAREN', + LBRACE = 'LBRACE', + RBRACE = 'RBRACE', + COMMA = 'COMMA', + COLON = 'COLON', + SEMICOLON = 'SEMICOLON', + WHITESPACE = 'WHITESPACE', + UNKNOWN = 'UNKNOWN', +} + +function classifyToken(token: string): Token { + if (token.startsWith('[') && token.endsWith(']')) { + return { type: TokenType.REF, value: token }; + } + if (token.startsWith('"') && token.endsWith('"')) { + return { type: TokenType.STRING, value: token }; + } + if (!isNaN(parseFloat(token))) { + return { type: TokenType.NUMBER, value: token }; + } + if (['TRUE', 'FALSE'].includes(token.toUpperCase())) { + return { type: TokenType.BOOLEAN, value: token.toUpperCase() }; + } + if (token.toUpperCase() === TokenType.NULL) { + return { type: TokenType.NULL, value: token.toUpperCase() }; + } + if ([TokenType.IF, TokenType.ELSE, TokenType.THEN].includes(token.toUpperCase() as TokenType)) { + return { type: token.toUpperCase() as TokenType, value: token.toUpperCase() }; + } + if (['=', '<>', '>', '<', '>=', '<=', 'IN', 'LIKE'].includes(token.toUpperCase())) { + return { type: TokenType.COMPARER, value: token.toUpperCase() }; + } + if (['AND', 'OR', 'NOT'].includes(token.toUpperCase())) { + return { type: TokenType.OPERATOR, value: token.toUpperCase() }; + } + switch (token) { + case '(': return { type: TokenType.LPAREN, value: token }; + case ')': return { type: TokenType.RPAREN, value: token }; + case '{': return { type: TokenType.LBRACE, value: token }; + case '}': return { type: TokenType.RBRACE, value: token }; + case ',': return { type: TokenType.COMMA, value: token }; + case ':': return { type: TokenType.COLON, value: token }; + case ';': return { type: TokenType.SEMICOLON, value: token }; + default: return { type: TokenType.UNKNOWN, value: token }; + } +} + +const isWhiteSpace = (char: string) => { + return char === ' ' || char === '\n' || char === '\t'; +}; + export class PictConstraintsLexer { private tokens: Token[] = []; private cache: CacheType = {}; public filters: (FilterType | null)[] = []; - public errors: string[][] = []; + public errors: (string | null)[] = []; constructor(private input: string, private debug=false) { - this.input = input; - this.debug = debug; this.tokenize(); this.analyze(); } @@ -27,8 +88,9 @@ export class PictConstraintsLexer { let buffer = ''; let insideQuotes = false; let insideBraces = false; + let insideBrackets = false; - const addToken = (type: string, value: string) => { + const addToken = (type: TokenType, value: string) => { tokens.push({ type, value }); }; @@ -39,7 +101,7 @@ export class PictConstraintsLexer { insideQuotes = !insideQuotes; buffer += char; if (!insideQuotes) { - addToken('STRING', buffer); + addToken(TokenType.STRING, buffer); buffer = ''; } } else if (insideQuotes) { @@ -49,10 +111,12 @@ export class PictConstraintsLexer { tokens.push(classifyToken(buffer)); buffer = ''; } + insideBrackets = true; buffer += char; - } else if (char === ']') { + } else if (char === ']' && insideBrackets) { buffer += char; tokens.push(classifyToken(buffer)); + insideBrackets = false; buffer = ''; } else if (char === '{') { insideBraces = true; @@ -60,21 +124,21 @@ export class PictConstraintsLexer { tokens.push(classifyToken(buffer)); buffer = ''; } - addToken('LBRACE', char); + addToken(TokenType.LBRACE, char); } else if (char === '}') { insideBraces = false; if (buffer.length > 0) { tokens.push(classifyToken(buffer)); buffer = ''; } - addToken('RBRACE', char); + addToken(TokenType.RBRACE, char); } else if (char === ',' && insideBraces) { if (buffer.length > 0) { tokens.push(classifyToken(buffer)); buffer = ''; } - addToken('COMMA', char); - } else if ('[]=<>!();:'.includes(char) && !insideBraces) { + addToken(TokenType.COMMA, char); + } else if ('[]=<>!();:'.includes(char) && !insideBraces && !insideBrackets) { if (buffer.length > 0) { tokens.push(classifyToken(buffer)); buffer = ''; @@ -93,7 +157,7 @@ export class PictConstraintsLexer { } else { tokens.push(classifyToken(char)); } - } else if (isWhiteSpace(char) && !insideBraces) { + } else if (isWhiteSpace(char) && !insideBraces && !insideBrackets) { if (buffer.length > 0) { tokens.push(classifyToken(buffer)); buffer = ''; @@ -102,13 +166,9 @@ export class PictConstraintsLexer { while (i + 1 < constraints.length && isWhiteSpace(constraints[i + 1])) { whitespaceBuffer += constraints[++i]; } - addToken('WHITESPACE', whitespaceBuffer); - } else if (isWhiteSpace(char) && insideBraces) { - if (buffer.length > 0) { - tokens.push(classifyToken(buffer)); - buffer = ''; - } - addToken('WHITESPACE', char); + addToken(TokenType.WHITESPACE, whitespaceBuffer); + } else if (isWhiteSpace(char) && (insideBraces || insideBrackets)) { + buffer += char; } else { buffer += char; } @@ -125,10 +185,7 @@ export class PictConstraintsLexer { let tokenIndex = 0; let setIndex = 0; let regexIndex = 0; - let errorMessages: string[] = []; - const errors: string[][] = []; const tokens = this.tokens; - const filters: (FilterType | null)[] = []; const nextToken = () => { while (tokenIndex < tokens.length && tokens[tokenIndex].type === 'WHITESPACE') { @@ -140,18 +197,25 @@ export class PictConstraintsLexer { const parseExpression: () => string = () => { let expr = parseTerm(); let token = nextToken(); + if (token?.type === TokenType.UNKNOWN) { + throw new Error(`Unexpected token: ${token.value}`); + } while (token && token.type === 'OPERATOR' && token.value === 'OR') { const right = parseTerm(); expr = `(${expr} || ${right})`; token = nextToken(); } tokenIndex--; // Go back one token - return expr; + return expr || 'true'; } const parseTerm: () => string = () => { let term = parseFactor(); + let token = nextToken(); + if (token?.type === TokenType.UNKNOWN) { + throw new Error(`Unexpected token: ${token.value}`); + } while (token && token.type === 'OPERATOR' && token.value === 'AND') { const right = parseFactor(); term = `(${term} && ${right})`; @@ -163,38 +227,57 @@ export class PictConstraintsLexer { const parseFactor: () => string = () => { let token = nextToken(); - if (token && token.type === 'OPERATOR' && token.value === 'NOT') { - const factor = parseFactor(); - return `!(${factor})`; - } else if (token && token.type === 'LPAREN') { - const expr = parseExpression(); - token = nextToken(); - if (!token || token.type !== 'RPAREN') { - errorMessages.push('Expected closing parenthesis'); - return 'false'; + if (token != null) { + if (token.type === 'OPERATOR' && token.value === 'NOT') { + const factor = parseFactor(); + return `!(${factor})`; + } + if (token.type === TokenType.LPAREN) { + const expr = parseExpression(); + token = nextToken(); + if (!token || token.type !== TokenType.RPAREN) { + throw new Error('Expected closing parenthesis'); + } + return `(${expr})`; + } + if (token.type === TokenType.BOOLEAN) { + return token.value.toUpperCase() === 'TRUE' ? 'true' : 'false'; + } + if (token.type === TokenType.UNKNOWN) { + throw new Error(`Unexpected token: ${token.value}`); } - return `(${expr})`; - } else if (token && token.type === 'BOOLEAN') { - return token.value.toUpperCase() === 'TRUE' ? 'true' : 'false'; - } else { - tokenIndex--; // Go back one token - return parseCondition(); } + tokenIndex--; // Go back one token + return parseCondition(); } const parseCondition: () => string = () => { const left = parseOperand(); + if (left == null) { + throw new Error('Expected field or value after "IF", "THEN", "ELSE"'); + + } const comparerToken = nextToken(); - if (!comparerToken || comparerToken.type !== 'COMPARER') { - errorMessages.push('Expected comparer'); - return 'false'; + if ([TokenType.NUMBER, TokenType.STRING, TokenType.BOOLEAN, TokenType.NULL].includes(comparerToken?.type!)) { + throw new Error(`Expected comparison operator but found value: ${comparerToken?.value}`); } - const comparer = comparerToken.value; + if (comparerToken?.type === TokenType.THEN) { + throw new Error('A comparison operator and value are required after the field.'); + } + if (comparerToken?.type === 'OPERATOR') { + throw new Error(`Expected comparison operator but found operator: ${comparerToken.value}`); + } + + const comparer = comparerToken?.value; + if (comparer === 'IN') { const right = parseSet(); return `${right}.has(${left})`; } const right = parseOperand(); + if (right == null) { + throw new Error('Expected field or value'); + } switch (comparer) { case '=': return `${left} === ${right}`; @@ -216,26 +299,25 @@ export class PictConstraintsLexer { } return `this.cache['${regexKey}'].test(${left})`; default: - errorMessages.push(`Unknown comparer: ${comparer}`); - return 'false'; + throw new Error(`Unknown comparison operator: ${comparer}`); } } const parseSet: () => string = () => { const elements: string[] = []; let token = nextToken(); - if (token && token.type === 'LBRACE') { + if (token && token.type === TokenType.LBRACE) { token = nextToken(); - while (token && token.type !== 'RBRACE') { - if (token.type === 'STRING') { + while (token && token.type !== TokenType.RBRACE) { + if (token.type === TokenType.STRING) { elements.push(token.value.slice(1, -1)); // remove quotes - } else if (token.type !== 'COMMA' && token.type !== 'WHITESPACE') { - errorMessages.push(`Unexpected token: ${token.value}`); + } else if (token.type !== TokenType.COMMA && token.type !== TokenType.WHITESPACE) { + throw new Error(`Unexpected token in array: ${token.value}`); } token = nextToken(); } } else { - errorMessages.push(`Expected '{' but found ${token ? token.value : 'null'}`); + throw new Error(`Expected '{' but found ${token ? token.value : TokenType.NULL}`); } const setKey = `set_${setIndex++}`; if (!this.cache[setKey]) { @@ -244,75 +326,119 @@ export class PictConstraintsLexer { return `this.cache['${setKey}']`; } - const parseOperand: () => string = () => { + const parseOperand: () => string | null = () => { const token = nextToken(); if (token == null) { - errorMessages.push('Unexpected end of input'); - return 'false'; + return null; } - if (token.type === 'REF') { + if (token.type === TokenType.REF) { const key = token.value.slice(1, -1); // remove [ and ] return `row["${key}"]`; - } else if (token.type === 'STRING') { + } else if (token.type === TokenType.STRING) { const value = token.value; // keep quotes for string literals return `${value}`; - } else if (token.type === 'NUMBER') { + } else if (token.type === TokenType.NUMBER) { return token.value; - } else if (token.type === 'BOOLEAN') { + } else if (token.type === TokenType.BOOLEAN) { return token.value === 'TRUE' ? 'true' : 'false'; - } else if (token.type === 'NULL') { - return 'null'; + } else if (token.type === TokenType.NULL) { + return TokenType.NULL; + } else { + return null; + } + } + + const abandon = () => { + while (tokenIndex < tokens.length && tokens[tokenIndex].type !== TokenType.SEMICOLON) { + tokenIndex++; + } + } + + const close = (code: string | null, error: string | null) => { + // Invariably, one of the two will be null. + if (code == null) { + if (this.debug) { + console.error(`Error[${this.errors.length}]:`, error); + } + this.filters.push(null); + this.errors.push(error); } else { - errorMessages.push(`Unexpected token: ${token.value}`); - return 'false'; + if (this.debug) { + console.debug(`Code[${this.filters.length}]:`, code); + } + try { + const f = this.makeClosure(code); + this.filters.push(f); + this.errors.push(null); + } catch (e) { + console.error(e); + this.filters.push(null); + // @ts-ignore + this.errors.push(`RuntimeError[${this.errors.length}]:`, e.message); + } + } } - while (tokenIndex < tokens.length) { + const read = () => { + try { + const expr = parseExpression(); + return expr; + } catch (e) { + // @ts-ignore + close(null, e.message); + } + // If the conditional expression ends with “ELSE”, + // the current index reaches a semicolon, and the next expression is skipped by the abandon function. + // Therefore, the index is reset to the previous one. + tokenIndex--; + abandon(); + return null; + }; + + while (tokens[tokenIndex] != null) { const token = nextToken(); if (token == null) { break; } - if (token.type === 'IF') { - const condition = parseExpression(); + if (token.type === TokenType.IF) { + const action = read(); + if (action == null) { + continue; + } const thenToken = nextToken(); - if (!thenToken || thenToken.type !== 'THEN') { - errorMessages.push('Expected THEN'); - break; + if (!thenToken || thenToken.type !== TokenType.THEN) { + abandon() + continue; + } + const thenAction = read(); + if (thenAction == null) { + continue; } - const thenAction = parseExpression(); const elseToken = nextToken(); - let elseAction = 'true'; - if (elseToken && elseToken.type === 'ELSE') { - elseAction = parseExpression(); + let elseAction: string | null = 'true'; + if (elseToken && elseToken.type === TokenType.ELSE) { + elseAction = read(); + if (elseAction == null) { + continue; + } } else { tokenIndex--; // Go back one token if ELSE is not found } - const filterCode = `return (${condition} ? (${thenAction}) : (${elseAction}));`; - try { - if (this.debug) { - console.debug(`code[${filters.length}]:`, filterCode); - } - const f = this.makeClosure(filterCode); - filters.push(f as FilterType); - } catch (e) { - filters.push(null); - // @ts-ignore - errorMessages.push(e.message); - } - errors.push(errorMessages); - errorMessages = []; - } else if (token.type === 'SEMICOLON') { + const code = `return (${action} ? (${thenAction}) : (${elseAction}));`; + close(code, null); + } else if (token.type === TokenType.SEMICOLON) { // do nothing } else { - errorMessages.push(`Unexpected token: ${token.value}`); - errors.push(errorMessages); - break; + if (token.type === TokenType.UNKNOWN) { + close(null, `Unknown token: ${token.value}`); + } else { + close(null, `The leading "IF" is missing, found ${token.value}`); + } + abandon(); } } - this.filters = filters; - this.errors = errors; } private makeClosure (code: string) { @@ -337,44 +463,3 @@ export class PictConstraintsLexer { } } -function classifyToken(token: string): Token { - if (token.startsWith('[') && token.endsWith(']')) { - return { type: 'REF', value: token }; - } - if (token.startsWith('"') && token.endsWith('"')) { - return { type: 'STRING', value: token }; - } - if (!isNaN(parseFloat(token))) { - return { type: 'NUMBER', value: token }; - } - if (['TRUE', 'FALSE'].includes(token.toUpperCase())) { - return { type: 'BOOLEAN', value: token.toUpperCase() }; - } - if (token.toUpperCase() === 'NULL') { - return { type: 'NULL', value: token.toUpperCase() }; - } - if (['IF', 'ELSE', 'THEN'].includes(token.toUpperCase())) { - return { type: token.toUpperCase(), value: token.toUpperCase() }; - } - if (['=', '<>', '>', '<', '>=', '<=', 'IN', 'LIKE'].includes(token.toUpperCase())) { - return { type: 'COMPARER', value: token.toUpperCase() }; - } - if (['AND', 'OR', 'NOT'].includes(token.toUpperCase())) { - return { type: 'OPERATOR', value: token.toUpperCase() }; - } else { - switch (token) { - case '(': return { type: 'LPAREN', value: token }; - case ')': return { type: 'RPAREN', value: token }; - case '{': return { type: 'LBRACE', value: token }; - case '}': return { type: 'RBRACE', value: token }; - case ',': return { type: 'COMMA', value: token }; - case ':': return { type: 'COLON', value: token }; - case ';': return { type: 'SEMICOLON', value: token }; - default: throw new Error(`Unknown token: ${token}`); - } - } -} - -const isWhiteSpace = (char: string) => { - return char === ' ' || char === '\n' || char === '\t'; -}; From 02999111bb2fa4e1b0137213fa4378754bb0582f Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 03:42:03 +0900 Subject: [PATCH 41/55] 2.4.0-alpha.1 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 38fefbd..f249b62 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.4.0-alpha.0", + "version": "2.4.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.4.0-alpha.0", + "version": "2.4.0-alpha.1", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 24f03df..1d2f574 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.4.0-alpha.0", + "version": "2.4.0-alpha.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From 2184f4bb666522fbcddcff56a97e161599a3ebc6 Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 05:40:12 +0900 Subject: [PATCH 42/55] update README and types --- typescript/README.md | 175 +++++++++++++++--------- typescript/src/__tests__/filter.test.ts | 9 +- typescript/src/__tests__/index.test.ts | 6 +- typescript/src/controller.ts | 22 +-- typescript/src/criteria/greedy.ts | 4 +- typescript/src/exceptions.ts | 4 +- typescript/src/index.ts | 9 +- typescript/src/lib.ts | 12 +- typescript/src/types.ts | 30 ++-- 9 files changed, 160 insertions(+), 111 deletions(-) diff --git a/typescript/README.md b/typescript/README.md index f655ee6..87dce4a 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -2,6 +2,9 @@ [![Workflow](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) [![codecov](https://codecov.io/gh/walkframe/covertable/branch/master/graph/badge.svg)](https://codecov.io/gh/walkframe/covertable) +# What is covertable? +covertable is a powerful tool for generating pairwise combinations of input factors, designed for both Node.js and browser environments. It's easy to use, flexible, and supports advanced filtering options, making it perfect for testing scenarios and generating comprehensive datasets. + # Installation ```sh @@ -10,15 +13,15 @@ $ npm install covertable --save # Usage -## Simple demo in Node.js: +## Simple usage in Node.js: ```javascript var covertable = require('covertable'); -var make = covertable.default; +var make = covertable.make; -var machine = ['iphone', 'pixel']; -var os = ['ios', 'android']; -var browser = ['FireFox', 'Chrome', 'Safari']; +var machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; +var os = ["iOS", "Android"]; +var browser = ["FireFox", "Chrome", "Safari"]; make([machine, os, browser]); ``` @@ -26,64 +29,47 @@ Output: ```javascript [ - [ 'pixel', 'android', 'Chrome' ], - [ 'pixel', 'ios', 'Safari' ], - [ 'pixel', 'android', 'FireFox' ], - [ 'iphone', 'android', 'Safari' ], - [ 'iphone', 'ios', 'Chrome' ], - [ 'iphone', 'ios', 'FireFox' ] + [ 'Pixel', 'iOS', 'Chrome' ], + [ 'ZenFone', 'iOS', 'FireFox' ], + [ 'Pixel', 'Android', 'Safari' ], + [ 'Galaxy', 'Android', 'Chrome' ], + [ 'XPERIA', 'Android', 'FireFox' ], + [ 'Pixel', 'iOS', 'FireFox' ], + [ 'iPhone', 'iOS', 'Safari' ], + [ 'Galaxy', 'iOS', 'Safari' ], + [ 'XPERIA', 'iOS', 'Chrome' ], + [ 'ZenFone', 'Android', 'Chrome' ], + [ 'Galaxy', 'iOS', 'FireFox' ], + [ 'iPhone', 'Android', 'Chrome' ], + [ 'iPhone', 'iOS', 'FireFox' ], + [ 'ZenFone', 'iOS', 'Safari' ], + [ 'XPERIA', 'iOS', 'Safari' ] ] ``` Of course, it also works in the browser well. -## Advanced demo in TypeScript: +## Advanced usage in TypeScript: -```typescript -import { default as make, makeAsync, sorters, criteria } from "covertable"; - -const machine = ['iphone', 'pixel']; -const os = ['ios', 'android']; -const browser = ['FireFox', 'Chrome', 'Safari']; - -make([machine, os, browser], { // optional - length: 2, // default: 2 - criterion: criteria.simple, // default: criteria.greedy - sorter: sorters.random, // default: sorters.hash - preFilter: (row: any) => !(row[1] === 'android' && row[0] !== 'pixel'), // default: null - postFilter: (row: any) => !(row[1] === 'ios' && row[2] !== 'Safari'), // default: null -}); -``` +As previously mentioned, when elements are specified as an array, the results will also be in array form. However, if the elements are specified as an object, the results will be in object form. -Output: +The following example uses preFilter and postFilter to apply constraints to the output results. In this case, `SuggestRowType` can also be used to infer the type of row parameters that the filter function receives. ```typescript -[ // filtered - [ 'iphone', 'ios', 'Safari' ], - [ 'pixel', 'android', 'Chrome' ], - [ 'pixel', 'ios', 'Safari' ] -] -``` +import { make, sorters, criteria, SuggestRowType, DictType } from "covertable"; -You can use also `makeAsync` function (generator). -- It receives the same arguments with `make` function. -- It returns the row at the time it's made. +const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; +const os = ["iOS", "Android"]; +const browser = ["FireFox", "Chrome", "Safari"]; -## Object input and output +const factors = {machine, os, browser}; -You can specify `factors` as object type: - -```typescript -import { default as make, sorters, criteria } from "covertable"; - -const machine = ['iphone', 'pixel']; -const os = ['ios', 'android']; -const browser = ['FireFox', 'Chrome', 'Safari']; - -make({machine, os, browser}, { // optional +make(factors, { // optional length: 2, - preFilter: (row: any) => !(row.os === 'android' && row.machine !== 'pixel'), // default: null - postFilter: (row: any) => !(row.os === 'ios' && row.browser !== 'Safari'), // default: null + // SuggestRowType is { machine: string, os: string, browser: string } + preFilter: (row: SuggestRowType) => !(row.os === 'Android' && row.machine !== 'Pixel'), // default: null + // Or DictType that is { [key: string]: string } + postFilter: (row: DictType) => !(row.os === 'iOS' && row.browser !== 'Safari'), // default: null }); ``` @@ -91,16 +77,29 @@ Then the output will change as follows: ```typescript [ // filtered - { machine: 'iphone', browser: 'Safari', os: 'ios' }, - { machine: 'pixel', browser: 'Chrome', os: 'android' }, - { machine: 'pixel', browser: 'Safari', os: 'ios' }, + { machine: 'Pixel', os: 'Android', browser: 'FireFox' }, + { machine: 'iPhone', os: 'iOS', browser: 'Safari' }, + { machine: 'Galaxy', browser: 'Safari', os: 'iOS' }, + { machine: 'Pixel', browser: 'Safari', os: 'iOS' }, + { machine: 'ZenFone', browser: 'Safari', os: 'iOS' }, + { machine: 'XPERIA', browser: 'Safari', os: 'iOS' } ] ``` -## Options -`covertable.make` function has options as `object` at 2nd argument. +You can use also `makeAsync` function (generator). +- It receives the same arguments with `make` function. +- It returns the row at the time it's made. -All options are omittable. +```js +import { makeAsync } from "covertable"; + +for await (const row of makeAsync([machine, os, browser])) { + console.log(row); +} +``` + +## Options +The `covertable.make` function accepts an options object as its second argument. Here are the available options: ### length Number of factors to be covered. (default: 2) @@ -108,9 +107,7 @@ Number of factors to be covered. (default: 2) Obviously the more it increases, the more number of combinations increases. ### sorter -Combinations depend on the order of spreading all over the rows. - -You can choice a sorter from the following: +Determines the order of combinations. - sorters.random: It makes different combinations everytime. (fastest) - sorters.hash: It makes combinations depending on hash of the pair and seed. (default) @@ -120,7 +117,7 @@ You can choice a sorter from the following: - When the combination of factors and seed are the same, covertable reproduces the same collective. ### criterion -You can choice a criterion from the following: +Determines the efficiency of combinations. - `criteria.simple`: it extracts any pairs that can be stored into the processing row. - `criteria.greedy`: it attempts to make most efficient combinations. (default) @@ -132,23 +129,69 @@ Although the latter is superior to former in terms of fewer combinations general Not relevant options will be ignored. ### preFilter -This is a function to filter beforehand. - -It receives an argument `row` as `object` type. +Function to filter combinations before they are registered. When the function returns `false`, the row combination will not be registered. - If factors type is `Array`, you should specify an index at the subscript like `row => row[1] < 6`. - If factors type is `Object`, you should specify a key at the subscript like `row => row.month < 6` or `row => row['month'] < 6` ### postFilter -This means a function to filter later. +Function to filter combinations after they are generated. The usage is the same as `preFilter`, only the difference is the timing of the call. It will delete rows not matched this function at the last. For this reason, the final test cases may not satisfy the factors coverage. -# Requirement +### PictConstraintsLexer + +Filter functions can also be generated using PictConstraintsLexer. Use as follows +This function is supported only in the typescript version. + +```js +import { make, PictConstraintsLexer } from "covertable"; + +const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; +const os = ["iOS", "Android"]; +const browser = ["FireFox", "Chrome", "Safari"]; + +const lexer = new PictConstraintsLexer( + ` + IF [machine] = "iPhone" THEN [os] = "iOS"; + IF [os] = "iOS" THEN [machine] = "iPhone"; + `, true +); + +make({machine, os, browser}, { // optional + preFilter: lexer.filter, +}); +``` + +```js +[ + { machine: 'ZenFone', browser: 'FireFox', os: 'Android' }, + { os: 'Android', browser: 'Safari', machine: 'Pixel' }, + { machine: 'Galaxy', browser: 'Chrome', os: 'Android' }, + { machine: 'XPERIA', os: 'Android', browser: 'FireFox' }, + { machine: 'Pixel', browser: 'Chrome', os: 'Android' }, + { os: 'iOS', browser: 'FireFox', machine: 'iPhone' }, + { machine: 'Pixel', browser: 'FireFox', os: 'Android' }, + { os: 'iOS', browser: 'Chrome', machine: 'iPhone' }, + { machine: 'Galaxy', browser: 'Safari', os: 'Android' }, + { machine: 'ZenFone', browser: 'Chrome', os: 'Android' }, + { os: 'iOS', browser: 'Safari', machine: 'iPhone' }, + { machine: 'Galaxy', browser: 'FireFox', os: 'Android' }, + { machine: 'XPERIA', browser: 'Chrome', os: 'Android' }, + { machine: 'ZenFone', browser: 'Safari', os: 'Android' }, + { machine: 'XPERIA', browser: 'Safari', os: 'Android' } +] +``` + +This feature acts as a conversion tool that enables the implementation of PICT constraint conditions within CoverTable, +allowing users to seamlessly apply complex constraints to their test data generation. + + +# Requirements ES2015 or later @@ -179,6 +222,6 @@ $ npm version patch $ npm publish ``` -# More info +# More information - [walkframe/covertable - GitHub](https://github.com/walkframe/covertable) diff --git a/typescript/src/__tests__/filter.test.ts b/typescript/src/__tests__/filter.test.ts index 7354042..d6ccad1 100644 --- a/typescript/src/__tests__/filter.test.ts +++ b/typescript/src/__tests__/filter.test.ts @@ -1,5 +1,4 @@ -import { Dict, SuggestRowType } from "../types"; -import { make, makeAsync, sorters, criteria } from "../index"; +import { make, DictType, SuggestRowType } from "../"; const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; const os = ["iOS", "Android"]; @@ -7,7 +6,7 @@ const browser = ["FireFox", "Chrome", "Safari"]; test('exclude impossible combinations', () => { const factors = {machine, os, browser}; - const preFilter = (row: Dict) => { + const preFilter = (row: DictType) => { return !( (row.machine === 'iPhone' && row.os !== 'iOS') || (row.machine !== 'iPhone' && row.os === 'iOS') @@ -49,14 +48,14 @@ test('Limited to iphone and iOS combinations only.', () => { test('Use a constant-false function for preFilter', () => { const factors = {machine, os, browser}; - const preFilter = (row: Dict) => false; + const preFilter = (row: DictType) => false; const rows = make(factors, { preFilter }); expect(rows).toEqual([]); }); test('Use the wrong conditional function for preFilter', () => { const factors = {machine, os, browser}; - const preFilter = (row: Dict) => row.machine === 'WindowsPhone'; + const preFilter = (row: DictType) => row.machine === 'WindowsPhone'; const rows = make(factors, { preFilter }); expect(rows).toEqual([]); }); diff --git a/typescript/src/__tests__/index.test.ts b/typescript/src/__tests__/index.test.ts index 904ab6f..db68b71 100644 --- a/typescript/src/__tests__/index.test.ts +++ b/typescript/src/__tests__/index.test.ts @@ -1,6 +1,6 @@ import { default as make, sorters, criteria } from '../index'; import { product, combinations, range, len, all, getItems } from '../lib'; -import { FactorsType, Scalar, Dict, PairType } from '../types'; +import { FactorsType, ScalarType, DictType, PairType } from '../types'; const getPairs = function* (factors: FactorsType, length = 2) { const allKeys = getItems(factors).map(([k, _]) => k); @@ -69,7 +69,7 @@ test('prefilter excludes specified pairs before', () => { ["d", "e"], ["f"], ]; - const preFilter = (row: Dict) => { + const preFilter = (row: DictType) => { if (row[0] === "a" && row[1] === "d") { return false; } @@ -151,7 +151,7 @@ test('dict type factors make dict row', () => { 'key5': ["m", "n", "o"], }; const rows = make(factors); - const sorter = (a: Scalar, b: Scalar) => a > b ? 1 : -1; + const sorter = (a: ScalarType, b: ScalarType) => a > b ? 1 : -1; for (let row of rows) { const keys1 = Object.keys(row).sort(sorter); const keys2 = Object.keys(factors).sort(sorter); diff --git a/typescript/src/controller.ts b/typescript/src/controller.ts index dc7c071..03820e8 100644 --- a/typescript/src/controller.ts +++ b/typescript/src/controller.ts @@ -17,9 +17,9 @@ import { IndicesType, FactorsType, SerialsType, - Scalar, - Dict, - PairByKey, + ScalarType, + DictType, + PairByKeyType, ParentsType, CandidateType, RowType, @@ -29,9 +29,9 @@ import { } from "./types"; import { NeverMatch, NotReady } from "./exceptions"; -export class Row extends Map implements RowType { +export class Row extends Map implements RowType { // index: number - public consumed: PairByKey = new Map(); + public consumed: PairByKeyType = new Map(); constructor(row: CandidateType) { super(); @@ -57,9 +57,9 @@ export class Controller { private serials: SerialsType = new Map(); private parents: ParentsType = new Map(); private indices: IndicesType = new Map(); - public incomplete: PairByKey = new Map(); + public incomplete: PairByKeyType = new Map(); - private rejected: Set = new Set(); + private rejected: Set = new Set(); public row: Row; constructor(public factors: FactorsType, public options: OptionsType) { @@ -169,8 +169,8 @@ export class Controller { return row.size === this.factorLength; } - toMap(row: Row): Map { - const result: Map = new Map(); + toMap(row: Row): Map { + const result: Map = new Map(); for (let [key, serial] of row.entries()) { const index = this.indices.get(serial) as number; const first = this.indices.get((this.serials.get(key) as PairType)[0]); @@ -181,7 +181,7 @@ export class Controller { } toProxy(row: Row) { - const obj: Dict = {}; + const obj: DictType = {}; for (let [key, value] of this.toMap(row).entries()) { obj[key] = value; } @@ -189,7 +189,7 @@ export class Controller { } toObject(row: Row) { - const obj: Dict = {}; + const obj: DictType = {}; for (let [key, value] of this.toMap(row).entries()) { obj[key] = value; } diff --git a/typescript/src/criteria/greedy.ts b/typescript/src/criteria/greedy.ts index b5529c0..512b6de 100644 --- a/typescript/src/criteria/greedy.ts +++ b/typescript/src/criteria/greedy.ts @@ -1,8 +1,8 @@ -import type {FactorsType, PairByKey, PairType} from '../types'; +import type {FactorsType, PairByKeyType, PairType} from '../types'; import { combinations, unique } from '../lib'; import { Controller } from '../controller'; -const getNumRemovablePairs = (indexes: Set, incomplete: PairByKey, length: number) => { +const getNumRemovablePairs = (indexes: Set, incomplete: PairByKeyType, length: number) => { let num = 0; const removingKeys = combinations([... indexes], length); for (let pair of removingKeys) { diff --git a/typescript/src/exceptions.ts b/typescript/src/exceptions.ts index 9450bac..677f9fe 100644 --- a/typescript/src/exceptions.ts +++ b/typescript/src/exceptions.ts @@ -1,7 +1,7 @@ -import { Scalar } from "./types"; +import { ScalarType } from "./types"; export class NotReady extends Error { - constructor(public key: Scalar) { + constructor(public key: ScalarType) { super(`Not yet '${key}' in the object`); } } diff --git a/typescript/src/index.ts b/typescript/src/index.ts index f3be2af..9a78f72 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -6,7 +6,7 @@ import greedy from "./criteria/greedy"; import simple from "./criteria/simple"; import {PictConstraintsLexer} from "./utils/pict"; -import { FactorsType, OptionsType, SuggestRowType } from "./types"; +import { FactorsType, OptionsType, SuggestRowType, DictType, ListType } from "./types"; import { Controller } from "./controller"; import { NeverMatch } from "./exceptions"; @@ -60,4 +60,11 @@ export { PictConstraintsLexer, }; +export type { + OptionsType, + SuggestRowType, + DictType, + ListType, +} + export default make; diff --git a/typescript/src/lib.ts b/typescript/src/lib.ts index cd9d0cc..90e454b 100644 --- a/typescript/src/lib.ts +++ b/typescript/src/lib.ts @@ -2,8 +2,8 @@ export { hex as md5 } from 'js-md5'; import { NotReady } from './exceptions'; import type { - FactorsType, Scalar, ParentsType, CandidateType, PairType, - Dict, + FactorsType, ScalarType, ParentsType, CandidateType, PairType, + DictType, } from './types'; // https://gist.github.com/righ/71e32be8e33f74bde516c06f80c941e8 @@ -79,7 +79,7 @@ export const len = (obj: any[] | object): number => { return Object.keys(obj).length; } -export const getItems = (container: FactorsType | Map): [Scalar, any[]][] => { +export const getItems = (container: FactorsType | Map): [ScalarType, any[]][] => { if (Array.isArray(container)) { return container.map((v, i) => [i, v]); } @@ -90,13 +90,13 @@ export const getItems = (container: FactorsType | Map): [Scalar, } export const getCandidate = (pair: number[], parents: ParentsType): CandidateType => { - const keys: Scalar[] = pair.map(p => parents.get(p) || 0); + const keys: ScalarType[] = pair.map(p => parents.get(p) || 0); return zip(keys, pair); } export const ascOrder = (a: number, b: number) => a > b ? 1 : -1; -export const unique = (pair: PairType): Scalar => { +export const unique = (pair: PairType): ScalarType => { const total = pair.reduce((a, b) => a * b); if (Number.isSafeInteger(total)) { return total; @@ -131,7 +131,7 @@ export function* primeGenerator(): Generator { export const proxyHandler = { - get(obj: Dict, key: string, receiver: any) { + get(obj: DictType, key: string, receiver: any) { if (key in obj) { return obj[key]; } diff --git a/typescript/src/types.ts b/typescript/src/types.ts index c5058b6..e48be1d 100644 --- a/typescript/src/types.ts +++ b/typescript/src/types.ts @@ -1,11 +1,11 @@ import type { Controller } from "./controller"; -export type Scalar = number | string; -export type Dict = { [s: string]: any }; -export type List = { [index: number]: any[] }; +export type ScalarType = number | string; +export type DictType = { [s: string]: any }; +export type ListType = { [index: number]: any[] }; -export type SerialsType = Map; -export type ParentsType = Map; +export type SerialsType = Map; +export type ParentsType = Map; export type IndicesType = Map; export type FilterRowType = { @@ -13,13 +13,13 @@ export type FilterRowType = { [index: number]: any; } -export type ArrayTuple = any[][]; -export type ArrayObject = { [s: string]: any[] }; -export type FactorsType = ArrayTuple | ArrayObject; +export type ArrayTupleType = any[][]; +export type ArrayObjectType = { [s: string]: any[] }; +export type FactorsType = ArrayTupleType | ArrayObjectType; -export type SuggestRowType = T extends ArrayTuple +export type SuggestRowType = T extends ArrayTupleType ? T[number][number][] - : T extends ArrayObject ? { [K in keyof T]: T[K][number] } + : T extends ArrayObjectType ? { [K in keyof T]: T[K][number] } : unknown; export type FilterType = (row: FilterRowType) => boolean; @@ -27,12 +27,12 @@ export type SuggestFilterType = (row: SuggestRowType) export type PairType = number[]; -export type PairByKey = Map; +export type PairByKeyType = Map; -export type CandidateType = [Scalar, number][]; +export type CandidateType = [ScalarType, number][]; export interface RowType { - consumed: PairByKey; + consumed: PairByKeyType; }; export type SorterType = ( @@ -41,7 +41,7 @@ export type SorterType = ( ) => PairType[]; export interface SortArgsType { - seed: Scalar; + seed: ScalarType; indices: IndicesType; }; @@ -56,7 +56,7 @@ export interface OptionsType { length?: number; sorter?: SorterType; criterion?: (ctrl: Controller) => IterableIterator; - seed?: Scalar; + seed?: ScalarType; tolerance?: number; preFilter?: FilterType | SuggestFilterType; postFilter?: FilterType | SuggestFilterType; From 1151c43805856d3345dab902181fd42cad6b462e Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 05:40:29 +0900 Subject: [PATCH 43/55] 2.4.0-alpha.2 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index f249b62..11269c4 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.4.0-alpha.1", + "version": "2.4.0-alpha.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.4.0-alpha.1", + "version": "2.4.0-alpha.2", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 1d2f574..696de66 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.4.0-alpha.1", + "version": "2.4.0-alpha.2", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From 9bdb036725caf62171973de0982cb5786ec2eb00 Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 05:58:55 +0900 Subject: [PATCH 44/55] update --- typescript/README.md | 10 +++++----- typescript/src/__tests__/pict.test.ts | 10 +++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/typescript/README.md b/typescript/README.md index 87dce4a..f6da668 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -68,7 +68,7 @@ make(factors, { // optional length: 2, // SuggestRowType is { machine: string, os: string, browser: string } preFilter: (row: SuggestRowType) => !(row.os === 'Android' && row.machine !== 'Pixel'), // default: null - // Or DictType that is { [key: string]: string } + // Or DictType that is { [key: string]: any } postFilter: (row: DictType) => !(row.os === 'iOS' && row.browser !== 'Safari'), // default: null }); ``` @@ -109,8 +109,8 @@ Obviously the more it increases, the more number of combinations increases. ### sorter Determines the order of combinations. -- sorters.random: It makes different combinations everytime. (fastest) -- sorters.hash: It makes combinations depending on hash of the pair and seed. (default) +- sorters.random: Generates different combinations each time. (fastest) +- sorters.hash: Uses a hash-based method for reproducibility. (default) - It receives `seed`. - `seed` option decides the order of storing from unstored pairs. @@ -119,8 +119,8 @@ Determines the order of combinations. ### criterion Determines the efficiency of combinations. -- `criteria.simple`: it extracts any pairs that can be stored into the processing row. -- `criteria.greedy`: it attempts to make most efficient combinations. (default) +- `criteria.simple`: Quickly generates combinations. +- `criteria.greedy`: Attempts to minimize the number of combinations, but is more time-intensive. (default) - It receives [tolerance](https://github.com/walkframe/covertable#tolerance) option. While `criteria.simple` processes quickly, `criteria.greedy` makes fewer combinations. diff --git a/typescript/src/__tests__/pict.test.ts b/typescript/src/__tests__/pict.test.ts index 5e8c279..ad75558 100644 --- a/typescript/src/__tests__/pict.test.ts +++ b/typescript/src/__tests__/pict.test.ts @@ -1,6 +1,15 @@ import { PictConstraintsLexer } from "../utils/pict"; describe('PictConstraintsLexer with single constraints', () => { + it('Blank', () => { + const lexer = new PictConstraintsLexer(``, true); + expect(lexer.filters.length).toBe(0); + expect(lexer.errors.length).toBe(0); + + const row1 = { PRICE: 150, DISCOUNT: 'YES' }; + expect(lexer.filter(row1)).toBe(true); + }); + it('should filter correctly with LIKE and IN conditions', () => { const lexer = new PictConstraintsLexer(` IF [NAME] LIKE "Alic?" THEN [STATUS] IN {"Active", "Pending"} ELSE [AGE] > 20 OR [COUNTRY] = "USA"; @@ -355,7 +364,6 @@ describe('PictConstraintsLexer with invalid constraints', () => { expect(lexer.errors.length).toBe(1); expect(lexer.errors[0]).toBe('The leading "IF" is missing, found [NAME]'); }); - it('Multiple invalid expressions', () => { const lexer = new PictConstraintsLexer(` From c0d0684230ec00255ccfb25b620d271e157664a8 Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 05:59:47 +0900 Subject: [PATCH 45/55] 2.4.0 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 11269c4..ae7f173 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.4.0-alpha.2", + "version": "2.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.4.0-alpha.2", + "version": "2.4.0", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 696de66..b948fbb 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.4.0-alpha.2", + "version": "2.4.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://github.com/walkframe/covertable", "repository": { From ababb7f57dd4713a09432b536fdef0830c5793a1 Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 19:56:41 +0900 Subject: [PATCH 46/55] update README --- README.md | 75 ++++++++++++++++ README.rst | 203 ------------------------------------------ python/history.md | 22 +++++ typescript/history.md | 38 ++++++++ 4 files changed, 135 insertions(+), 203 deletions(-) create mode 100644 README.md delete mode 100644 README.rst create mode 100644 python/history.md create mode 100644 typescript/history.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..89a2102 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Covertable + +![covertable logo](./covertable.png) + +Time is limited. + +Creating a test case that satisfies all possible factors is often unrealistic and, more importantly, tedious. + +Save time with Covertable, a flexible pairwise tool that generates combinations covering two (or more) factors. + +## Implementations + +Covertable is available in two implementations, with TypeScript as the primary focus and Python offered as a secondary option. + +### TypeScript + +[![NPM Version](https://badge.fury.io/js/covertable.svg)](https://badge.fury.io/js/covertable) [![Build Status](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) + +- [README](https://github.com/walkframe/covertable/blob/master/typescript) +- [History](https://github.com/walkframe/covertable/blob/master/typescript/history.md) + +### Python (Legacy Support) + +[![PyPI Version](https://badge.fury.io/py/covertable.svg)](https://badge.fury.io/py/covertable) [![Build Status](https://github.com/walkframe/covertable/actions/workflows/python.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/python.yaml) + +- [README](https://github.com/walkframe/covertable/blob/master/python/README.rst) +- [History](https://github.com/walkframe/covertable/blob/master/python/history.md) + + +For more details, please refer to the links above. + +## Performance + +> **Note:** +> The following data was measured in Python 3.7.7 on a `3.1 GHz 6-Core Intel Core i5`. +> The coverage number is `2`. + +| Combination | Default | Minimum case | Fastest case | +|-------------------|-------------------------------------|---------------------------------------|------------------------------------| +| **3^4** | num: `9`
time: `0.0006s` | num: `9`
time: `0.0006s` | num: `14`
time: `0.0005s` | +| **3^13** | num: `19`
time: `0.03s` | num: `17`
time: `0.03s` | num: `21`
time: `0.003s` | +| **4^15 + 3^17 + 2^29** | num: `36`
time: `7.41s` | num: `34`
time: `7.47s` | num: `42`
time: `0.40s` | +| **4^1 + 3^39 + 2^35** | num: `27`
time: `15.19s` | num: `26`
time: `14.70s` | num: `30`
time: `0.51s` | +| **2^100** | num: `14`
time: `23.97s` | num: `12`
time: `0.63s` | num: `13`
time: `0.48s` | +| **10^20** | num: `198`
time: `14.28s` | num: `195`
time: `14.48s` | num: `284`
time: `0.53s` | + +In general, as the number of elements or coverage increases, the number of combinations tends to increase significantly. + +## Tolerance + +If you use the `greedy` criterion and specify a positive integer for the `tolerance` option, you can increase speed at the expense of the number of combinations. + +The greater the `tolerance`, the faster the speed and the larger the number of combinations. + +### Example: 10^20 Test Cases + +| Tolerance | num | time | +|-----------|------|--------| +| 0 (default) | `195` | `14.48s` | +| 1 | `199` | `12.45s` | +| 2 | `201` | `9.48s` | +| 3 | `201` | `7.17s` | +| 4 | `207` | `5.70s` | +| 5 | `212` | `4.58s` | +| 6 | `212` | `3.65s` | +| 7 | `216` | `3.07s` | +| 8 | `223` | `2.57s` | +| 9 | `226` | `2.14s` | +| 10 | `233` | `1.84s` | +| 11 | `237` | `1.61s` | +| 12 | `243` | `1.43s` | +| 13 | `249` | `1.28s` | +| 14 | `254` | `1.19s` | + + diff --git a/README.rst b/README.rst deleted file mode 100644 index fa58202..0000000 --- a/README.rst +++ /dev/null @@ -1,203 +0,0 @@ -.. image:: ./covertable.png - :alt: covertable logo - -Time is limited. - -It is not realistic to create a test case that satisfies all the multiple factors, -and above all, it is tedious. - -Save time with covertable. It is a flexible pairwise tool to create a two (or more) factor covered combination. - - -Now it has 2 implementations. - -:Python: - - - .. image:: https://badge.fury.io/py/covertable.svg - :target: https://badge.fury.io/py/covertable - - .. image:: https://github.com/walkframe/covertable/actions/workflows/python.yaml/badge.svg - :target: https://github.com/walkframe/covertable/actions/workflows/python.yaml - - `README `__ - - `Code `__ - - -:TypeScript: - - - .. image:: https://badge.fury.io/js/covertable.svg - :target: https://badge.fury.io/js/covertable - - .. image:: https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg - :target: https://github.com/walkframe/covertable/actions/workflows/typescript.yaml - - `README `__ - - `Code `__ - - -Go see the detail from these links. - -Performance -=================== - -.. note:: - - - The following data was measured in Python 3.7.7 and ``3.1 GHz 6 Cores Intel Core i5``. - - coverage number is `2`. - -.. list-table:: Number and time of combinations. - :widths: 1 3 3 3 - :header-rows: 1 - :stub-columns: 1 - - * - Combination - - Default - - Minimum case - - Fastest case - * - 3^4 - - - num: ``9`` - - cond: *default* - - time: ``0.0006s`` - - - num: ``9`` - - cond: *default* - - time: ``0.0006s`` - - - num: ``14`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.0005s`` - * - 3^13 - - - num: ``19`` - - cond: *default* - - time: ``0.03s`` - - - num: ``17`` - - cond: ``seed: 1084`` - - time: ``0.03s`` - - - num: ``21`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.003s`` - * - 4^15 + 3^17 + 2^29 - - - num: ``36`` - - cond: *default* - - time: ``7.41s`` - - - num: ``34`` - - cond: ``seed: 19`` - - time: ``7.47s`` - - - num: ``42`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.40s`` - * - 4^1 + 3^39 + 2^35 - - - num: ``27`` - - cond: *default* - - time: ``15.19s`` - - - num: ``26`` - - cond: ``seed: 14`` - - time: ``14.70s`` - - - num: ``30`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.51s`` - * - 2^100 - - - num: ``14`` - - cond: *default* - - time: ``23.97s`` - - - num: ``12`` - - cond: ``seed: 6, criterion: simple`` - - time: ``0.63s`` - - - num: ``13`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.48s`` - * - 10^20 - - - num: ``198`` - - cond: *default* - - time: ``14.28s`` - - - num: ``195`` - - cond: ``seed: 1139`` - - time: ``14.48s`` - - - num: ``284`` - - cond: ``sorter: random, criterion: simple`` - - time: ``0.53s`` - -In general, as the number of elements or coverage increases, -the number of combinations have a tendency to increase significantly. - -Tolerance ----------------- - -If you use `greedy` criterion and specify a positive integer to `tolerance` option, -it can increase the speed at the expense of the number of combinations. - -The greater the `tolerance`, the shorter the speed and bigger the number of combinations. - -.. list-table:: Table for the case when combinations are created from ``10^20`` test cases. - :widths: 1 3 3 - :header-rows: 1 - :stub-columns: 1 - - * - tolerance - - num - - time - * - 0 (default) - - ``195`` - - ``14.48s`` - * - 1 - - ``199`` - - ``12.45s`` - * - 2 - - ``201`` - - ``9.48s`` - * - 3 - - ``201`` - - ``7.17s`` - * - 4 - - ``207`` - - ``5.70s`` - * - 5 - - ``212`` - - ``4.58s`` - * - 6 - - ``212`` - - ``3.65s`` - * - 7 - - ``216`` - - ``3.07s`` - * - 8 - - ``223`` - - ``2.57s`` - * - 9 - - ``226`` - - ``2.14s`` - * - 10 - - ``233`` - - ``1.84s`` - * - 11 - - ``237`` - - ``1.61s`` - * - 12 - - ``243`` - - ``1.43s`` - * - 13 - - ``249`` - - ``1.28s`` - * - 14 - - ``254`` - - ``1.19s`` - - -History -======= -:2.0.x: - - - sorter option was splitted into sorter and criterion. - - - e.g. greedy -> hash sorter + greedy criterion. - - - `greedy` method is much faster than before. - - `greedy` method got an option `tolerance` to balance speed and results. - - - sequenctial sorter was dropped. - - - Because The number of combinations would be huge in TypeScript. - -:1.1.x: - - - Greedy sorter improved in both implementations. - - - It got increased in speed. - -:1.0.x: - - - First release 🎉 diff --git a/python/history.md b/python/history.md new file mode 100644 index 0000000..004b330 --- /dev/null +++ b/python/history.md @@ -0,0 +1,22 @@ +# History + +## 2.1.x +- Add `make_async` function to generate combinations sequentially. + +## 2.0.x + +- The `sorter` option was split into `sorter` and `criterion`. + - e.g., greedy -> hash sorter + greedy criterion. +- The `greedy` method is much faster than before. +- The `greedy` method now includes a `tolerance` option to balance speed and results. +- The sequential sorter was dropped. + - Due to the potential for huge numbers of combinations in TypeScript. + +## 1.1.x + +- The greedy sorter was improved in both implementations. + - Speed has been increased. + +## 1.0.x + +- First release 🎉 diff --git a/typescript/history.md b/typescript/history.md new file mode 100644 index 0000000..810b3a8 --- /dev/null +++ b/typescript/history.md @@ -0,0 +1,38 @@ +# History + +## 2.4.x +- Fixed an issue where preFilter was evaluating and excluding incomplete elements. This is a minor upgrade due to the large scope of the impact. +- Type names are now unified with the Type suffix. + +## 2.3.x +- PictConstraintsLexer was added. ([#37](https://github.com/walkframe/covertable/pull/37)) + - It is a lexer designed to parse PICT constraints. + - It parses constraints written in the PICT format, enabling the evaluation of complex conditions. + - The parsed constraints are then used in the make function to dynamically filter the generated combinations based on the specified rules. + +## 2.2.x +- Speed is increased by expressing combinations of elements as a product of prime numbers. +- Added `SuggestRowType` to infer the row type. + +## 2.1.x +- Speed up processing speed by pre-sorting target pairs. +- Added `makeAsync` function to generate combinations sequentially. + + +## 2.0.x + +- The `sorter` option was split into `sorter` and `criterion`. + - e.g., greedy -> hash sorter + greedy criterion. +- The `greedy` method is much faster than before. +- The `greedy` method now includes a `tolerance` option to balance speed and results. +- The sequential sorter was dropped. + - Due to the potential for huge numbers of combinations in TypeScript. + +## 1.1.x + +- The greedy sorter was improved in both implementations. + - Speed has been increased. + +## 1.0.x + +- First release 🎉 From 89b1b7e69abc26ea6760f6d45420861c70b38bfa Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 20:01:06 +0900 Subject: [PATCH 47/55] update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 89a2102..9b28e68 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Covertable +# CoverTable ![covertable logo](./covertable.png) @@ -6,11 +6,11 @@ Time is limited. Creating a test case that satisfies all possible factors is often unrealistic and, more importantly, tedious. -Save time with Covertable, a flexible pairwise tool that generates combinations covering two (or more) factors. +Save time with CoverTable, a flexible pairwise tool that generates combinations covering two (or more) factors. ## Implementations -Covertable is available in two implementations, with TypeScript as the primary focus and Python offered as a secondary option. +CoverTable is available in two implementations, with TypeScript as the primary focus and Python offered as a secondary option. ### TypeScript From 3dca4236d55c6a99bc46d4c4198c2c6c11547e96 Mon Sep 17 00:00:00 2001 From: righ Date: Thu, 29 Aug 2024 20:05:06 +0900 Subject: [PATCH 48/55] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b28e68..0d6fdfc 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ CoverTable is available in two implementations, with TypeScript as the primary f [![NPM Version](https://badge.fury.io/js/covertable.svg)](https://badge.fury.io/js/covertable) [![Build Status](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) -- [README](https://github.com/walkframe/covertable/blob/master/typescript) +- [README](https://github.com/walkframe/covertable/blob/master/typescript/README.md) - [History](https://github.com/walkframe/covertable/blob/master/typescript/history.md) ### Python (Legacy Support) From 3288393517f160102f3c598d423a0b7bb9185a5d Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 1 Sep 2024 05:17:39 +0900 Subject: [PATCH 49/55] update link --- typescript/README.md | 203 ++-------------------------------------- typescript/package.json | 2 +- 2 files changed, 9 insertions(+), 196 deletions(-) diff --git a/typescript/README.md b/typescript/README.md index f6da668..134dd77 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -1,31 +1,20 @@ [![npm version](https://badge.fury.io/js/covertable.svg)](https://badge.fury.io/js/covertable) [![Workflow](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml/badge.svg)](https://github.com/walkframe/covertable/actions/workflows/typescript.yaml) [![codecov](https://codecov.io/gh/walkframe/covertable/branch/master/graph/badge.svg)](https://codecov.io/gh/walkframe/covertable) +[![github](https://img.shields.io/github/stars/walkframe/covertable)](https://github.com/walkframe/covertable) # What is covertable? covertable is a powerful tool for generating pairwise combinations of input factors, designed for both Node.js and browser environments. It's easy to use, flexible, and supports advanced filtering options, making it perfect for testing scenarios and generating comprehensive datasets. -# Installation - -```sh -$ npm install covertable --save -``` - -# Usage - -## Simple usage in Node.js: +# Simple usage ```javascript -var covertable = require('covertable'); -var make = covertable.make; - -var machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; -var os = ["iOS", "Android"]; -var browser = ["FireFox", "Chrome", "Safari"]; - +import { make } from "covertable"; +const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; +const os = ["iOS", "Android"]; +const browser = ["FireFox", "Chrome", "Safari"]; make([machine, os, browser]); ``` -Output: ```javascript [ @@ -47,181 +36,5 @@ Output: ] ``` -Of course, it also works in the browser well. - -## Advanced usage in TypeScript: - -As previously mentioned, when elements are specified as an array, the results will also be in array form. However, if the elements are specified as an object, the results will be in object form. - -The following example uses preFilter and postFilter to apply constraints to the output results. In this case, `SuggestRowType` can also be used to infer the type of row parameters that the filter function receives. - -```typescript -import { make, sorters, criteria, SuggestRowType, DictType } from "covertable"; - -const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; -const os = ["iOS", "Android"]; -const browser = ["FireFox", "Chrome", "Safari"]; - -const factors = {machine, os, browser}; - -make(factors, { // optional - length: 2, - // SuggestRowType is { machine: string, os: string, browser: string } - preFilter: (row: SuggestRowType) => !(row.os === 'Android' && row.machine !== 'Pixel'), // default: null - // Or DictType that is { [key: string]: any } - postFilter: (row: DictType) => !(row.os === 'iOS' && row.browser !== 'Safari'), // default: null -}); -``` - -Then the output will change as follows: - -```typescript -[ // filtered - { machine: 'Pixel', os: 'Android', browser: 'FireFox' }, - { machine: 'iPhone', os: 'iOS', browser: 'Safari' }, - { machine: 'Galaxy', browser: 'Safari', os: 'iOS' }, - { machine: 'Pixel', browser: 'Safari', os: 'iOS' }, - { machine: 'ZenFone', browser: 'Safari', os: 'iOS' }, - { machine: 'XPERIA', browser: 'Safari', os: 'iOS' } -] -``` - -You can use also `makeAsync` function (generator). -- It receives the same arguments with `make` function. -- It returns the row at the time it's made. - -```js -import { makeAsync } from "covertable"; - -for await (const row of makeAsync([machine, os, browser])) { - console.log(row); -} -``` - -## Options -The `covertable.make` function accepts an options object as its second argument. Here are the available options: - -### length -Number of factors to be covered. (default: 2) - -Obviously the more it increases, the more number of combinations increases. - -### sorter -Determines the order of combinations. - -- sorters.random: Generates different combinations each time. (fastest) -- sorters.hash: Uses a hash-based method for reproducibility. (default) - - - It receives `seed`. - - `seed` option decides the order of storing from unstored pairs. - - When the combination of factors and seed are the same, covertable reproduces the same collective. - -### criterion -Determines the efficiency of combinations. - -- `criteria.simple`: Quickly generates combinations. -- `criteria.greedy`: Attempts to minimize the number of combinations, but is more time-intensive. (default) - - It receives [tolerance](https://github.com/walkframe/covertable#tolerance) option. - -While `criteria.simple` processes quickly, `criteria.greedy` makes fewer combinations. -Although the latter is superior to former in terms of fewer combinations generally, it is time-intensive process. - -Not relevant options will be ignored. - -### preFilter -Function to filter combinations before they are registered. - -When the function returns `false`, the row combination will not be registered. -- If factors type is `Array`, you should specify an index at the subscript like `row => row[1] < 6`. -- If factors type is `Object`, you should specify a key at the subscript like `row => row.month < 6` or `row => row['month'] < 6` - -### postFilter -Function to filter combinations after they are generated. - -The usage is the same as `preFilter`, only the difference is the timing of the call. -It will delete rows not matched this function at the last. - -For this reason, the final test cases may not satisfy the factors coverage. - -### PictConstraintsLexer - -Filter functions can also be generated using PictConstraintsLexer. Use as follows -This function is supported only in the typescript version. - -```js -import { make, PictConstraintsLexer } from "covertable"; - -const machine = ["iPhone", "Pixel", "XPERIA", "ZenFone", "Galaxy"]; -const os = ["iOS", "Android"]; -const browser = ["FireFox", "Chrome", "Safari"]; - -const lexer = new PictConstraintsLexer( - ` - IF [machine] = "iPhone" THEN [os] = "iOS"; - IF [os] = "iOS" THEN [machine] = "iPhone"; - `, true -); - -make({machine, os, browser}, { // optional - preFilter: lexer.filter, -}); -``` - -```js -[ - { machine: 'ZenFone', browser: 'FireFox', os: 'Android' }, - { os: 'Android', browser: 'Safari', machine: 'Pixel' }, - { machine: 'Galaxy', browser: 'Chrome', os: 'Android' }, - { machine: 'XPERIA', os: 'Android', browser: 'FireFox' }, - { machine: 'Pixel', browser: 'Chrome', os: 'Android' }, - { os: 'iOS', browser: 'FireFox', machine: 'iPhone' }, - { machine: 'Pixel', browser: 'FireFox', os: 'Android' }, - { os: 'iOS', browser: 'Chrome', machine: 'iPhone' }, - { machine: 'Galaxy', browser: 'Safari', os: 'Android' }, - { machine: 'ZenFone', browser: 'Chrome', os: 'Android' }, - { os: 'iOS', browser: 'Safari', machine: 'iPhone' }, - { machine: 'Galaxy', browser: 'FireFox', os: 'Android' }, - { machine: 'XPERIA', browser: 'Chrome', os: 'Android' }, - { machine: 'ZenFone', browser: 'Safari', os: 'Android' }, - { machine: 'XPERIA', browser: 'Safari', os: 'Android' } -] -``` - -This feature acts as a conversion tool that enables the implementation of PICT constraint conditions within CoverTable, -allowing users to seamlessly apply complex constraints to their test data generation. - - -# Requirements - -ES2015 or later - -- [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators) -- [for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) -- [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) -- [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) -- [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) -- [Object.entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) - -# Development - -```sh -$ npm install -``` - -## Testing -```sh -$ npm test -- --coverage -``` - -## Publish - -```sh -$ # npm adduser -$ npm run build -$ npm version patch -$ npm publish -``` - -# More information - -- [walkframe/covertable - GitHub](https://github.com/walkframe/covertable) +# Advanced usage +Advanced usage is [here](https://docs.walkframe.com/covertable/advanced) \ No newline at end of file diff --git a/typescript/package.json b/typescript/package.json index b948fbb..c96254e 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -2,7 +2,7 @@ "name": "covertable", "version": "2.4.0", "description": "A flexible pairwise tool written in TypeScript", - "homepage": "https://github.com/walkframe/covertable", + "homepage": "https://docs.walkframe.com/covertable", "repository": { "type": "git", "url": "git+https://github.com/walkframe/covertable.git" From 6b06f52003b3045cbd0b3c4220554b495247eb6a Mon Sep 17 00:00:00 2001 From: righ Date: Sun, 1 Sep 2024 05:20:27 +0900 Subject: [PATCH 50/55] 2.4.1 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index ae7f173..294c1ca 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.4.0", + "version": "2.4.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.4.0", + "version": "2.4.1", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index c96254e..2ad6e2e 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.4.0", + "version": "2.4.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://docs.walkframe.com/covertable", "repository": { From 636eae7d0cdafa218a868ff1319aa68d1a2810c6 Mon Sep 17 00:00:00 2001 From: righ Date: Mon, 17 Mar 2025 22:03:17 +0900 Subject: [PATCH 51/55] feat: Controller and progress --- typescript/src/controller.ts | 61 +++++++++++++++++++++++++++--------- typescript/src/index.ts | 41 +++++------------------- 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/typescript/src/controller.ts b/typescript/src/controller.ts index 03820e8..0bf4b0f 100644 --- a/typescript/src/controller.ts +++ b/typescript/src/controller.ts @@ -1,4 +1,4 @@ - +import greedy from "./criteria/greedy"; import hash from "./sorters/hash"; import { range, @@ -58,13 +58,15 @@ export class Controller { private parents: ParentsType = new Map(); private indices: IndicesType = new Map(); public incomplete: PairByKeyType = new Map(); + private numAllChunks: number = 0; private rejected: Set = new Set(); public row: Row; - constructor(public factors: FactorsType, public options: OptionsType) { + constructor(public factors: FactorsType, public options: OptionsType = {}) { this.serialize(factors); this.setIncomplete(); + this.numAllChunks = this.incomplete.size; this.row = new Row([]); this.factorLength = len(factors); this.factorIsArray = factors instanceof Array; @@ -112,7 +114,7 @@ export class Controller { } } - setPair(pair: PairType) { + private setPair(pair: PairType) { for (let [key, value] of this.getCandidate(pair)) { this.row.set(key, value); } @@ -122,7 +124,7 @@ export class Controller { } } - consume(pair: PairType) { + public consume(pair: PairType) { const pairKey = unique(pair); const deleted = this.incomplete.delete(pairKey); if (deleted) { @@ -130,12 +132,12 @@ export class Controller { } } - getCandidate(pair: PairType) { + public getCandidate(pair: PairType) { return getCandidate(pair, this.parents); } // Returns a negative value if it is unknown if it can be stored. - storable(candidate: CandidateType) { + public storable(candidate: CandidateType) { let num = 0; for (let [key, el] of candidate) { let existing: number | undefined = this.row.get(key); @@ -165,11 +167,11 @@ export class Controller { return num; } - isFilled(row: Row): boolean { + public isFilled(row: Row): boolean { return row.size === this.factorLength; } - toMap(row: Row): Map { + private toMap(row: Row): Map { const result: Map = new Map(); for (let [key, serial] of row.entries()) { const index = this.indices.get(serial) as number; @@ -180,7 +182,7 @@ export class Controller { return result; } - toProxy(row: Row) { + private toProxy(row: Row) { const obj: DictType = {}; for (let [key, value] of this.toMap(row).entries()) { obj[key] = value; @@ -188,7 +190,7 @@ export class Controller { return new Proxy(obj, proxyHandler) as SuggestRowType; } - toObject(row: Row) { + private toObject(row: Row) { const obj: DictType = {}; for (let [key, value] of this.toMap(row).entries()) { obj[key] = value; @@ -196,19 +198,19 @@ export class Controller { return obj as SuggestRowType; } - reset() { + private reset() { this.row.consumed.forEach((pair, pairKey) => { this.incomplete.set(pairKey, pair); }); this.row = new Row([]); } - discard() { + private discard() { this.rejected.add(this.row.getPairKey()); this.row = new Row([]); } - restore() { + private restore() { const row = this.row; this.row = new Row([]); if (this.factorIsArray) { @@ -220,7 +222,7 @@ export class Controller { return this.toObject(row); } - close() { + private close() { const trier = new Row([...this.row.entries()]); const kvs = getItems(this.serials); for (let [k, vs] of kvs) { @@ -274,4 +276,35 @@ export class Controller { throw e; } } + + get progress() { + return 1 - this.incomplete.size / this.numAllChunks; + } + + public *makeAsync(): Generator, void, unknown> { + const {criterion = greedy, postFilter} = this.options; + do { + for (let pair of criterion(this)) { + if (this.isFilled(this.row)) { + break; + } + this.setPair(pair); + } + try { + const complete = this.close(); + if (complete) { + if (!postFilter || postFilter(this.toObject(this.row))) { + yield this.restore() as SuggestRowType; + } else { + this.discard(); + } + } + } catch (e) { + if (e instanceof NeverMatch) { + break; + } + throw e; + } + } while (this.incomplete.size); + } } diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 9a78f72..2b86560 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -8,41 +8,13 @@ import simple from "./criteria/simple"; import {PictConstraintsLexer} from "./utils/pict"; import { FactorsType, OptionsType, SuggestRowType, DictType, ListType } from "./types"; import { Controller } from "./controller"; -import { NeverMatch } from "./exceptions"; const makeAsync = function* ( factors: T, options: OptionsType = {} -) { - const { - criterion = greedy, - postFilter, - } = options; - +): Generator, void, unknown> { const ctrl = new Controller(factors, options); - do { - for (let pair of criterion(ctrl)) { - if (ctrl.isFilled(ctrl.row)) { - break; - } - ctrl.setPair(pair); - } - try { - const complete = ctrl.close(); - if (complete) { - if (!postFilter || postFilter(ctrl.toObject(ctrl.row))) { - yield ctrl.restore() as SuggestRowType; - } else { - ctrl.discard(); - } - } - } catch (e) { - if (e instanceof NeverMatch) { - break; - } - throw e; - } - } while (ctrl.incomplete.size); + yield* ctrl.makeAsync(); }; const make = (factors: T, options: OptionsType = {}) => { @@ -53,15 +25,16 @@ const sorters = { hash, random }; const criteria = { greedy, simple }; export { - make, - makeAsync, - sorters, + make, + makeAsync, + sorters, criteria, PictConstraintsLexer, + Controller, }; export type { - OptionsType, + OptionsType, SuggestRowType, DictType, ListType, From 268793a1431608cb7ab3de1133ab5a2b270d3c2c Mon Sep 17 00:00:00 2001 From: righ Date: Mon, 17 Mar 2025 22:04:31 +0900 Subject: [PATCH 52/55] v2.5.0 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 294c1ca..a3e63f0 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.4.1", + "version": "2.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.4.1", + "version": "2.5.0", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index 2ad6e2e..aa4a37e 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.4.1", + "version": "2.5.0", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://docs.walkframe.com/covertable", "repository": { From 09c6755896df4c5cc6b561e455e9687b9e5f4f72 Mon Sep 17 00:00:00 2001 From: righ Date: Mon, 17 Mar 2025 22:38:21 +0900 Subject: [PATCH 53/55] fix: 0div --- typescript/src/controller.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/typescript/src/controller.ts b/typescript/src/controller.ts index 0bf4b0f..70d4aa9 100644 --- a/typescript/src/controller.ts +++ b/typescript/src/controller.ts @@ -278,6 +278,9 @@ export class Controller { } get progress() { + if (this.numAllChunks === 0) { + return 0; + } return 1 - this.incomplete.size / this.numAllChunks; } From abcbf43542dedad83846c24d18735d5124286c36 Mon Sep 17 00:00:00 2001 From: righ Date: Mon, 17 Mar 2025 22:38:39 +0900 Subject: [PATCH 54/55] v2.5.1 --- typescript/package-lock.json | 4 ++-- typescript/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typescript/package-lock.json b/typescript/package-lock.json index a3e63f0..6cab470 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "covertable", - "version": "2.5.0", + "version": "2.5.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "covertable", - "version": "2.5.0", + "version": "2.5.1", "license": "Apache-2.0", "dependencies": { "js-md5": "^0.7.3" diff --git a/typescript/package.json b/typescript/package.json index aa4a37e..64b9f9d 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.5.0", + "version": "2.5.1", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://docs.walkframe.com/covertable", "repository": { From 90611d06e56c3c776d40cf3fa7256e2c932c0433 Mon Sep 17 00:00:00 2001 From: righ Date: Fri, 28 Mar 2025 20:17:15 +0900 Subject: [PATCH 55/55] fix: consume row pairs when the prefilter does not match. --- typescript/package.json | 2 +- typescript/src/controller.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/typescript/package.json b/typescript/package.json index 64b9f9d..190d03a 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "covertable", - "version": "2.5.1", + "version": "2.5.2", "description": "A flexible pairwise tool written in TypeScript", "homepage": "https://docs.walkframe.com/covertable", "repository": { diff --git a/typescript/src/controller.ts b/typescript/src/controller.ts index 70d4aa9..80544c1 100644 --- a/typescript/src/controller.ts +++ b/typescript/src/controller.ts @@ -131,6 +131,11 @@ export class Controller { this.row.consumed.set(pairKey, pair); } } + public consumeRow(row: Row) { + for (let pair of combinations([...row.values()], this.pairwiseCount)) { + this.consume(pair); + } + } public getCandidate(pair: PairType) { return getCandidate(pair, this.parents); @@ -156,6 +161,7 @@ export class Controller { try { const ok = this.options.preFilter(proxy); if (!ok) { + this.consumeRow(nxt); return null; } } catch (e) { @@ -206,7 +212,8 @@ export class Controller { } private discard() { - this.rejected.add(this.row.getPairKey()); + const pairKey = this.row.getPairKey(); + this.rejected.add(pairKey); this.row = new Row([]); } @@ -268,7 +275,7 @@ export class Controller { } const proxy = this.toProxy(this.row); try { - return this.options.preFilter ? this.options.preFilter(proxy) : true; + return this.options.preFilter?.(proxy) ?? true; } catch (e) { if (e instanceof NotReady) { return false; @@ -284,7 +291,7 @@ export class Controller { return 1 - this.incomplete.size / this.numAllChunks; } - public *makeAsync(): Generator, void, unknown> { + public *makeAsync() { const {criterion = greedy, postFilter} = this.options; do { for (let pair of criterion(this)) { @@ -309,5 +316,6 @@ export class Controller { throw e; } } while (this.incomplete.size); + this.incomplete.clear(); } }