Repository: LokiJS-Forge/LokiDB
Branch: master
Commit: ccc45527b2e9
Files: 643
Total size: 2.7 MB
Directory structure:
gitextract_bumayf7k/
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DEVELOPER.md
├── LICENSE
├── README.md
├── benchmark/
│ ├── benchmark.js
│ └── benchmark_indexes.js
├── config/
│ ├── jasmine.json
│ ├── karma.config.js
│ ├── nycrc.json
│ ├── nycrc.node.json
│ ├── tsconfig.tslint.json
│ ├── tsconfig.webpack.json
│ ├── tslint.json
│ └── webpack-config-creator.js
├── dist/
│ └── packages/
│ ├── fs-storage/
│ │ ├── lokidb.fs-storage.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── full-text-search/
│ │ ├── lokidb.full-text-search.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── full-text-search-language/
│ │ ├── lokidb.full-text-search-language.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── full-text-search-language-de/
│ │ ├── lokidb.full-text-search-language-de.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── full-text-search-language-en/
│ │ ├── lokidb.full-text-search-language-en.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── indexed-storage/
│ │ ├── lokidb.indexed-storage.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── local-storage/
│ │ ├── lokidb.local-storage.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── loki/
│ │ ├── lokidb.loki.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ ├── memory-storage/
│ │ ├── lokidb.memory-storage.js
│ │ └── types/
│ │ ├── common/
│ │ │ ├── plugin.d.ts
│ │ │ └── types.d.ts
│ │ ├── fs-storage/
│ │ │ └── src/
│ │ │ ├── fs_storage.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search/
│ │ │ └── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.d.ts
│ │ │ │ ├── character_filter.d.ts
│ │ │ │ ├── token_filter.d.ts
│ │ │ │ └── tokenizer.d.ts
│ │ │ ├── full_text_search.d.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.d.ts
│ │ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ │ ├── levenshtein_automata.d.ts
│ │ │ │ ├── long.d.ts
│ │ │ │ ├── parametric_description.d.ts
│ │ │ │ └── run_automaton.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index_searcher.d.ts
│ │ │ ├── inverted_index.d.ts
│ │ │ ├── query_types.d.ts
│ │ │ └── scorer.d.ts
│ │ ├── full-text-search-language/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── language.d.ts
│ │ ├── full-text-search-language-de/
│ │ │ └── src/
│ │ │ ├── german_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── full-text-search-language-en/
│ │ │ └── src/
│ │ │ ├── english_analyzer.d.ts
│ │ │ └── index.d.ts
│ │ ├── indexed-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── indexed_storage.d.ts
│ │ ├── local-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── local_storage.d.ts
│ │ ├── loki/
│ │ │ └── src/
│ │ │ ├── avl_index.d.ts
│ │ │ ├── clone.d.ts
│ │ │ ├── collection.d.ts
│ │ │ ├── comparators.d.ts
│ │ │ ├── dynamic_view.d.ts
│ │ │ ├── event_emitter.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── loki.d.ts
│ │ │ ├── operator_packages.d.ts
│ │ │ ├── ranged_indexes.d.ts
│ │ │ ├── result_set.d.ts
│ │ │ └── unique_index.d.ts
│ │ ├── memory-storage/
│ │ │ └── src/
│ │ │ ├── index.d.ts
│ │ │ └── memory_storage.d.ts
│ │ └── partitioning-adapter/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── partitioning_adapter.d.ts
│ └── partitioning-adapter/
│ ├── lokidb.partitioning-adapter.js
│ └── types/
│ ├── common/
│ │ ├── plugin.d.ts
│ │ └── types.d.ts
│ ├── fs-storage/
│ │ └── src/
│ │ ├── fs_storage.d.ts
│ │ └── index.d.ts
│ ├── full-text-search/
│ │ └── src/
│ │ ├── analyzer/
│ │ │ ├── analyzer.d.ts
│ │ │ ├── character_filter.d.ts
│ │ │ ├── token_filter.d.ts
│ │ │ └── tokenizer.d.ts
│ │ ├── full_text_search.d.ts
│ │ ├── fuzzy/
│ │ │ ├── automaton.d.ts
│ │ │ ├── lev1t_parametric_description.d.ts
│ │ │ ├── lev2t_parametric_description.d.ts
│ │ │ ├── levenshtein_automata.d.ts
│ │ │ ├── long.d.ts
│ │ │ ├── parametric_description.d.ts
│ │ │ └── run_automaton.d.ts
│ │ ├── index.d.ts
│ │ ├── index_searcher.d.ts
│ │ ├── inverted_index.d.ts
│ │ ├── query_types.d.ts
│ │ └── scorer.d.ts
│ ├── full-text-search-language/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── language.d.ts
│ ├── full-text-search-language-de/
│ │ └── src/
│ │ ├── german_analyzer.d.ts
│ │ └── index.d.ts
│ ├── full-text-search-language-en/
│ │ └── src/
│ │ ├── english_analyzer.d.ts
│ │ └── index.d.ts
│ ├── indexed-storage/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── indexed_storage.d.ts
│ ├── local-storage/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── local_storage.d.ts
│ ├── loki/
│ │ └── src/
│ │ ├── avl_index.d.ts
│ │ ├── clone.d.ts
│ │ ├── collection.d.ts
│ │ ├── comparators.d.ts
│ │ ├── dynamic_view.d.ts
│ │ ├── event_emitter.d.ts
│ │ ├── index.d.ts
│ │ ├── loki.d.ts
│ │ ├── operator_packages.d.ts
│ │ ├── ranged_indexes.d.ts
│ │ ├── result_set.d.ts
│ │ └── unique_index.d.ts
│ ├── memory-storage/
│ │ └── src/
│ │ ├── index.d.ts
│ │ └── memory_storage.d.ts
│ └── partitioning-adapter/
│ └── src/
│ ├── index.d.ts
│ └── partitioning_adapter.d.ts
├── docs/
│ ├── comparators.md
│ ├── css/
│ │ ├── codemirror/
│ │ │ ├── codemirror.css
│ │ │ └── foldgutter.css
│ │ └── javascript_editor.css
│ ├── index.md
│ ├── js/
│ │ ├── codemirror/
│ │ │ ├── addon/
│ │ │ │ ├── edit/
│ │ │ │ │ └── matchbrackets.js
│ │ │ │ └── fold/
│ │ │ │ ├── brace-fold.js
│ │ │ │ ├── foldcode.js
│ │ │ │ └── foldgutter.js
│ │ │ ├── lib/
│ │ │ │ └── codemirror.js
│ │ │ └── mode/
│ │ │ └── javascript/
│ │ │ └── javascript.js
│ │ ├── gitter.js
│ │ └── javascript_editor.js
│ ├── operator_packages.md
│ └── ranged_indexes.md
├── integration/
│ ├── .gitignore
│ ├── config/
│ │ ├── jasmine.json
│ │ ├── karma.amd.config.js
│ │ └── karma.browser.config.js
│ ├── package.json
│ ├── scripts/
│ │ └── install_lokidb.ts
│ └── spec/
│ ├── generic/
│ │ ├── full-text-search-language-de.spec.js
│ │ ├── full-text-search-language-en.spec.js
│ │ ├── full-text-search-language.spec.js
│ │ ├── full-text-search.spec.js
│ │ ├── loki.spec.js
│ │ ├── memory-storage.spec.js
│ │ └── partitioning-adapter.spec.js
│ ├── helper/
│ │ └── integration.helper.js
│ ├── node/
│ │ └── node-storage.spec.js
│ └── web/
│ ├── indexed-storage.spec.js
│ └── local-storage.spec.js
├── mkdocs.yml
├── package.json
├── packages/
│ ├── common/
│ │ ├── plugin.ts
│ │ └── types.ts
│ ├── fs-storage/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── node/
│ │ │ └── fs_storage.spec.ts
│ │ ├── src/
│ │ │ ├── fs_storage.ts
│ │ │ └── index.ts
│ │ └── webpack.config.js
│ ├── full-text-search/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ ├── generic/
│ │ │ │ ├── analyzer/
│ │ │ │ │ ├── character_filter.spec.ts
│ │ │ │ │ ├── token_filter.spec.ts
│ │ │ │ │ └── tokenizer.spec.ts
│ │ │ │ ├── full_text_search.spec.ts
│ │ │ │ ├── inverted_index.spec.ts
│ │ │ │ └── search/
│ │ │ │ ├── fuzzy.spec.ts
│ │ │ │ └── wildcard.spec.ts
│ │ │ └── node/
│ │ │ ├── MOCK_DATA.ts
│ │ │ ├── QUERIES.ts
│ │ │ └── elasticsearch.spec.ts
│ │ ├── src/
│ │ │ ├── analyzer/
│ │ │ │ ├── analyzer.ts
│ │ │ │ ├── character_filter.ts
│ │ │ │ ├── token_filter.ts
│ │ │ │ └── tokenizer.ts
│ │ │ ├── full_text_search.ts
│ │ │ ├── fuzzy/
│ │ │ │ ├── automaton.ts
│ │ │ │ ├── lev1t_parametric_description.ts
│ │ │ │ ├── lev2t_parametric_description.ts
│ │ │ │ ├── levenshtein_automata.ts
│ │ │ │ ├── long.ts
│ │ │ │ ├── parametric_description.ts
│ │ │ │ └── run_automaton.ts
│ │ │ ├── index.ts
│ │ │ ├── index_searcher.ts
│ │ │ ├── inverted_index.ts
│ │ │ ├── query_types.ts
│ │ │ └── scorer.ts
│ │ └── webpack.config.js
│ ├── full-text-search-language/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── helper/
│ │ │ └── create_lanuage_test.helper.ts
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── language.ts
│ │ └── webpack.config.js
│ ├── full-text-search-language-de/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── generic/
│ │ │ └── german_analyzer.spec.ts
│ │ ├── src/
│ │ │ ├── german_analyzer.ts
│ │ │ └── index.ts
│ │ └── webpack.config.js
│ ├── full-text-search-language-en/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── generic/
│ │ │ └── english_analyzer.spec.ts
│ │ ├── src/
│ │ │ ├── english_analyzer.ts
│ │ │ └── index.ts
│ │ └── webpack.config.js
│ ├── indexed-storage/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── web/
│ │ │ └── indexed_storage.spec.ts
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── indexed_storage.ts
│ │ └── webpack.config.js
│ ├── local-storage/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── web/
│ │ │ └── local_storage.spec.ts
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── local_storage.ts
│ │ └── webpack.config.js
│ ├── loki/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── generic/
│ │ │ ├── avl-index.spec.ts
│ │ │ ├── changesApi.spec.ts
│ │ │ ├── cloning.spec.ts
│ │ │ ├── collection.spec.ts
│ │ │ ├── comparators.spec.ts
│ │ │ ├── dynamic_view.spec.ts
│ │ │ ├── eventEmitter.spec.ts
│ │ │ ├── joins.spec.ts
│ │ │ ├── operator_packages.spec.ts
│ │ │ ├── ops.spec.ts
│ │ │ ├── persistence.spec.ts
│ │ │ ├── remove.spec.ts
│ │ │ ├── sortingIndexing.spec.ts
│ │ │ ├── stage.spec.ts
│ │ │ ├── stats.spec.ts
│ │ │ ├── test.spec.ts
│ │ │ ├── transforms.spec.ts
│ │ │ ├── typed.spec.ts
│ │ │ └── unique.spec.ts
│ │ ├── src/
│ │ │ ├── avl_index.ts
│ │ │ ├── clone.ts
│ │ │ ├── collection.ts
│ │ │ ├── comparators.ts
│ │ │ ├── dynamic_view.ts
│ │ │ ├── event_emitter.ts
│ │ │ ├── index.ts
│ │ │ ├── loki.ts
│ │ │ ├── operator_packages.ts
│ │ │ ├── ranged_indexes.ts
│ │ │ ├── result_set.ts
│ │ │ └── unique_index.ts
│ │ └── webpack.config.js
│ ├── memory-storage/
│ │ ├── package.json
│ │ ├── spec/
│ │ │ └── generic/
│ │ │ └── memory_storage.spec.ts
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── memory_storage.ts
│ │ └── webpack.config.js
│ └── partitioning-adapter/
│ ├── package.json
│ ├── spec/
│ │ └── generic/
│ │ └── partitioning.spec.ts
│ ├── src/
│ │ ├── index.ts
│ │ └── partitioning_adapter.ts
│ └── webpack.config.js
├── scripts/
│ ├── build.ts
│ ├── common.ts
│ └── deploy.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = space
indent_size = 2
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## I'm submitting a...
[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/LokiJS-Forge/LokiDB/blob/master/CONTRIBUTING.md#question
## Current behavior
## Expected behavior
## Minimal reproduction of the problem with instructions
## What is the motivation / use case for changing the behavior?
## Environment
LokiDB version: X.Y.Z
Browser/Node version: Browser X.Y.Z.
Others:
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## PR Checklist
Please check if your PR fulfills the following requirements:
- [ ] The commit message follows our guidelines: https://github.com/LokiJS-Forge/LokiDB/blob/master/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
## PR Type
What kind of change does this PR introduce?
```
[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:
```
## What is the current behavior?
Issue Number: N/A
## What is the new behavior?
## Does this PR introduce a breaking change?
```
[ ] Yes
[ ] No
```
## Other information
================================================
FILE: .gitignore
================================================
# IDE
.idea/
# NODE
node_modules/
# Tests
coverage/
.nyc_output
# Typescript
.ts/
# Build artifacts
build/
dist/packages-dist/
packages/**/*.html
site/
docs/api/
================================================
FILE: .travis.yml
================================================
language: python
python:
- "3.5"
node_js:
- "10"
dist: trusty
sudo: required
env:
global:
- GIT_NAME: Travis CI
- GIT_EMAIL: builds@travis-ci.org
- GIT_BRANCH: master
services:
- elasticsearch
addons:
chrome: stable
before_install:
- pip3 install mkdocs
- pip3 install mkdocs-material
script:
- npm install
- PATH=${PATH}:\.\/node_modules\/\.bin/
- npm run lint
- npm test
- codecov
- npm run docs
- mkdocs build
- npm run build
- npm run build -- --dist
- npm install --prefix integration
- npm run test:integration
after_success:
- npm run deploy
================================================
FILE: CHANGELOG.md
================================================
# [2.1.0](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0...2.1.0) (2020-08-23)
### Features
* **fts:** support optional, empty or number fields ([#181](https://github.com/LokiJS-Forge/LokiDB/issues/181)) ([57e2ff8](https://github.com/LokiJS-Forge/LokiDB/commit/57e2ff8))
# [2.0.0](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0-beta.9...2.0.0) (2020-08-22)
### Bug Fixes
* **persistence:** ignore error if database is not found on autoload ([#179](https://github.com/LokiJS-Forge/LokiDB/issues/179)) ([d1703c6](https://github.com/LokiJS-Forge/LokiDB/commit/d1703c6))
# [2.0.0-beta.9](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0-beta.8...2.0.0-beta.9) (2020-02-07)
### Bug Fixes
* **loki:** unique search with no matching entry should not fail ([#172](https://github.com/LokiJS-Forge/LokiDB/issues/172)) ([fd2c7d9](https://github.com/LokiJS-Forge/LokiDB/commit/fd2c7d9))
* **loki:** use global.proceas in getENV ([#170](https://github.com/LokiJS-Forge/LokiDB/issues/170)) ([a65e668](https://github.com/LokiJS-Forge/LokiDB/commit/a65e668))
# [2.0.0-beta.8](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0-beta.7...2.0.0-beta.8) (2018-09-14)
### Bug Fixes
* **loki:** define nested properties on rollback transaction ([#149](https://github.com/LokiJS-Forge/LokiDB/issues/149)) ([9e06e91](https://github.com/LokiJS-Forge/LokiDB/commit/9e06e91))
### Features
* **loki:** remove binary index ([#146](https://github.com/LokiJS-Forge/LokiDB/issues/146)) ([1fb99f2](https://github.com/LokiJS-Forge/LokiDB/commit/1fb99f2))
* **loki:** user definable comparators and operator packages ([#152](https://github.com/LokiJS-Forge/LokiDB/issues/152)) ([5c14bc2](https://github.com/LokiJS-Forge/LokiDB/commit/5c14bc2))
# [2.0.0-beta.7](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0-beta.6...2.0.0-beta.7) (2018-06-27)
### Bug Fixes
* **full-text-search:** apply bool query boost to subquery results ([#122](https://github.com/LokiJS-Forge/LokiDB/issues/122)) ([5548fe5](https://github.com/LokiJS-Forge/LokiDB/commit/5548fe5))
* **full-text-search:** handle not and filter bool queries right ([#128](https://github.com/LokiJS-Forge/LokiDB/issues/128)) ([98d0cd8](https://github.com/LokiJS-Forge/LokiDB/commit/98d0cd8))
* **loki:** fix autosave and autoload of the database ([#112](https://github.com/LokiJS-Forge/LokiDB/issues/112)) ([ef260fd](https://github.com/LokiJS-Forge/LokiDB/commit/ef260fd))
* **loki:** when cloning, meta will be applied correctly and clones emitted ([#111](https://github.com/LokiJS-Forge/LokiDB/issues/111)) ([d287a2d](https://github.com/LokiJS-Forge/LokiDB/commit/d287a2d)), closes [techfort/LokiJS#666](https://github.com/techfort/LokiJS/issues/666)
### Features
* improve type notation ([#109](https://github.com/LokiJS-Forge/LokiDB/issues/109)) ([3b60c9f](https://github.com/LokiJS-Forge/LokiDB/commit/3b60c9f))
* **full-text-search:** allow number or string as document id ([#115](https://github.com/LokiJS-Forge/LokiDB/issues/115)) ([1d81e25](https://github.com/LokiJS-Forge/LokiDB/commit/1d81e25))
* **full-text-search:** export function analyze ([#102](https://github.com/LokiJS-Forge/LokiDB/issues/102)) ([c1dd78c](https://github.com/LokiJS-Forge/LokiDB/commit/c1dd78c))
* **full-text-search:** if elasticsearch is not available, disable its unit test ([#98](https://github.com/LokiJS-Forge/LokiDB/issues/98)) ([a1c7d8d](https://github.com/LokiJS-Forge/LokiDB/commit/a1c7d8d))
* **full-text-search:** implement conditional minimum should match parameter ([#129](https://github.com/LokiJS-Forge/LokiDB/issues/129)) ([baa6311](https://github.com/LokiJS-Forge/LokiDB/commit/baa6311))
* **full-text-search:** make analyzers classes instead of objects ([#123](https://github.com/LokiJS-Forge/LokiDB/issues/123)) ([1959688](https://github.com/LokiJS-Forge/LokiDB/commit/1959688))
# [2.0.0-beta.6](https://github.com/LokiJS-Forge/LokiDB/compare/2.0.0-beta.5...2.0.0-beta.6) (2018-03-23)
For a better distinction, the library has been renamed to LokiDB.
The repository is now located under https://github.com/LokiJS-Forge/LokiDB
The npm packages can be found under the organization scope @lokidb.
## Commit Summary
### Bug Fixes
* **full-text-search:** fix fuzzy's prefix length, edit distance and idf ([#68](https://github.com/LokiJS-Forge/LokiDB/issues/68)) ([da06836](https://github.com/LokiJS-Forge/LokiDB/commit/da06836))
* **full-text-search:** rename field option "name" to "field" ([#67](https://github.com/LokiJS-Forge/LokiDB/issues/67)) ([ff74219](https://github.com/LokiJS-Forge/LokiDB/commit/ff74219))
* **loki:** fix a autosave race condition when using asynchronous adapter ([#79](https://github.com/LokiJS-Forge/LokiDB/issues/79)) ([db26d02](https://github.com/LokiJS-Forge/LokiDB/commit/db26d02))
* **loki:** fix binary index in batch updates when not cloning ([#78](https://github.com/LokiJS-Forge/LokiDB/issues/78)) ([8081799](https://github.com/LokiJS-Forge/LokiDB/commit/8081799))
### Features
* **full-text-search:** remove query builder ([#73](https://github.com/LokiJS-Forge/LokiDB/issues/73)) ([84757ab](https://github.com/LokiJS-Forge/LokiDB/commit/84757ab))
* **full-text-search:** remove unnecessary array query ([#75](https://github.com/LokiJS-Forge/LokiDB/issues/75)) ([4ff5165](https://github.com/LokiJS-Forge/LokiDB/commit/4ff5165))
* **full-text-search:** replace the old "tokenizer" class with an analyzer interface ([#76](https://github.com/LokiJS-Forge/LokiDB/issues/76)) ([2d44384](https://github.com/LokiJS-Forge/LokiDB/commit/2d44384))
* **full-text-search:** return score result as an equivalent array to result set data ([#69](https://github.com/LokiJS-Forge/LokiDB/issues/69)) ([7ea17c0](https://github.com/LokiJS-Forge/LokiDB/commit/7ea17c0))
* **loki:** add diagnostic function to test binary index validity ([#85](https://github.com/LokiJS-Forge/LokiDB/issues/85)) ([d611722](https://github.com/LokiJS-Forge/LokiDB/commit/d611722))
* **loki:** add option to disable meta property for documents added to a collection ([#80](https://github.com/LokiJS-Forge/LokiDB/issues/80)) ([1a49470](https://github.com/LokiJS-Forge/LokiDB/commit/1a49470))
* **loki:** add simplified javascript comparisons $jgt, $jgte, $jlt, $jlte, $jbetween ([#87](https://github.com/LokiJS-Forge/LokiDB/issues/87)) ([32e4b1e](https://github.com/LokiJS-Forge/LokiDB/commit/32e4b1e))
* **loki:** change and improve nested property support ([#81](https://github.com/LokiJS-Forge/LokiDB/issues/81)) ([2730284](https://github.com/LokiJS-Forge/LokiDB/commit/2730284))
* **loki:** return an existing collection if a collection with the same name already exists ([#77](https://github.com/LokiJS-Forge/LokiDB/issues/77)) ([75afd67](https://github.com/LokiJS-Forge/LokiDB/commit/75afd67))
* **loki:** simplesort leverages binary indices better when filtered ([#83](https://github.com/LokiJS-Forge/LokiDB/issues/83)) ([4d1b25b](https://github.com/LokiJS-Forge/LokiDB/commit/4d1b25b))
# [2.0.0-beta.5](https://github.com/LokiJS-Forge/LokiJS2/compare/2.0.0-beta.4...2.0.0-beta.5) (2018-01-02)
### Bug Fixes
* **full-text-search-language:** add missing function export ([#64](https://github.com/LokiJS-Forge/LokiJS2/issues/64)) ([9b926e2](https://github.com/LokiJS-Forge/LokiJS2/commit/9b926e2))
### Features
* improve typings ([#62](https://github.com/LokiJS-Forge/LokiJS2/issues/62)) ([b44f550](https://github.com/LokiJS-Forge/LokiJS2/commit/b44f550))
* **full-text-search:** add an optional score explanation ([#65](https://github.com/LokiJS-Forge/LokiJS2/issues/65)) ([9fde195](https://github.com/LokiJS-Forge/LokiJS2/commit/9fde195))
* **memory-storage:** move memory storage to a separate package ([#63](https://github.com/LokiJS-Forge/LokiJS2/issues/63)) ([7cea02a](https://github.com/LokiJS-Forge/LokiJS2/commit/7cea02a))
# [2.0.0-beta.4](https://github.com/LokiJS-Forge/LokiJS2/compare/2.0.0-beta.3...2.0.0-beta.4) (2017-12-01)
### Features
* **full-text-search:** make index Unicode safe and improve fuzzy performance ([#55](https://github.com/LokiJS-Forge/LokiJS2/issues/55)) ([f1dea05](https://github.com/LokiJS-Forge/LokiJS2/commit/f1dea05))
# [2.0.0-beta.3](https://github.com/LokiJS-Forge/LokiJS2/compare/2.0.0-beta.2...2.0.0-beta.3) (2017-11-26)
### Bug Fixes
* coverage ([#42](https://github.com/LokiJS-Forge/LokiJS2/issues/42)) ([3509429](https://github.com/LokiJS-Forge/LokiJS2/commit/3509429))
* **full-text-search:** fix fuzzy extended to withdraw wrong results ([#51](https://github.com/LokiJS-Forge/LokiJS2/issues/51)) ([4d493ac](https://github.com/LokiJS-Forge/LokiJS2/commit/4d493ac))
* **loki:** cloning method for specific classes ([#30](https://github.com/LokiJS-Forge/LokiJS2/issues/30)) ([4f4a182](https://github.com/LokiJS-Forge/LokiJS2/commit/4f4a182))
* **loki:** fix error if passed parameters are not serializable for transform ([#43](https://github.com/LokiJS-Forge/LokiJS2/issues/43)) ([dde34ed](https://github.com/LokiJS-Forge/LokiJS2/commit/dde34ed))
* **loki:** implement deep clone as default clone option ([#44](https://github.com/LokiJS-Forge/LokiJS2/issues/44)) ([2f3b718](https://github.com/LokiJS-Forge/LokiJS2/commit/2f3b718))
### Features
* **full-text-search:** add full-text-search as separate package ([#35](https://github.com/LokiJS-Forge/LokiJS2/issues/35)) ([14b9947](https://github.com/LokiJS-Forge/LokiJS2/commit/14b9947))
* **full-text-search:** english and german language support ([3a93477](https://github.com/LokiJS-Forge/LokiJS2/commit/3a93477))
* **full-text-search:** implement extended fuzzy ([#47](https://github.com/LokiJS-Forge/LokiJS2/issues/47)) ([0579026](https://github.com/LokiJS-Forge/LokiJS2/commit/0579026))
* **loki:** add 'dataOptions' to eqJoin ([#33](https://github.com/LokiJS-Forge/LokiJS2/issues/33)) ([efa450e](https://github.com/LokiJS-Forge/LokiJS2/commit/efa450e))
* **loki:** add optional flag for Changes API to limit update operation output to modified properties only ([#29](https://github.com/LokiJS-Forge/LokiJS2/issues/29)) ([a8abe99](https://github.com/LokiJS-Forge/LokiJS2/commit/a8abe99))
* **loki:** allow sorting on nested properties ([#31](https://github.com/LokiJS-Forge/LokiJS2/issues/31)) ([9b426a4](https://github.com/LokiJS-Forge/LokiJS2/commit/9b426a4))
* **loki:** chained/transform map op now accepts 'dataOptions' for clone/removeMeta ([#34](https://github.com/LokiJS-Forge/LokiJS2/issues/34)) ([67d61ac](https://github.com/LokiJS-Forge/LokiJS2/commit/67d61ac))
* **loki:** make Resultset and DynamicView sortable by full-text-search scoring ([#45](https://github.com/LokiJS-Forge/LokiJS2/issues/45)) ([0a5b946](https://github.com/LokiJS-Forge/LokiJS2/commit/0a5b946))
* **loki:** rename collection ([#32](https://github.com/LokiJS-Forge/LokiJS2/issues/32)) ([745e025](https://github.com/LokiJS-Forge/LokiJS2/commit/745e025))
* integrate full-text-search to loki (insert/update/remove + search) ([8fbc174](https://github.com/LokiJS-Forge/LokiJS2/commit/8fbc174))
* move to typescript ([#36](https://github.com/LokiJS-Forge/LokiJS2/issues/36)) ([d47f190](https://github.com/LokiJS-Forge/LokiJS2/commit/d47f190))
# [2.0.0-beta.2](https://github.com/LokiJS-Forge/LokiJS2/compare/2.0.0-beta.1...2.0.0-beta.2) (2017-09-21)
# 2.0.0-beta.1 (2017-09-21)
### Features
* **fs-storage:** add fs storage as separate package ([#19](https://github.com/LokiJS-Forge/LokiJS2/issues/19)) ([ec2e523](https://github.com/LokiJS-Forge/LokiJS2/commit/ec2e523))
* **indexed-storage:** add indexed storage as separate package ([#20](https://github.com/LokiJS-Forge/LokiJS2/issues/20)) ([1150029](https://github.com/LokiJS-Forge/LokiJS2/commit/1150029))
* **local-storage:** add local storage as separate package ([#18](https://github.com/LokiJS-Forge/LokiJS2/issues/18)) ([548abfe](https://github.com/LokiJS-Forge/LokiJS2/commit/548abfe))
* **loki:** add lokijs as core package ([#9](https://github.com/LokiJS-Forge/LokiJS2/issues/9)) ([f670ea0](https://github.com/LokiJS-Forge/LokiJS2/commit/f670ea0))
* **partitioning-adapter:** add partitioning-adapter as separate package ([#14](https://github.com/LokiJS-Forge/LokiJS2/issues/14)) ([c6b18ca](https://github.com/LokiJS-Forge/LokiJS2/commit/c6b18ca))
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at lutztonineubert@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to LokiDB
We would love for you to contribute to LokiDB and help make it even better than it is
today! As a contributor, here are the guidelines we would like you to follow:
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Test LokiDB](#develop)
## Code of Conduct
Help us keep LokiDB open and inclusive. Please read and follow our [Code of Conduct][coc].
## Got a Question or Problem?
Please ask your questions tagged with `lokidb` at [Stack Overflow][stackoverflow].
If you would like to chat about the questions in real-time, you can reach out via [our gitter channel][gitter].
## Found a Bug?
If you find a bug in the source code, you can help us by
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
[submit a Pull Request](#submit-pr) with a fix.
## Missing a Feature?
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
Repository. If you would like to *implement* a new feature, please submit an issue with
a proposal for your work first, to be sure that we can use it.
## Submission Guidelines
### Submitting an Issue
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
- version of LokiDB used
- 3rd-party libraries and their versions
- and most importantly - a use-case that fails
A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. If plunker is not a suitable way to demonstrate the problem (for example for issues related to our npm packaging), please create a standalone git repository demonstrating the problem.
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
Unfortunately we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
You can file new issues by filling out our [new issue form][new-issue].
### Submitting a Pull Request (PR)
Before you submit your Pull Request (PR) consider the following guidelines:
* Search [GitHub][pulls] for an open or closed PR that relates to your submission. You don't want to duplicate effort.
* Create your patch, **including appropriate test cases**.
* Follow our [Coding Rules](#rules).
* Run the full LokiDB test suite, as described in the [developer documentation][dev-doc],
and ensure that all tests pass.
* Commit your changes using a descriptive commit message that follows our
[commit message conventions](#commit). Adherence to these conventions
is necessary because release notes are automatically generated from these messages.
* In GitHub, send a pull request to `LokiDB:master`.
* If we suggest changes then:
* Make the required updates.
* Re-run the LokiDB test suites to ensure tests are still passing.
That's it! Thank you for your contribution!
## Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
* All public API methods **must be documented**. (Details TBC).
* We use a consistent code formatting. An automated formatter is available, see the [developer guideline][dev-doc].
## Commit Message Guidelines
We have very precise rules over how our git commit messages can be formatted. This leads to **more
readable messages** that are easy to follow when looking through the **project history**. But also,
we use the git commit messages to **generate the LokiDB change log**.
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
```
():
```
The **header** is mandatory and the **scope** of the header is optional.
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
Samples: (even more [samples][commits])
```
docs(changelog): update change log to beta.5
```
```
fix(release): need to depend on latest rxjs and zone.js
The version in our package.json gets copied to the one we publish, and users need the latest of these.
```
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit .`, where the hash is the SHA of the commit being reverted.
### Type
Must be one of the following:
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
* **docs**: Documentation only changes
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **test**: Adding missing tests or correcting existing tests
### Scope
The scope should be the name of the npm package affected (as perceived by person reading changelog generated from commit messages.
The following is the list of supported scopes:
* **loki**: The LokiDB database.
* **partitioning-adapter**: The partitioning adapter.
* **local-storage**: The local storage adapter.
* **indexed-storage**: The indexed db storage adapter.
* **fs-storage**: The file system storage adapter.
* **memory-storage**: The in-memory storage adapter.
* **full-text-search**: The full-text search engine.
* **full-text-search-language**: The language analyzer utility package.
* **full-text-search-language-de**: The german language analyzer.
* **full-text-search-language-en**: The english language analyzer.
There are currently a few exceptions to the "use package name" rule:
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
### Subject
The subject contains succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
[coc]: https://github.com/LokiJS-Forge/LokiDB/blob/master/CODE_OF_CONDUCT.md
[dev-doc]: https://github.com/LokiJS-Forge/LokiDB/blob/master/DEVELOPER.md
[github]: https://github.com/LokiJS-Forge/LokiDB
[new-issue]: https://github.com/LokiJS-Forge/LokiDB/issues/new
[pulls]: https://github.com/LokiJS-Forge/LokiDB/pulls
[commit]: https://github.com/LokiJS-Forge/LokiDB/commits/master
[gitter]: https://gitter.im/techfort/LokiDB
[plunker]: http://plnkr.co/edit
[stackoverflow]: http://stackoverflow.com/questions/tagged/lokidb?sort=newest
================================================
FILE: DEVELOPER.md
================================================
# Building and testing LokiDB
This document describes how to set up your development environment to build and test LokiDB.
* [Prerequisite software](#prerequisite-software)
* [Running tests](#running-tests)
* [Formatting your source code](#formatting-your-source-code)
* [Building LokiDB](#building-lokidb)
See the [contribution guidelines][contribution] if you'd like to contribute to LokiDB.
## Prerequisite software
Before you can build and test LokiDB, you must install and configure the
following products on your development machine:
* [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or
[Windows](http://windows.github.com)); [GitHub's Guide to Installing
Git](https://help.github.com/articles/set-up-git) is a good source of information.
* [Node.js](http://nodejs.org), (version `>=7.0.0`) which is used to run tests and generate distributable files.
We also use Node's Package Manager, `npm`(version `>=4.0.0`), which comes with Node.
Depending on your system, you can install Node either from source or as a pre-packaged bundle.
* [Elasticsearch](https://www.elastic.co/downloads/elasticsearch) which is used to unit test LokiDB's full text search.
## Running tests
To run tests:
```shell
$ npm run test # Run all LokiDB tests
$ npm run test:web # Run tests only in web browser
$ npm run test:node # Run tests only in node
```
All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass.
## Formatting your source code
LokiDB uses [ESLint][eslint] to format the source code. If the source code is not properly formatted, the CI will fail and the PR can not be merged.
You can check that your code is properly formatted and adheres to coding style by running:
``` shell
$ npm run lint
```
You can automatically format your code by running:
``` shell
$ npm run lint:fix
```
## Building LokiDB
To build LokiDB, run:
``` shell
$ npm run build
```
[eslint]: https://eslint.org/
[contribution]: https://github.com/LokiJS-Forge/LokiDB/blob/master/CONTRIBUTING.md
================================================
FILE: LICENSE
================================================
This text consists of three parts:
Part I: Remarks regarding the license given in
Part II: MIT License
Part III: Apache License
-------------------------------------------------------------------------------
Part I:
LokiDB is mostly distributed under the MIT License.
Except the following packages:
@lokidb/full-text-search
- Apache License (https://lucene.apache.org/)
- Apache License (https://www.elastic.co/)
-------------------------------------------------------------------------------
Part II:
MIT License
Copyright (c) 2015-2018 Joe Minichino
David Easterday
Toni Neubert
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
Part III:
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
================================================
FILE: README.md
================================================
[![npm status][npm]][npm-url]
[![build status][build]][build-url]
[![coverage status][coverage]][coverage-url]
# LokiDB
LokiDB is a document oriented database written in TypeScript.
Its purpose is to store javascript objects as documents in a blazing fast nosql fashion and retrieve them with a similar mechanism.
LokiDB is the official successor of [LokiJS][lokijs-url].
## Install
Install with npm:
```bash
npm install @lokidb/loki
```
## Documentation
Check out our interactive [documentation](https://LokiJS-Forge.github.io/LokiDB/).
## Plugins
### Storage and Adapter
|Name|Description|
|:---|:----------|
|[@lokidb/fs-storage][fs-storage-npm-url] | A persistence adapter which persists to node fs module storage. |
|[@lokidb/local-storage][local-storage-npm-url] | A persistence adapter which persists to web browser's local storage. |
|[@lokidb/indexed-storage][indexed-storage-npm-url] | A persistence adapter which persists to web browser's indexed db storage. |
|[@lokidb/memory-storage][memory-storage-npm-url] | A persistence adapter which persists to memory. |
|[@lokidb/partitioning-adapter][partitioning-adapter-npm-url] | An adapter for adapters. Converts a non reference mode adapter into a reference mode adapter which can perform destructuring and partitioning.|
### Full-Text Search
|Name|Description|
|:---|:----------|
|[@lokidb/full-text-search][full-text-search-npm-url] | A full-text search engine. |
|[@lokidb/full-text-search-language][full-text-search-language-npm-url] | A language analyzer utility package. |
|[@lokidb/full-text-search-language-de][full-text-search-language-de-npm-url] | ![flag][full-text-search-language-de-flag] A german language analyzer. |
|[@lokidb/full-text-search-language-en][full-text-search-language-en-npm-url] | ![flag][full-text-search-language-en-flag] An english language analyzer. |
[build]: https://travis-ci.org/LokiJS-Forge/LokiDB.svg?branch=master
[build-url]: https://travis-ci.org/LokiJS-Forge/LokiDB
[coverage]: https://codecov.io/gh/LokiJS-Forge/LokiDB/branch/master/graph/badge.svg
[coverage-url]: https://codecov.io/gh/LokiJS-Forge/LokiDB/branch/master
[lokijs-url]: https://github.com/techfort/LokiJS
[npm]: https://img.shields.io/npm/v/@lokidb/loki.svg
[npm-url]: https://www.npmjs.com/package/@lokidb/loki
[fs-storage]: https://github.com/LokiJS-Forge/LokiDB
[fs-storage-npm-url]: https://www.npmjs.com/package/@lokidb/fs-storage
[local-storage]: https://github.com/LokiJS-Forge/LokiDB
[local-storage-npm-url]: https://www.npmjs.com/package/@lokidb/local-storage
[indexed-storage]: https://github.com/LokiJS-Forge/LokiDB
[indexed-storage-npm-url]: https://www.npmjs.com/package/@lokidb/indexed-storage
[memory-storage]: https://github.com/LokiJS-Forge/LokiDB
[memory-storage-npm-url]: https://www.npmjs.com/package/@lokidb/memory-storage
[partitioning-adapter]: https://github.com/LokiJS-Forge/LokiDB
[partitioning-adapter-npm-url]: https://www.npmjs.com/package/@lokidb/partitioning-adapter
[full-text-search]: https://github.com/LokiJS-Forge/LokiDB
[full-text-search-npm-url]: https://www.npmjs.com/package/@lokidb/full-text-search
[full-text-search-language]: https://github.com/LokiJS-Forge/LokiDB
[full-text-search-language-npm-url]: https://www.npmjs.com/package/@lokidb/full-text-search-language
[full-text-search-language-de]: https://github.com/LokiJS-Forge/LokiDB
[full-text-search-language-de-flag]: https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/de.png
[full-text-search-language-de-npm-url]: https://www.npmjs.com/package/@lokidb/full-text-search-language-de
[full-text-search-language-en]: https://github.com/LokiJS-Forge/LokiDB
[full-text-search-language-en-npm-url]: https://www.npmjs.com/package/@lokidb/full-text-search-language-en
[full-text-search-language-en-flag]: https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/us.png
================================================
FILE: benchmark/benchmark.js
================================================
/**
* Core, "single object lookup" benchmarks
*/
let Loki = require('../build/packages/loki/lokidb.loki.js').default,
crypto = require("crypto");
/**
* Generates a random string using node crypto library which is less memory 'leaky'
*/
function genRandomVal() {
return crypto.randomBytes(50).toString('hex');
}
/**
* Helper method for instantiating a loki database
* @param {*} mode
*/
function createDatabase(mode) {
let tdb = new Loki("temp.db");
let coll;
switch (mode) {
case "avl":
coll = tdb.addCollection('perfcoll', {
rangedIndexes: {
"customId": { indexTypeName: "avl", comparatorName: "js" }
}
});
break;
case "unique":
coll = tdb.addCollection('perfcoll', {
unique: ['customId']
});
break;
case "none":
default:
coll = tdb.addCollection('perfcoll');
break;
}
return tdb;
}
/**
* Helper method for populating a collection
* @param {*} db
* @param {*} count
*/
function populateDatabase(db, count) {
let coll = db.getCollection("perfcoll");
// populate collection
let idxbuf = [];
let customIdx, v1;
for (let idx = 0; idx < count; idx++) {
customIdx = count - idx;
idxbuf.push(customIdx);
v1 = genRandomVal();
coll.insert({
customId: customIdx,
val: v1,
val2: "more data 1234567890"
});
}
return idxbuf;
}
/**
* Benchmarks collection.by() performance with unique index
* @param {*} count
* @param {*} multiple
*/
function benchUniquePerf(count, multiple) {
let udb = createDatabase("unique");
let uniquecoll = udb.getCollection('perfcoll');
let v1, idxbuf = [];
for (let idx = 0; idx < count; idx++) {
v1 = genRandomVal();
uniquecoll.insert({
customId: (count - idx),
val: v1,
val2: "more data 1234567890"
});
idxbuf.push(count - idx);
}
let start, end;
let totalTimes = [];
let totalMS = 0.0;
let customIdx, result;
for (let m = 0; m < multiple; m++) {
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
result = uniquecoll.by('customId', customIdx);
end = process.hrtime(start);
totalTimes.push(end);
if (result.customId !== customIdx) {
console.log("(perfUnique) object retrieved does match custom id");
}
}
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = multiple * count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("coll.by() : " + totalMS + "ms (" + rate + " ops/s) " + multiple*count + " iterations, " + count + " docs x " + multiple);
};
/**
* Benchmarks collection.get() performance
* @param {*} count number of documents to insert into collection
* @param {*} multiple number of times to repeat get() for each document
*/
function testperfGet(count, multiple) {
let gdb = createDatabase("none");
let coll = gdb.getCollection('perfcoll');
let start, end;
let totalTimes = [];
let totalMS = 0.0;
let customIdx, v1, obj = {}, idxbuf = [];
for (let idx = 0; idx < count; idx++) {
v1 = genRandomVal();
obj = coll.insert({
customId: (count - idx),
val: v1,
val2: "more data 1234567890"
});
idxbuf.push(obj.$loki);
}
let result;
for (let m = 0; m < multiple; m++) {
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
result = coll.get(customIdx);
end = process.hrtime(start);
totalTimes.push(end);
if (result.$loki !== customIdx) {
console.log("(perfGet) object retrieved does match get id");
}
}
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = multiple * count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("coll.get() : " + totalMS + "ms (" + rate + " ops/s) " + multiple*count + " iterations, " + count + " docs x " + multiple);
}
/**
* Benchmark collection find() performance
* @param {*} mode Index Mode ("none", "unique", "avl")
* @param {*} count Document count to populate collection with
* @param {*} multiple Used to repeat finding each document this number of times
*/
function testperfFind(mode, count, multiple) {
multiple = multiple || 1;
let fdb = createDatabase(mode);
let idxbuf = populateDatabase(fdb, count);
let coll = fdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let results;
for (let m = 0; m < multiple; m++) {
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
results = coll.find({
'customId': customIdx
});
end = process.hrtime(start);
totalTimes.push(end);
if (results.length !== 1) {
console.log("(perfFind) received " + results.length + "instead of 1 matches!");
}
}
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = multiple * count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("coll.find() : " + totalMS + "ms (" + rate + " ops/s) " + multiple * count + " iterations, " + count + " docs x " + multiple);
}
/**
* Resultset benchmark
* @param {*} mode
* @param {*} count
*/
function testperfRS(mode, count, multiple) {
multiple = multiple || 1;
let rsdb = createDatabase(mode);
let idxbuf = populateDatabase(rsdb, count);
let coll = rsdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let customIdx, results;
for (let m = 0; m < multiple; m++) {
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
results = coll.chain().find({
'customId': customIdx
}).data();
end = process.hrtime(start)
totalTimes.push(end);
if (results.length !== 1) {
console.log("(perfRS) received " + results.length + "instead of 1 matches!");
}
}
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = multiple * count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("resultset chained find() : " + totalMS + "ms (" + rate + " ops/s) " + multiple * count + " iterations, " + count + " docs x " + multiple);
}
/**
* Benchmark dynamic view performance
* @param {*} mode
* @param {*} count
* @param {*} multiple
*/
function testperfDV(mode, count, multiple) {
multiple = multiple || 1;
let dvdb = createDatabase(mode);
let idxbuf = populateDatabase(dvdb, count);
let coll = dvdb.getCollection("perfcoll");
let start, end;
let start2, end2, totalTime2 = 0.0;
let totalTimes = [];
let totalTimes2 = [];
let totalMS = 0;
let totalMS2 = 0;
let customIdx, dv, results;
for (let m = 0; m < multiple; m++) {
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
dv = coll.addDynamicView("perfview");
dv.applyFind({
'customId': customIdx
});
results = dv.data();
end = process.hrtime(start);
totalTimes.push(end);
// test speed of repeated query on an already set up dynamicview
start2 = process.hrtime();
results = dv.data();
end2 = process.hrtime(start2);
totalTimes2.push(end2);
coll.removeDynamicView("perfview");
}
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
totalMS2 += totalTimes2[idx][0] * 1e3 + totalTimes2[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
totalMS2 = totalMS2.toFixed(2);
let rate = multiple * count * 1000 / totalMS;
let rate2 = multiple * count * 1000 / totalMS2;
rate = rate.toFixed(2);
rate2 = rate2.toFixed(2);
console.log("loki dynamic view first find : " + totalMS + "ms (" + rate + " ops/s) " + multiple * count + " iterations, " + count + " docs x " + multiple);
console.log("loki dynamic view subsequent finds : " + totalMS2 + "ms (" + rate2 + " ops/s) " + multiple * count + " iterations, " + count + " docs x " + multiple);
}
/**
* Attempt to free up global variables and invoke node garbage collector (if enabled)
*/
function cleanup() {
if (global.gc) {
global.gc()
}
}
let corePerf = [
() => testperfGet(200000, 20),
() => benchUniquePerf(200000, 20)
];
let nonIndexedSteps = [
() => testperfFind("none", 5000, 8),
() => testperfRS("none", 5000, 8),
() => testperfDV("none", 5000, 8)
];
let nonIndexedStepsHigh = [
() => testperfFind("none", 10000, 1),
() => testperfRS("none", 10000, 1),
() => testperfDV("none", 10000, 1)
];
let avlIndexSteps = [
() => testperfFind("avl", 20000, 20),
() => testperfRS("avl", 20000, 20),
() => testperfDV("avl", 20000, 20)
];
let avlIndexStepsHigh = [
() => testperfFind("avl", 200000, 2),
() => testperfRS("avl", 200000, 2),
() => testperfDV("avl", 200000, 2)
];
let perfGroups = [
{ name: "Benchmarking Core Id lookup performance", steps: corePerf },
{ name: "Benchmarking NON-INDEX query performance (Lower doc count)", steps: nonIndexedSteps },
{ name: "Benchmarking NON-INDEX query performance (Higher doc count)", steps: nonIndexedStepsHigh },
{ name: "Benchmarking AVL TREE INDEX query performance (Lower doc count)", steps: avlIndexSteps },
{ name: "Benchmarking AVL TREE INDEX query performance (Higher doc count)", steps: avlIndexStepsHigh }
];
/**
* Executes steps within a benchmark group, pausing in between steps.
* Once the benchmark group steps are depleted, we initiate next group.
* @param {*} steps
*/
function execSteps(steps) {
// if we are finished with this group's steps...
if (steps.length === 0) {
// wait a few seconds in between benchmark groups
setTimeout(execGroups, 4000);
return;
}
let s = steps.shift();
s();
setTimeout(() => { execSteps(steps); }, 1000);
}
/**
* Kicks off a group of benchmarks, cleaning up in between
*/
function execGroups() {
let g = perfGroups.shift();
if (!g) return;
cleanup();
console.log("");
console.log("## " + g.name + " ##");
console.log("");
execSteps(g.steps);
}
console.log("");
console.log("Note: run 'npm run build' before benchmarking after getting latest or modifying code");
console.log("");
if (!global.gc) {
console.warn("##");
console.warn("## IMPORTANT! : For accuracy of results, launch node with --expose-gc flag");
console.warn("##");
}
execGroups();
================================================
FILE: benchmark/benchmark_indexes.js
================================================
/**
* This module is to be used to benchmark loki binary index lifecycle
*
* Attempt to simulate and benchmark effects of various rebuild strategies on
* insert, find, remove, and update to be used to instrument refactorings/optimizations.
*
* Since a given index type may prioritize lookups/finds over maintenance of insert/update/remove ops,
* the 'Nightmare' tests attempt to pair a find along with insert/update/removes. The resulting
* times tend to average out this bias to allow examining overall performance for scale.
*
* Currently, this benchmark will compare the following index options :
* - Unindexed
* - Adaptive Binary Indices (Lazy benchmarks can be uncommented if you wish those as well)
* - AVL Indexes based on self-balancing AVL binary search trees
*/
let Loki = require('../build/packages/loki/lokidb.loki.js').default,
crypto = require("crypto"); // for less 'leaky' random string generation
/**
* Generate random string using node cryto lib for less memory 'leaky' behavior than js string construction
*/
function genRandomVal() {
return crypto.randomBytes(50).toString('hex');
}
/**
* Helper method to shuffle array
* @param {*} array
*/
function shuffle(array) {
let currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
/**
* Helper method to convert number of bytes into more readable representation.
* @param {*} bytes
* @param {*} decimals
*/
function formatBytes(bytes, decimals) {
if (bytes == 0) return '0 Byte';
let k = 1000; // or 1024 for binary
let dm = decimals + 1 || 3;
let sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
/**
* Logs memory usage info to console
* @param {*} msg
*/
function logMemoryUsage(msg) {
let pmu = process.memoryUsage();
console.log(msg + " => rss : " + formatBytes(pmu.rss) + " heapTotal : " + formatBytes(pmu.heapTotal) + " heapUsed : " + formatBytes(pmu.heapUsed));
}
/**
* Helper method for instantiating a loki database
* @param {*} mode indexing mode ("none", "avl")
*/
function createDatabase(mode) {
let tdb = new Loki("temp.db");
let coll;
switch (mode) {
case "avl":
coll = tdb.addCollection('perfcoll', {
rangedIndexes: {
"customId": { indexTypeName: "avl", comparatorName: "js" }
}
});
break;
case "none":
default:
coll = tdb.addCollection('perfcoll');
break;
}
return tdb;
}
/**
* Helper method for populating a collection
* @param {*} db loki database instance containing collection to populate
* @param {*} count number of documents to insert
*/
function populateDatabase(db, count) {
let coll = db.getCollection("perfcoll");
// populate collection
let idxbuf = [];
let customIdx, v1;
for (let idx = 0; idx < count; idx++) {
customIdx = count - idx;
idxbuf.push(customIdx);
v1 = genRandomVal();
coll.insert({
customId: customIdx,
val: v1,
val2: "more data 1234567890"
});
}
return idxbuf;
}
/**
* Profiles memory usage for unindexed and avl indexed collections
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count
*/
function profileDatabaseMemory(mode, count) {
let mdb = createDatabase(mode);
populateDatabase(mdb, count);
let coll = mdb.getCollection("perfcoll");
let id, v1;
for (let idx = 0; idx < 100000; idx++) {
id = count - idx;
v1 = genRandomVal();
coll.insert({
customId: id,
val1: v1,
val2: "more data 1234567890"
});
}
logMemoryUsage(mode);
}
/**
* Benchmarks insertion rates for unindexed and avl indexed collections
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count
*/
function profileInsertion(mode, count) {
let mdb = createDatabase(mode);
let coll = mdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
// populate collection manually instead of helper since we won't retain idxbuf
let customIdx, v1;
for (let idx = 0; idx < count; idx++) {
customIdx = count - idx;
v1 = genRandomVal();
start = process.hrtime();
coll.insert({
customId: customIdx,
val: v1,
val2: "more data 1234567890"
});
end = process.hrtime(start);
totalTimes.push(end);
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("insertion rate (" + mode + ") : " + totalMS + "ms (" + rate + " ops/s) " + count + " documents");
}
/**
* Benchmarks find performance for given document count (not multiplied to show raw ms perf)
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count
*/
function perfFind(mode, count) {
let fdb = createDatabase(mode);
let idxbuf = populateDatabase(fdb, count);
let coll = fdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let customIdx, results;
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf[idx];
start = process.hrtime();
results = coll.find({
'customId': customIdx
});
end = process.hrtime(start);
totalTimes.push(end);
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("random coll.find() : " + totalMS + "ms (" + rate + " ops/s) " + count + " iterations");
}
/**
* Benchmarks interlacing insert + find (on indexed column) to measure index thrashing
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count
*/
function perfFindInterlacedInserts(mode, count) {
let fdb = createDatabase(mode);
let idxbuf = [];
let coll = fdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let customIdx, results;
for (let idx = 0; idx < count; idx++) {
customIdx = count - idx;
start = process.hrtime();
// insert record with id outside range of pre-populated records
coll.insert({
customId: customIdx,
val: 999,
val2: 999,
val3: "more data 1234567890"
});
// do quick find of object just inserted
results = coll.find({
'customId': customIdx
});
end = process.hrtime(start);
totalTimes.push(end);
if (results.length !== 1 || results[0].customId !== customIdx) {
console.log("(interlaced inserts) unexpected results")
}
}
if (coll.find().length !== count) {
console.log("(interlaced inserts) unexpected total inserted document count");
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("interlaced inserts + coll.find() : " + totalMS + "ms (" + rate + " ops/s) " + count + " iterations");
}
/**
* Benchmarks interlacing find + remove (on indexed column) to measure index thrashing
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count
*/
function perfFindInterlacedRemoves(mode, count, multiple) {
let fdb = createDatabase(mode);
let idxbuf = populateDatabase(fdb, count);
let coll = fdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let removeId, result;
for (let idx = 0; idx < count; idx++) {
removeId = idxbuf.pop();
start = process.hrtime();
result = coll.findOne({
'customId': removeId
});
coll.remove(result);
end = process.hrtime(start);
totalTimes.push(end);
}
if (coll.find().length !== 0) {
console.log("(interlaces removes) unexpected final doc count");
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("interlaced removes + coll.find() : " + totalMS + "ms (" + rate + " ops/s) " + count + " iterations");
}
/**
* Benchmarks interlacing find + update (on indexed column) to measure index thrashing
* @param {*} mode indexing mode ("none", "avl")
* @param {*} count number of interlaced finds+updates to perform
*/
function perfFindInterlacesUpdates(mode, count) {
let fdb = createDatabase(mode);
let idxbuf = populateDatabase(fdb, count);
let coll = fdb.getCollection("perfcoll");
let start, end;
let totalTimes = [];
let totalMS = 0;
let customIdx, newIdx, result;
for (let idx = 0; idx < count; idx++) {
customIdx = idxbuf.pop();
newIdx = count + idx;
start = process.hrtime();
// lookup next doc
result = coll.findOne({
'customId': customIdx
});
// update doc, modifying the field (potentially) being indexed
result.customId = newIdx;
coll.update(result);
end = process.hrtime(start);
totalTimes.push(end);
}
if (coll.find().length !== count) {
console.log("(interlaced updates) unexpected final doc count");
}
for (let idx = 0; idx < totalTimes.length; idx++) {
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1] / 1e6;
}
totalMS = totalMS.toFixed(2);
let rate = count * 1000 / totalMS;
rate = rate.toFixed(2);
console.log("interlaced updates + coll.find() : " + totalMS + "ms (" + rate + " ops/s) " + count + " iterations");
}
/**
* Attempt to free up global variables and invoke node garbage collector (if enabled)
*/
function cleanup() {
if (global.gc) {
global.gc();
}
}
let memoryProfileSteps = [
cleanup,
() => logMemoryUsage("baseline"),
() => profileDatabaseMemory("unindexed", 10000),
cleanup,
() => logMemoryUsage("baseline"),
() => profileDatabaseMemory("avl", 10000)
];
let insertionProfileSteps = [
// Unindexed Inserts
cleanup,
() => console.log("no index"),
() => profileInsertion("none", 100000),
// AVL indexed inserts
cleanup,
() => console.log("avl tree index"),
() => profileInsertion("avl", 100000)
];
let nightmareUnindexedLowSteps = [
() => {
console.log("");
console.log("------------ Beginning Nightmare Benchmarks ------------");
console.log("Nightmare tests combine a find() with either an insert(), update(), or remove()");
console.log("to remove any bias and show weaknesses that each indexing strategy may be leveraging, ");
console.log("such as placing all emphasis on find() performance to detriment of index maintenance costs.");
console.log("");
},
() => {
console.log("Perf: Unindexed Nightmare (Lower Scale @ 5,000 docs/iterations) ------------------------");
createDatabase("none");
},
cleanup,
() => perfFind("none", 5000),
cleanup,
() => perfFindInterlacedInserts("none", 5000),
cleanup,
() => perfFindInterlacedRemoves("none", 5000),
cleanup,
() => perfFindInterlacesUpdates("none", 5000)
];
let nightmareUnindexedHighSteps = [
() => {
console.log("Perf: Unindexed Nightmare (Higher Scale @ 10,000 docs/iterations) ------------------------");
createDatabase("none");
},
cleanup,
() => perfFind("none", 10000),
cleanup,
() => perfFindInterlacedInserts("none", 10000),
cleanup,
() => perfFindInterlacedRemoves("none", 10000),
cleanup,
() => perfFindInterlacesUpdates("none", 10000),
];
let nightmareAvlLowSteps = [
() => console.log("Perf: AVL Indexed Nightmare (Lower Scale @ 40,000 docs/iterations) ---"),
cleanup,
() => perfFind("avl", 40000),
cleanup,
() => perfFindInterlacedInserts("avl", 40000),
cleanup,
() => perfFindInterlacedRemoves("avl", 40000),
cleanup,
() => perfFindInterlacesUpdates("avl", 40000),
];
let nightmareAvlHighSteps = [
() => console.log("Perf: AVL Indexed Nightmare (Higher Scale @ 100,000 docs/iterations) ---"),
cleanup,
() => perfFind("avl", 100000),
cleanup,
() => perfFindInterlacedInserts("avl", 100000),
cleanup,
() => perfFindInterlacedRemoves("avl", 100000),
cleanup,
() => perfFindInterlacesUpdates("avl", 100000)
];
let perfGroups = [
//{ name: "Memory Profiling of database with various indexing", steps: memoryProfileSteps },
//{ name: "Document Insertion rates with various indexes", steps: insertionProfileSteps },
{ name: "Nightmare Unindexed (Low Range)", steps: nightmareUnindexedLowSteps },
{ name: "Nightmare Unindexed (High Range)", steps: nightmareUnindexedHighSteps },
{ name: "Nightmare AVL Index (Low Range)", steps: nightmareAvlLowSteps },
{ name: "Nightmare AVL Index (High Range)", steps: nightmareAvlHighSteps }
];
function execSteps(steps) {
if (steps.length === 0) {
setTimeout(execGroups, 4000);
return;
}
let s = steps.shift();
s();
setTimeout(() => { execSteps(steps); }, 1000);
}
function execGroups() {
let g = perfGroups.shift();
if (!g) return;
cleanup();
console.log("");
console.log("## " + g.name + " ##");
console.log("");
execSteps(g.steps);
}
if (!global.gc) {
console.warn("##");
console.warn("## IMPORTANT! : For accuracy of results, launch node with --expose-gc flag");
console.warn("##");
}
console.log("");
console.log("Note: run 'npm run build' before benchmarking after getting latest or modifying code");
console.log("");
execGroups();
================================================
FILE: config/jasmine.json
================================================
{
"spec_dir": "packages/*/spec",
"spec_files": [
"generic/**/*.spec.[jt]s",
"node/**/*.spec.[jt]s"
],
"helpers": [
"../../../node_modules/ts-node/register/index.js",
"../../../node_modules/jasmine-expect/index.js",
"../../common/spec/helper/**/*helper.[jt]s",
"helper/**/*.[jt]s"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
================================================
FILE: config/karma.config.js
================================================
/* global process, require, module, require */
const path = require("path");
module.exports = function (config) {
const configuration = {
frameworks: ["jasmine", "jasmine-matchers"],
browsers: ["ChromeHeadless"],
basePath: "../",
files: [
{pattern: "packages/*/spec/generic/**/*.spec.ts", watched: false},
{pattern: "packages/*/spec/web/**/*.spec.ts", watched: false}
],
preprocessors: {
"packages/*/spec/generic/**/*.spec.ts": ["webpack"],
"packages/*/spec/web/**/*.spec.ts": ["webpack"]
},
// coverage reporter generates the coverage
reporters: ["progress", "coverage-istanbul"],
coverageIstanbulReporter: {
dir: "coverage/karma/",
reports: ["text-summary", "json"],
fixWebpackSourcePaths: true
},
mime: {
"text/x-typescript": ["ts"]
},
webpack: {
mode: "development",
stats: 'errors-only',
resolve: {
extensions: [".ts"],
},
devtool: "source-map",
module: {
rules: [
{
enforce: "pre",
test: /\.ts$/,
loader: "tslint-loader",
exclude: /node_modules/,
options: {
failOnHint: false,
configFile: path.join(__dirname, "tslint.json"),
}
},
{
test: /\.ts$/,
loader: "ts-loader",
options: {
configFile: path.join(__dirname, "tsconfig.webpack.json")
}
},
{
enforce: "post",
exclude: [
/node_modules/,
/\.spec\.ts$/,
/.*\/spec\/.+\.ts/,
/\.helper\.ts$/,
/.*\/helper\/.+\.ts/
],
loader: "istanbul-instrumenter-loader?esModules=true",
test: /\.ts$/
}
]
}
},
webpackMiddleware: {
logLevel: "warn"
},
plugins: [
"karma-chrome-launcher",
"karma-coverage-istanbul-reporter",
"karma-jasmine",
"karma-jasmine-matchers",
"karma-webpack",
],
};
config.set(configuration);
};
================================================
FILE: config/nycrc.json
================================================
{
"reporter": [
"text-summary",
"html"
],
"report-dir": "./coverage/",
"temp-directory": "./coverage/"
}
================================================
FILE: config/nycrc.node.json
================================================
{
"extension": [
".ts"
],
"reporter": [
"text-summary",
"json"
],
"exclude": [
"**/*.helper.[jt]s",
"**/*.spec.[jt]s",
"**/spec/**/*.[jt]s"
],
"report-dir": "./coverage/node/"
}
================================================
FILE: config/tsconfig.tslint.json
================================================
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "../types/",
"sourceMap": true,
"declaration": true,
"moduleResolution": "classic",
"strictPropertyInitialization": true,
"alwaysStrict": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es6",
"lib": [
"es2017"
],
"typeRoots": [
"node_modules/@types"
],
"types": [
"jasmine",
"jasmine-expect",
"node"
]
},
"include": [
"../packages/**/*.ts"
]
}
================================================
FILE: config/tsconfig.webpack.json
================================================
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "../types/",
"sourceMap": true,
"declaration": true,
"moduleResolution": "classic",
"strictPropertyInitialization": true,
"alwaysStrict": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es6",
"lib": [
"es2017",
"dom"
],
"typeRoots": [
"node_modules/@types"
],
"types": [
"jasmine",
"jasmine-expect",
"node"
]
},
"include": [
"../packages/*/src/**/*.ts"
]
}
================================================
FILE: config/tslint.json
================================================
{
"rulesDirectory": [
"../node_modules/vrsource-tslint-rules/rules",
"../node_modules/tslint-eslint-rules/dist/rules"
],
"extends": [
"tslint-eslint-rules"
],
"rules": {
"no-console": [true, "log"],
"no-duplicate-imports": true,
"no-duplicate-variable": true,
"no-jasmine-focus": true,
"no-var-keyword": true,
"semicolon": [true],
"variable-name": [true, "ban-keywords"],
"no-inner-declarations": [true, "function"],
"quotemark": [true, "double"],
"eofline": true,
"ter-indent": [true, 2, {
"SwitchCase": 1
}],
"whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator",
"check-rest-spread", "check-type", "check-type", "check-typecast", "check-type-operator", "check-preblock"],
"no-trailing-whitespace": true
}
}
================================================
FILE: config/webpack-config-creator.js
================================================
/* global __dirname, module, require */
const path = require("path");
module.exports = (options) => {
if (options.entry === undefined) {
throw Error("options.entry must be specified.")
}
if (options.filename === undefined) {
throw Error("options.Filename must be specified.")
}
if (options.library === undefined) {
throw Error("options.library must be specified.")
}
return {
mode: "production",
entry: options.entry,
output: {
filename: options.filename,
library: options.library,
libraryTarget: "umd2",
umdNamedDefine: true,
globalObject: "typeof self !== 'undefined' ? self : this"
},
externals: options.externals,
resolve: {
extensions: [".ts"]
},
devtool: "source-map",
module: {
rules: [
{
enforce: "pre",
test: /\.ts$/,
loader: "tslint-loader",
exclude: /node_modules/,
options: {
failOnHint: true,
configFile: path.join("config", "tslint.json"),
}
},
{
test: /\.ts$/,
loader: "ts-loader",
options: {
configFile: path.join("config", "tsconfig.webpack.json")
}
}
]
},
optimization: {
minimize: false
},
};
};
================================================
FILE: dist/packages/fs-storage/lokidb.fs-storage.js
================================================
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("fs"));
else if(typeof define === 'function' && define.amd)
define("@lokidb/fs-storage", ["fs"], factory);
else if(typeof exports === 'object')
exports["@lokidb/fs-storage"] = factory(require("fs"));
else
{ root["@lokidb/fs-storage"] = factory(root["fs"]); root["LokiFsStorage"] = root["@lokidb/fs-storage"].default; }
})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE__0__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 3);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__0__;
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PLUGINS; });
function getGlobal() {
let glob;
(function (global) {
glob = global;
})(global !== undefined && global || this);
return glob;
}
function create() {
const global = getGlobal();
const sym = Symbol.for("LOKI");
if (global[sym] === undefined) {
global[sym] = {};
}
return global[sym];
}
/**
* @hidden
*/
const PLUGINS = create();
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(2)))
/***/ }),
/* 2 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FSStorage", function() { return FSStorage; });
/* harmony import */ var _common_plugin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
/**
* A loki persistence adapter which persists using node fs module.
*/
class FSStorage {
/**
* Registers the fs storage as plugin.
*/
static register() {
_common_plugin__WEBPACK_IMPORTED_MODULE_0__[/* PLUGINS */ "a"]["FSStorage"] = FSStorage;
}
/**
* Deregisters the fs storage as plugin.
*/
static deregister() {
delete _common_plugin__WEBPACK_IMPORTED_MODULE_0__[/* PLUGINS */ "a"]["FSStorage"];
}
/**
* Load data from file, will throw an error if the file does not exist
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname) {
return new Promise((resolve, reject) => {
fs__WEBPACK_IMPORTED_MODULE_1__["stat"](dbname, (err, stats) => {
if (!err && stats.isFile()) {
fs__WEBPACK_IMPORTED_MODULE_1__["readFile"](dbname, {
encoding: "utf8"
}, function readFileCallback(err, data) {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
}
else {
reject(null);
}
});
});
}
/**
* Save data to file, will throw an error if the file can't be saved
* might want to expand this to avoid dataloss on partial save
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname, dbstring) {
const tmpdbname = dbname + "~";
return new Promise((resolve, reject) => {
fs__WEBPACK_IMPORTED_MODULE_1__["writeFile"](tmpdbname, dbstring, (err) => {
if (err) {
reject(err);
}
else {
fs__WEBPACK_IMPORTED_MODULE_1__["rename"](tmpdbname, dbname, (err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
}
});
});
}
/**
* Delete the database file, will throw an error if the
* file can't be deleted
* @param {string} dbname - the filename of the database to delete
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname) {
return new Promise((resolve, reject) => {
fs__WEBPACK_IMPORTED_MODULE_1__["unlink"](dbname, function deleteDatabaseCallback(err) {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
}
}
/***/ })
/******/ ]);
});
//# sourceMappingURL=lokidb.fs-storage.js.map
================================================
FILE: dist/packages/fs-storage/types/common/plugin.d.ts
================================================
/**
* @hidden
*/
export declare const PLUGINS: void;
================================================
FILE: dist/packages/fs-storage/types/common/types.d.ts
================================================
/**
* @hidden
*/
import { Loki } from "../loki/src/loki";
export interface StorageAdapter {
loadDatabase(dbname: string): Promise;
saveDatabase?(dbname: string, serialization: string): Promise;
deleteDatabase?(dbname: string): Promise;
mode?: string;
exportDatabase?(dbname: string, dbref: Loki): Promise;
}
export declare type Doc = T & {
$loki: number;
meta?: {
created: number;
revision: number;
version: number;
updated?: number;
};
};
export interface Dict {
[index: string]: T;
[index: number]: T;
}
================================================
FILE: dist/packages/fs-storage/types/fs-storage/src/fs_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* A loki persistence adapter which persists using node fs module.
*/
export declare class FSStorage implements StorageAdapter {
/**
* Registers the fs storage as plugin.
*/
static register(): void;
/**
* Deregisters the fs storage as plugin.
*/
static deregister(): void;
/**
* Load data from file, will throw an error if the file does not exist
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* Save data to file, will throw an error if the file can't be saved
* might want to expand this to avoid dataloss on partial save
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* Delete the database file, will throw an error if the
* file can't be deleted
* @param {string} dbname - the filename of the database to delete
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
}
================================================
FILE: dist/packages/fs-storage/types/fs-storage/src/index.d.ts
================================================
import { FSStorage } from "./fs_storage";
export { FSStorage };
export default FSStorage;
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/analyzer/analyzer.d.ts
================================================
import { CharacterFilter } from "./character_filter";
import { Tokenizer, whitespaceTokenizer } from "./tokenizer";
import { lowercaseTokenFilter, TokenFilter } from "./token_filter";
/**
* A analyzer converts a string into tokens which are added to the inverted index for searching.
*/
export interface Analyzer {
/**
* The character filters of the analyzer.
*/
char_filter?: CharacterFilter[];
/**
* The tokenizer of the analyzer.
*/
tokenizer: Tokenizer;
/**
* The token filters of the analyzer.
*/
token_filter?: TokenFilter[];
}
/**
* Analyzes a given string.
* @param {Analyzer} analyzer - the analyzer
* @param {string} str - the string
* @returns {string[]} - the tokens
*/
export declare function analyze(analyzer: Analyzer, str: string): string[];
/**
* An analyzer with the whitespace tokenizer and the lowercase token filter.
*/
export declare class StandardAnalyzer implements Analyzer {
tokenizer: typeof whitespaceTokenizer;
token_filter: (typeof lowercaseTokenFilter)[];
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/analyzer/character_filter.d.ts
================================================
/**
* A character filter is used to preprocess a string before it is passed to a tokenizer.
*/
export declare type CharacterFilter = (value: string) => string;
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/analyzer/token_filter.d.ts
================================================
/**
* A token filter takes tokens from a tokenizer and modify, delete or add tokens.
*/
export declare type TokenFilter = (value: string, index: number, array: string[]) => string;
/**
* Converts a token to lowercase.
* @param {string} token - the token
* @returns {string} - the lowercased token
*/
export declare function lowercaseTokenFilter(token: string): string;
/**
* Converts a token to uppercase.
* @param {string} token - the token
* @returns {string} - the uppercased token
*/
export declare function uppercaseTokenFilter(token: string): string;
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/analyzer/tokenizer.d.ts
================================================
/**
* A tokenizer splits a string into individual tokens.
*/
export declare type Tokenizer = (value: string) => string[];
/**
* Splits a string at whitespace characters into tokens.
* @param {string} value - the string
* @returns {string[]} - the tokens
*/
export declare function whitespaceTokenizer(value: string): string[];
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/full_text_search.d.ts
================================================
import { InvertedIndex } from "./inverted_index";
import { Dict } from "../../common/types";
import { Query } from "./query_types";
import { Scorer } from "./scorer";
import { Analyzer } from "./analyzer/analyzer";
export declare class FullTextSearch {
private _id;
private _docs;
private _idxSearcher;
private _invIdxs;
/**
* Registers the full-text search as plugin.
*/
static register(): void;
/**
* Initialize the full-text search for the given fields.
* @param {object[]} fieldOptions - the field options
* @param {string} fieldOptions.field - the name of the property field
* @param {boolean=true} fieldOptions.store - flag to indicate if the full-text search should be stored on serialization or
* rebuild on deserialization
* @param {boolean=true} fieldOptions.optimizeChanges - flag to optimize updating and deleting of documents
* (requires more memory but performs faster)
* @param {Analyzer} fieldOptions.analyzer - an analyzer for the field
* @param {string} [id] - the property name of the document index
*/
constructor(fieldOptions?: FullTextSearch.FieldOptions[], id?: string);
addDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
removeDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
updateDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
clear(): void;
search(query: Query): Scorer.ScoreResults;
toJSON(): FullTextSearch.Serialization;
static fromJSONObject(serialized: FullTextSearch.Serialization, analyzers?: Dict): FullTextSearch;
}
export declare namespace FullTextSearch {
interface FieldOptions extends InvertedIndex.FieldOptions {
field: string;
}
interface Serialization {
id: string;
ii: Dict;
}
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/automaton.d.ts
================================================
/**
* Transition with dest, min and max.
* @hidden
*/
export declare type Transition = [number, number, number];
/**
* @type {number}
* @hidden
*/
export declare const MIN_CODE_POINT = 0;
/**
* @type {number}
* @hidden
*/
export declare const MAX_CODE_POINT = 1114111;
/**
* From org/apache/lucene/util/automaton/Automaton.java
* @hidden
*/
export declare class Automaton {
private _stateTransitions;
private _accept;
private _nextState;
private _currState;
private _transitions;
constructor();
isAccept(n: number): boolean;
createState(): number;
setAccept(state: number, accept: boolean): void;
finishState(): void;
private _finishCurrentState();
getStartPoints(): number[];
step(state: number, label: number): number;
getNumStates(): number;
addTransition(source: number, dest: number, min: number, max: number): void;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/lev1t_parametric_description.d.ts
================================================
import { ParametricDescription } from "./parametric_description";
/**
* From org/apache/lucene/util/automaton/Lev1TParametricDescription.java
* @hidden
*/
export declare class Lev1TParametricDescription extends ParametricDescription {
constructor(w: number);
transition(absState: number, position: number, vector: number): number;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/lev2t_parametric_description.d.ts
================================================
import { ParametricDescription } from "./parametric_description";
/**
* From org/apache/lucene/util/automaton/Lev2TParametricDescription.java
* @hidden
*/
export declare class Lev2TParametricDescription extends ParametricDescription {
constructor(w: number);
transition(absState: number, position: number, vector: number): number;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/levenshtein_automata.d.ts
================================================
import { Automaton } from "./automaton";
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java
* @hidden
*/
export declare class LevenshteinAutomata {
private _word;
private _numRanges;
private _rangeLower;
private _rangeUpper;
private _description;
private _alphabet;
private _editDistance;
constructor(input: number[], editDistance: number);
/**
* Transforms the NDFA to a DFA.
* @returns {Automaton}
*/
toAutomaton(): Automaton;
private _getVector(x, pos, end);
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/long.d.ts
================================================
/**
* Class supports 64Bit integer operations.
* A cut-down version of dcodeIO/long.js.
* @hidden
*/
export declare class Long {
private _low;
private _high;
constructor(low?: number, high?: number);
/**
* Returns this long with bits arithmetically shifted to the right by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftRight(numBits: number): Long;
/**
* Returns this long with bits arithmetically shifted to the left by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftLeft(numBits: number): Long;
/**
* Returns the bitwise AND of this Long and the specified.
* @param {Long} other - the other Long
* @returns {Long} the long
*/
and(other: Long): Long;
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
* @returns {number}
*/
toInt(): number;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/parametric_description.d.ts
================================================
import { Long } from "./long";
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java#ParametricDescription
* @hidden
*/
export declare class ParametricDescription {
protected _w: number;
private _n;
private _minErrors;
constructor(w: number, n: number, minErrors: number[]);
/**
* Return the number of states needed to compute a Levenshtein DFA
*/
size(): number;
/**
* Returns true if the state in any Levenshtein DFA is an accept state (final state).
*/
isAccept(absState: number): boolean;
/**
* Returns the position in the input word for a given state.
* This is the minimal boundary for the state.
*/
getPosition(absState: number): number;
static unpack(data: Long[], index: number, bitsPerValue: number): number;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/fuzzy/run_automaton.d.ts
================================================
import { Automaton } from "./automaton";
/**
* From org/apache/lucene/util/automaton/RunAutomaton.java
* @hidden
*/
export declare class RunAutomaton {
private _points;
private _accept;
private _transitions;
private _classmap;
constructor(automaton: Automaton);
getCharClass(c: number): number;
step(state: number, c: number): number;
isAccept(state: number): boolean;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/index.d.ts
================================================
import { FullTextSearch } from "./full_text_search";
import { analyze, StandardAnalyzer } from "./analyzer/analyzer";
import { whitespaceTokenizer } from "./analyzer/tokenizer";
import { lowercaseTokenFilter, uppercaseTokenFilter } from "./analyzer/token_filter";
export { FullTextSearch, analyze, StandardAnalyzer, whitespaceTokenizer, lowercaseTokenFilter, uppercaseTokenFilter };
export default FullTextSearch;
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/index_searcher.d.ts
================================================
import { Scorer } from "./scorer";
import { InvertedIndex } from "./inverted_index";
import { Query } from "./query_types";
import { Dict } from "../../common/types";
/**
* @hidden
*/
export declare class IndexSearcher {
private _invIdxs;
private _docs;
private _scorer;
/**
* Constructs an index searcher.
* @param {Dict} invIdxs - the inverted indexes
* @param {Set} docs - the ids of the documents
*/
constructor(invIdxs: Dict, docs: Set);
search(query: Query): Scorer.ScoreResults;
setDirty(): void;
private _recursive(query, doScoring);
private _getUnique(queries, doScoring, queryResults);
private _getAll(queries, doScoring, queryResults?);
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/inverted_index.d.ts
================================================
import { Analyzer } from "./analyzer/analyzer";
/**
* Converts a string into an array of code points.
* @param str - the string
* @returns {number[]} to code points
* @hidden
*/
export declare function toCodePoints(str: string): number[];
/**
* Inverted index class handles featured text search for specific document fields.
* @hidden
*/
export declare class InvertedIndex {
analyzer: Analyzer;
docCount: number;
docStore: Map;
totalFieldLength: number;
root: InvertedIndex.Index;
private _store;
private _optimizeChanges;
/**
* @param {boolean} [options.store=true] - inverted index will be stored at serialization rather than rebuilt on load
* @param {boolean} [options.optimizeChanges=true] - flag to store additional metadata inside the index for better
* performance if an existing field is updated or removed
* @param {Analyzer} [options.analyzer=] - the analyzer of this inverted index
*/
constructor(options?: InvertedIndex.FieldOptions);
/**
* Adds defined fields of a document to the inverted index.
* @param {string} field - the field to add
* @param {number} docId - the doc id of the field
*/
insert(field: string, docId: InvertedIndex.DocumentIndex): void;
/**
* Removes all relevant terms of a document from the inverted index.
* @param {number} docId - the document.
*/
remove(docId: InvertedIndex.DocumentIndex): void;
/**
* Gets the term index of a term.
* @param {string} term - the term
* @param {object} root - the term index to start from
* @param {number} start - the position of the term string to start from
* @return {object} - The term index or null if the term is not in the term tree.
*/
static getTermIndex(term: number[], root: InvertedIndex.Index, start?: number): InvertedIndex.Index;
/**
* Extends a term index to all available term leafs.
* @param {object} idx - the term index to start from
* @param {number[]} [term=[]] - the current term
* @param {Array} termIndices - all extended indices with their term
* @returns {Array} - Array with term indices and extension
*/
static extendTermIndex(idx: InvertedIndex.Index, term?: number[], termIndices?: InvertedIndex.IndexTerm[]): InvertedIndex.IndexTerm[];
/**
* Serialize the inverted index.
* @returns {{docStore: *, _fields: *, index: *}}
*/
toJSON(): InvertedIndex.Serialization;
/**
* Deserialize the inverted index.
* @param {{docStore: *, _fields: *, index: *}} serialized - The serialized inverted index.
* @param {Analyzer} analyzer[undefined] - an analyzer
*/
static fromJSONObject(serialized: InvertedIndex.Serialization, analyzer?: Analyzer): InvertedIndex;
private static _serializeIndex(idx);
private static _deserializeIndex(serialized);
/**
* Set parent of to each index and regenerate the indexRef.
* @param {Index} index - the index
* @param {Index} parent - the parent
*/
private _regenerate(index, parent);
/**
* Iterate over the whole inverted index and remove the document.
* Delete branch if not needed anymore.
* Function is needed if index is used without optimization.
* @param {Index} idx - the index
* @param {number} docId - the doc id
* @returns {boolean} true if index is empty
*/
private _remove(idx, docId);
}
export declare namespace InvertedIndex {
interface FieldOptions {
store?: boolean;
optimizeChanges?: boolean;
analyzer?: Analyzer;
}
type Index = Map & {
dc?: Map;
df?: number;
pa?: Index;
};
type IndexTerm = {
index: Index;
term: number[];
};
interface SerializedIndex {
d?: {
df: number;
dc: [DocumentIndex, number][];
};
k?: number[];
v?: SerializedIndex[];
}
type Serialization = SpareSerialization | FullSerialization;
type SpareSerialization = {
_store: false;
_optimizeChanges: boolean;
};
type FullSerialization = {
_store: true;
_optimizeChanges: boolean;
docCount: number;
docStore: [DocumentIndex, DocStore][];
totalFieldLength: number;
root: SerializedIndex;
};
interface DocStore {
fieldLength?: number;
indexRef?: Index[];
}
type DocumentIndex = number | string;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/query_types.d.ts
================================================
/**
* Base query to enable boost to a query type.
*/
export interface BaseQuery {
type: Type;
boost?: number;
}
/**
* A query which finds documents where a document field contains a term.
*/
export interface TermQuery extends BaseQuery<"term"> {
field: string;
value: string;
}
/**
* A query which finds documents where a document field contains any of the terms.
*/
export interface TermsQuery extends BaseQuery<"terms"> {
field: string;
value: string[];
}
/**
* A query which finds documents where the wildcard term can be applied at an existing document field term.
*/
export interface WildcardQuery extends BaseQuery<"wildcard"> {
field: string;
value: string;
enable_scoring?: boolean;
}
/**
* A query which finds documents where the fuzzy term can be transformed into an existing document field term within a
* given edit distance.
*/
export interface FuzzyQuery extends BaseQuery<"fuzzy"> {
field: string;
value: string;
fuzziness?: 0 | 1 | 2 | "AUTO";
prefix_length?: number;
extended?: boolean;
}
/**
* A query which matches documents containing the prefix of a term inside a field.
*/
export interface PrefixQuery extends BaseQuery<"prefix"> {
field: string;
value: string;
enable_scoring?: boolean;
}
/**
* A query which matches all documents with a given field.
*/
export interface ExistsQuery extends BaseQuery<"exists"> {
field: string;
}
/**
* A query which tokenizes the given text into tokens and performs a sub query for each token. The results are combined
* using a boolean operator.
*/
export interface MatchQuery extends BaseQuery<"match"> {
field: string;
value: string;
minimum_should_match?: number | string;
operator?: "and" | "or";
fuzziness?: 0 | 1 | 2 | "AUTO";
prefix_length?: number;
extended?: boolean;
}
/**
* A query that matches all documents and giving them a constant score equal to the query boost.
*/
export interface MatchQueryAll extends BaseQuery<"match_all"> {
}
/**
* A query that wraps sub queries and returns a constant score equal to the query boost for every document in the filter.
*/
export interface ConstantScoreQuery extends BaseQuery<"constant_score"> {
filter: QueryTypes[];
}
/**
* A query that matches documents matching boolean combinations of sub queries.
*/
export interface BoolQuery extends BaseQuery<"bool"> {
must?: QueryTypes[];
filter?: QueryTypes[];
should?: QueryTypes[];
not?: QueryTypes[];
minimum_should_match?: number | string;
}
/**
* Union type of possible query types.
*/
export declare type QueryTypes = BoolQuery | ConstantScoreQuery | TermQuery | TermsQuery | WildcardQuery | FuzzyQuery | MatchQuery | MatchQueryAll | PrefixQuery | ExistsQuery;
/**
* The main query with the actually full-text search query and the scoring parameters.
*/
export interface Query {
query: QueryTypes;
calculate_scoring?: boolean;
explain?: boolean;
bm25?: {
k1: number;
b: number;
};
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search/src/scorer.d.ts
================================================
import { InvertedIndex } from "./inverted_index";
import { Dict } from "../../common/types";
import { Query } from "./query_types";
/**
* @hidden
*/
export declare class Scorer {
private _invIdxs;
private _cache;
constructor(invIdxs: Dict);
setDirty(): void;
score(fieldName: string, boost: number, termIdx: InvertedIndex.Index, doScoring: boolean | null, queryResults: Scorer.QueryResults, term: number[], df?: number): void;
scoreConstant(boost: number, docId: InvertedIndex.DocumentIndex, queryResults: Scorer.QueryResults): Scorer.QueryResults;
finalScore(query: Query, queryResults: Scorer.QueryResults): Scorer.ScoreResults;
private static _calculateFieldLength(fieldLength);
private _getCache(fieldName);
/**
* Returns the idf by either calculate it or use a cached one.
* @param {string} fieldName - the name of the field
* @param {number} docFreq - the doc frequency of the term
* @returns {number} the idf
* @private
*/
private _idf(fieldName, docFreq);
private _avgFieldLength(fieldName);
}
export declare namespace Scorer {
interface IDFCache {
idfs: Dict;
avgFieldLength: number;
}
interface QueryResult {
tf?: number;
idf?: number;
boost: number;
fieldName?: string;
term?: number[];
}
type QueryResults = Map;
interface BM25Explanation {
boost: number;
score: number;
docID: number;
fieldName: string;
index: string;
idf: number;
tfNorm: number;
tf: number;
fieldLength: number;
avgFieldLength: number;
}
interface ConstantExplanation {
boost: number;
score: number;
}
type ScoreExplanation = BM25Explanation | ConstantExplanation;
type ScoreResult = {
score: number;
explanation?: ScoreExplanation[];
};
type ScoreResults = Dict;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language/src/index.d.ts
================================================
export { generateStopWordFilter, generateTrimmer, Among, SnowballProgram } from "./language";
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language/src/language.d.ts
================================================
export declare function generateTrimmer(wordCharacters: string): (token: string) => string;
export declare function generateStopWordFilter(stopWords: string[]): (token: string) => string;
export declare class Among {
s_size: number;
s: number[];
substring_i: number;
result: number;
method: any;
constructor(s: string, substring_i: number, result: number, method?: any);
}
export declare class SnowballProgram {
current: string;
bra: number;
ket: number;
limit: number;
cursor: number;
limit_backward: number;
constructor();
setCurrent(word: string): void;
getCurrent(): string;
in_grouping(s: number[], min: number, max: number): boolean;
in_grouping_b(s: number[], min: number, max: number): boolean;
out_grouping(s: number[], min: number, max: number): boolean;
out_grouping_b(s: number[], min: number, max: number): boolean;
eq_s(s_size: number, s: string): boolean;
eq_s_b(s_size: number, s: string): boolean;
find_among(v: Among[], v_size: number): number;
find_among_b(v: Among[], v_size: number): number;
replace_s(c_bra: number, c_ket: number, s: string): number;
slice_check(): void;
slice_from(s: string): void;
slice_del(): void;
insert(c_bra: number, c_ket: number, s: string): void;
slice_to(): string;
eq_v_b(s: string): boolean;
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language-de/src/german_analyzer.d.ts
================================================
import { Analyzer } from "../../full-text-search/src/analyzer/analyzer";
export declare class GermanAnalyzer implements Analyzer {
tokenizer: (str: string) => string[];
token_filter: ((token: string) => string)[];
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language-de/src/index.d.ts
================================================
import { GermanAnalyzer } from "./german_analyzer";
export { GermanAnalyzer };
export default GermanAnalyzer;
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language-en/src/english_analyzer.d.ts
================================================
import { Analyzer } from "../../full-text-search/src/analyzer/analyzer";
export declare class EnglishAnalyzer implements Analyzer {
tokenizer: (str: string) => string[];
token_filter: ((token: string) => string)[];
}
================================================
FILE: dist/packages/fs-storage/types/full-text-search-language-en/src/index.d.ts
================================================
import { EnglishAnalyzer } from "./english_analyzer";
export { EnglishAnalyzer };
export default EnglishAnalyzer;
================================================
FILE: dist/packages/fs-storage/types/indexed-storage/src/index.d.ts
================================================
import { IndexedStorage } from "./indexed_storage";
export { IndexedStorage };
export default IndexedStorage;
================================================
FILE: dist/packages/fs-storage/types/indexed-storage/src/indexed_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* Loki persistence adapter class for indexedDb.
* This class fulfills abstract adapter interface which can be applied to other storage methods.
* Utilizes the included LokiCatalog app/key/value database for actual database persistence.
* IndexedDb storage is provided per-domain, so we implement app/key/value database to
* allow separate contexts for separate apps within a domain.
*/
export declare class IndexedStorage implements StorageAdapter {
private _appname;
private catalog;
/**
* Registers the indexed storage as plugin.
*/
static register(): void;
/**
* Deregisters the indexed storage as plugin.
*/
static deregister(): void;
/**
* @param {string} [appname=loki] - Application name context can be used to distinguish subdomains, "loki" by default
*/
constructor(appname?: string);
/**
* Retrieves a serialized db string from the catalog.
*
* @example
* // LOAD
* var idbAdapter = new LokiIndexedAdapter("finance");
* var db = new loki("test", { adapter: idbAdapter });
* db.base(function(result) {
* console.log("done");
* });
*
* @param {string} dbname - the name of the database to retrieve.
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise<{}>;
/**
* Saves a serialized db to the catalog.
*
* @example
* // SAVE : will save App/Key/Val as "finance"/"test"/{serializedDb}
* let idbAdapter = new LokiIndexedAdapter("finance");
* let db = new loki("test", { adapter: idbAdapter });
* let coll = db.addCollection("testColl");
* coll.insert({test: "val"});
* db.saveDatabase(); // could pass callback if needed for async complete
*
* @param {string} dbname - the name to give the serialized database within the catalog.
* @param {string} dbstring - the serialized db string to save.
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* Deletes a serialized db from the catalog.
*
* @example
* // DELETE DATABASE
* // delete "finance"/"test" value from catalog
* idbAdapter.deleteDatabase("test", function {
* // database deleted
* });
*
* @param {string} dbname - the name of the database to delete from the catalog.
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
/**
* Removes all database partitions and pages with the base filename passed in.
* This utility method does not (yet) guarantee async deletions will be completed before returning
*
* @param {string} dbname - the base filename which container, partitions, or pages are derived
*/
deleteDatabasePartitions(dbname: string): void;
/**
* Retrieves object array of catalog entries for current app.
*
* @example
* idbAdapter.getDatabaseList(function(result) {
* // result is array of string names for that appcontext ("finance")
* result.forEach(function(str) {
* console.log(str);
* });
* });
*
* @param {function} callback - should accept array of database names in the catalog for current app.
*/
getDatabaseList(callback: (names: string[]) => void): void;
/**
* Allows retrieval of list of all keys in catalog along with size
* @param {function} callback - (Optional) callback to accept result array.
*/
getCatalogSummary(callback: (entry: Entry[]) => void): void;
}
export interface Entry {
app: string;
key: string;
size: number;
}
export default IndexedStorage;
================================================
FILE: dist/packages/fs-storage/types/local-storage/src/index.d.ts
================================================
import { LocalStorage } from "./local_storage";
export { LocalStorage };
export default LocalStorage;
================================================
FILE: dist/packages/fs-storage/types/local-storage/src/local_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* A loki persistence adapter which persists to web browser's local storage object
* @constructor LocalStorageAdapter
*/
export declare class LocalStorage implements StorageAdapter {
/**
* Registers the local storage as plugin.
*/
static register(): void;
/**
* Deregisters the local storage as plugin.
*/
static deregister(): void;
/**
* loadDatabase() - Load data from localstorage
* @param {string} dbname - the name of the database to load
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* saveDatabase() - save data to localstorage, will throw an error if the file can't be saved
* might want to expand this to avoid dataloss on partial save
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was saved
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* deleteDatabase() - delete the database from localstorage, will throw an error if it
* can't be deleted
* @param {string} dbname - the filename of the database to delete
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
}
export default LocalStorage;
================================================
FILE: dist/packages/fs-storage/types/loki/src/avl_index.d.ts
================================================
import { IRangedIndex, IRangedIndexRequest } from "./ranged_indexes";
import { ILokiComparer } from "./comparators";
/**
* Treenode type for binary search tree (BST) implementation.
*
* To support duplicates, we may need to either repurpose parent to
* point to 'elder' sibling or add a siblingId to point to owner of
* node represented in tree.
*/
export declare type TreeNode = {
id: number;
value: T;
parent: number | null;
balance: number;
height: number;
left: number | null;
right: number | null;
siblings: number[];
};
export interface ITreeNodeHash {
[id: number]: TreeNode;
}
/**
* LokiDB AVL Balanced Binary Tree Index implementation.
* To support duplicates, we use siblings (array) in tree nodes.
* Basic AVL components guided by William Fiset tutorials at :
* https://github.com/williamfiset/data-structures/blob/master/com/williamfiset/datastructures/balancedtree/AVLTreeRecursive.java
* https://www.youtube.com/watch?v=g4y2h70D6Nk&list=PLDV1Zeh2NRsD06x59fxczdWLhDDszUHKt
*/
export declare class AvlTreeIndex implements IRangedIndex {
name: string;
comparator: ILokiComparer;
nodes: ITreeNodeHash;
apex: number | null;
/**
* Initializes index with property name and a comparer function.
*/
constructor(name: string, comparator: ILokiComparer);
backup(): AvlTreeIndex;
restore(tree: AvlTreeIndex): void;
/**
* Used for inserting a new value into the BinaryTreeIndex
* @param id Unique Id (such as $loki) to associate with value
* @param val Value to be indexed and inserted into binary tree
*/
insert(id: number, val: T): void;
/**
* Recursively inserts a treenode and re-balances if needed.
* @param current
* @param node
*/
insertNode(current: TreeNode, node: TreeNode): number;
/**
* Updates height and balance (calculation) for tree node
* @param node
*/
private updateBalance(node);
/**
* Balance the 'double left-heavy' condition
* @param node
*/
private leftLeftCase(node);
/**
* Balance the '(parent) left heavy, (child) right heavy' condition
* @param node
*/
private leftRightCase(node);
/**
* Balance the 'double right-heavy' condition
* @param node
*/
private rightRightCase(node);
/**
* Balance the '(parent) right heavy, (child) left heavy' condition
* @param node
*/
private rightLeftCase(node);
/**
* Left rotation of node. Swaps right child into current location.
* @param node
*/
private rotateLeft(node);
/**
* Right rotation of node. Swaps left child into current location.
* @param node
*/
private rotateRight(node);
/**
* Diagnostic method for examining tree contents and structure
* @param node
*/
getValuesAsTree(node?: TreeNode): any;
/**
* Updates a value, possibly relocating it, within binary tree
* @param id Unique Id (such as $loki) to associate with value
* @param val New value to be indexed within binary tree
*/
update(id: number, val: T): void;
/**
* Removes a value from the binary tree index
* @param id
*/
remove(id: number): void;
/**
* Recursive node removal and rebalancer
* @param node
* @param val
*/
private removeNode(node, id);
/**
* Utility method for updating a parent's child link when it changes
* @param parentId
* @param oldChildId
* @param newChildId
*/
private updateChildLink(parentId, oldChildId, newChildId);
/**
* When removing a parent with only child, this does simple remap of child to grandParent.
* @param grandParent New parent of 'child'.
* @param parent Node being removed.
* @param child Node to reparent to grandParent.
*/
private promoteChild(parent, child);
/**
* Finds a successor to a node and replaces that node with it.
* @param node
*/
private promoteSuccessor(node);
/**
* Utility method for finding In-Order predecessor to the provided node
* @param node Parent node to find leaf node of greatest 'value'
*/
private findGreaterLeaf(node);
/**
* Utility method for finding In-Order successor to the provided node
* @param node Parent Node to find leaf node of least 'value'
*/
private findLesserLeaf(node);
/**
* Interface method to support ranged queries. Results sorted by index property.
* @param range Options for ranged request.
*/
rangeRequest(range?: IRangedIndexRequest): number[];
/**
* Implements ranged request operations.
* @param node
* @param range
*/
private collateRequest(node, range);
/**
* Used on a branch node to return an array of id within that branch, sorted by their value
* @param node
*/
private collateIds(node);
/**
* Traverses tree to a node matching the provided value.
* @param node
* @param val
*/
/**
* Inline/Non-recusive 'single value' ($eq) lookup.
* Traverses tree to a node matching the provided value.
* @param node
* @param val
*/
private locate(node, val);
/**
* Index integrity check (IRangedIndex interface function)
*/
validateIndex(): boolean;
/**
* Recursive Node validation routine
* @param node
*/
private validateNode(node);
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/clone.d.ts
================================================
export declare type CloneMethod = "parse-stringify" | "deep" | "shallow" | "shallow-recurse";
/**
* @hidden
*/
export declare function clone(data: T, method?: CloneMethod): T;
================================================
FILE: dist/packages/fs-storage/types/loki/src/collection.d.ts
================================================
import { LokiEventEmitter } from "./event_emitter";
import { UniqueIndex } from "./unique_index";
import { ResultSet } from "./result_set";
import { DynamicView } from "./dynamic_view";
import { IRangedIndex } from "./ranged_indexes";
import { CloneMethod } from "./clone";
import { Doc, Dict } from "../../common/types";
import { FullTextSearch } from "../../full-text-search/src/full_text_search";
import { Analyzer } from "../../full-text-search/src/analyzer/analyzer";
/**
* Collection class that handles documents of same type
* @extends LokiEventEmitter
* @param - the data type
* @param - nested properties of data type
*/
export declare class Collection extends LokiEventEmitter {
name: string;
_data: Doc[];
private _idIndex;
_rangedIndexes: {
[P in keyof T]?: Collection.RangedIndexMeta;
};
_lokimap: {
[$loki: number]: Doc;
};
_unindexedSortComparator: string;
_defaultLokiOperatorPackage: string;
/**
* Unique constraints contain duplicate object references, so they are not persisted.
* We will keep track of properties which have unique constraints applied here, and regenerate on load.
*/
_constraints: {
unique: {
[P in keyof T]?: UniqueIndex;
};
};
/**
* Transforms will be used to store frequently used query chains as a series of steps which itself can be stored along
* with the database.
*/
_transforms: Dict[]>;
/**
* In autosave scenarios we will use collection level dirty flags to determine whether save is needed.
* currently, if any collection is dirty we will autosave the whole database if autosave is configured.
* Defaulting to true since this is called from addCollection and adding a collection should trigger save.
*/
_dirty: boolean;
private _cached;
/**
* Is collection transactional.
*/
private _transactional;
/**
* Options to clone objects when inserting them.
*/
_cloneObjects: boolean;
/**
* Default clone method (if enabled) is parse-stringify.
*/
_cloneMethod: CloneMethod;
/**
* If set to true we will not maintain a meta property for a document.
*/
private _disableMeta;
/**
* Disable track changes.
*/
private _disableChangesApi;
/**
* Disable delta update object style on changes.
*/
_disableDeltaChangesApi: boolean;
/**
* By default, if you insert a document with a Date value for an indexed property, we will convert that value to number.
*/
private _serializableIndexes;
/**
* Name of path of used nested properties.
*/
private _nestedProperties;
/**
* Option to activate a cleaner daemon - clears "aged" documents at set intervals.
*/
_ttl: Collection.TTL;
private _maxId;
private _dynamicViews;
/**
* Changes are tracked by collection and aggregated by the db.
*/
private _changes;
/**
* stages: a map of uniquely identified 'stages', which hold copies of objects to be
* manipulated without affecting the data in the original collection
*/
private _stages;
private _commitLog;
_fullTextSearch: FullTextSearch;
/**
* @param {string} name - collection name
* @param {(object)} [options={}] - a configuration object
* @param {string[]} [options.unique=[]] - array of property names to define unique constraints for
* @param {string[]} [options.exact=[]] - array of property names to define exact constraints for
* @param {RangedIndexOptions} [options.rangedIndexes] - configuration object for ranged indexes
* @param {boolean} [options.asyncListeners=false] - whether listeners are invoked asynchronously
* @param {boolean} [options.disableMeta=false] - set to true to disable meta property on documents
* @param {boolean} [options.disableChangesApi=true] - set to false to enable Changes API
* @param {boolean} [options.disableDeltaChangesApi=true] - set to false to enable Delta Changes API (requires Changes API, forces cloning)
* @param {boolean} [options.clone=false] - specify whether inserts and queries clone to/from user
* @param {boolean} [options.serializableIndexes=true] - converts date values on binary indexed property values are serializable
* @param {string} [options.cloneMethod="deep"] - the clone method
* @param {number} [options.transactional=false] - ?
* @param {number} [options.ttl=] - age of document (in ms.) before document is considered aged/stale.
* @param {number} [options.ttlInterval=] - time interval for clearing out 'aged' documents; not set by default
* @param {string} [options.unindexedSortComparator="js"] "js", "abstract", "abstract-date", "loki" or other registered comparator name
* @param {string} [options.defaultLokiOperatorPackage="js"] "js", "loki", "comparator" (or user defined) query ops package
* @param {FullTextSearch.FieldOptions} [options.fullTextSearch=] - the full-text search options
* @see {@link Loki#addCollection} for normal creation of collections
*/
constructor(name: string, options?: Collection.Options);
toJSON(): Collection.Serialized;
static fromJSONObject(obj: Collection.Serialized, options?: Collection.DeserializeOptions): Collection;
/**
* Adds a named collection transform to the collection
* @param {string} name - name to associate with transform
* @param {array} transform - an array of transformation 'step' objects to save into the collection
*/
addTransform(name: string, transform: Collection.Transform[]): void;
/**
* Retrieves a named transform from the collection.
* @param {string} name - name of the transform to lookup.
*/
getTransform(name: string): Collection.Transform[];
/**
* Updates a named collection transform to the collection
* @param {string} name - name to associate with transform
* @param {object} transform - a transformation object to save into collection
*/
setTransform(name: string, transform: Collection.Transform[]): void;
/**
* Removes a named collection transform from the collection
* @param {string} name - name of collection transform to remove
*/
removeTransform(name: string): void;
private setTTL(age, interval);
/**
* Create a row filter that covers all documents in the collection.
*/
_prepareFullDocIndex(): number[];
/**
* Ensure rangedIndex of a field.
* @param field
* @param indexTypeName
* @param comparatorName
*/
ensureIndex(field: string, indexTypeName?: string, comparatorName?: string): void;
/**
* Ensure rangedIndex of a field.
* @param field Property to create an index on (need to look into contraining on keyof T)
* @param indexTypeName Name of IndexType factory within (global?) hashmap to create IRangedIndex from
* @param comparatorName Name of Comparator within (global?) hashmap
*/
ensureRangedIndex(field: string, indexTypeName?: string, comparatorName?: string): void;
ensureUniqueIndex(field: keyof T): UniqueIndex;
/**
* Quickly determine number of documents in collection (or query)
* @param {object} query - (optional) query object to count results of
* @returns {number} number of documents in the collection
*/
count(query?: ResultSet.Query>): number;
/**
* Rebuild idIndex
*/
private _ensureId();
/**
* Add a dynamic view to the collection
* @param {string} name - name of dynamic view to add
* @param {object} options - (optional) options to configure dynamic view with
* @param {boolean} [options.persistent=false] - indicates if view is to main internal results array in 'resultdata'
* @param {string} [options.sortPriority=SortPriority.PASSIVE] - the sort priority
* @param {number} options.minRebuildInterval - minimum rebuild interval (need clarification to docs here)
* @returns {DynamicView} reference to the dynamic view added
**/
addDynamicView(name: string, options?: DynamicView.Options): DynamicView;
/**
* Remove a dynamic view from the collection
* @param {string} name - name of dynamic view to remove
**/
removeDynamicView(name: string): void;
/**
* Look up dynamic view reference from within the collection
* @param {string} name - name of dynamic view to retrieve reference of
* @returns {DynamicView} A reference to the dynamic view with that name
**/
getDynamicView(name: string): DynamicView;
/**
* Applies a 'mongo-like' find query object and passes all results to an update function.
* @param {object} filterObject - the 'mongo-like' query object
* @param {function} updateFunction - the update function
*/
findAndUpdate(filterObject: ResultSet.Query>, updateFunction: (obj: Doc) => any): void;
/**
* Applies a 'mongo-like' find query object removes all documents which match that filter.
* @param {object} filterObject - 'mongo-like' query object
*/
findAndRemove(filterObject: ResultSet.Query>): void;
/**
* Adds object(s) to collection, ensure object(s) have meta properties, clone it if necessary, etc.
* @param {(object|array)} doc - the document (or array of documents) to be inserted
* @returns {(object|array)} document or documents inserted
*/
insert(doc: TData): Doc;
insert(doc: TData[]): Doc[];
/**
* Adds a single object, ensures it has meta properties, clone it if necessary, etc.
* @param {object} doc - the document to be inserted
* @param {boolean} bulkInsert - quiet pre-insert and insert event emits
* @returns {object} document or 'undefined' if there was a problem inserting it
*/
insertOne(doc: TData, bulkInsert?: boolean): Doc;
/**
* Refers nested properties of an object to the root of it.
* @param {T} data - the object
* @returns {T & TNested} the object with nested properties
* @hidden
*/
_defineNestedProperties(data: U): U & TNested;
/**
* Empties the collection.
* @param {boolean} [removeIndices=false] - remove indices
*/
clear({removeIndices: removeIndices}?: {
removeIndices?: boolean;
}): void;
/**
* Updates an object and notifies collection that the document has changed.
* @param {object} doc - document to update within the collection
*/
update(doc: Doc | Doc[]): void;
/**
* Add object to collection
*/
private _add(obj);
/**
* Applies a filter function and passes all results to an update function.
* @param {function} filterFunction - the filter function
* @param {function} updateFunction - the update function
*/
updateWhere(filterFunction: (obj: Doc) => boolean, updateFunction: (obj: Doc) => Doc): void;
/**
* Remove all documents matching supplied filter function.
* @param {function} filterFunction - the filter function
*/
removeWhere(filterFunction: (obj: Doc) => boolean): void;
removeDataOnly(): void;
/**
* Remove a document from the collection
* @param {number|object} doc - document to remove from collection
*/
remove(doc: number | Doc | Doc[]): void;
/**
* Returns all changes.
* @returns {Collection.Change[]}
*/
getChanges(): Collection.Change[];
/**
* Enables/disables changes api.
* @param {boolean} disableChangesApi
* @param {boolean} disableDeltaChangesApi
*/
setChangesApi(disableChangesApi: boolean, disableDeltaChangesApi?: boolean): void;
/**
* Clears all the changes.
*/
flushChanges(): void;
private _getObjectDelta(oldObject, newObject);
/**
* Compare changed object (which is a forced clone) with existing object and return the delta
*/
private _getChangeDelta(obj, old);
/**
* Creates a clone of the current status of an object and associates operation and collection name,
* so the parent db can aggregate and generate a changes object for the entire db
*/
private _createChange(name, op, obj, old?);
private _createInsertChange(obj);
private _createUpdateChange(obj, old);
private _insertMetaWithChange(obj);
private _updateMetaWithChange(obj, old);
private _insertMeta(obj);
private _updateMeta(obj);
/**
* Get by Id - faster than other methods because of the searching algorithm
* @param {int} id - $loki id of document you want to retrieve
* @param {boolean} returnPosition - if 'true' we will return [object, position]
* @returns {(object|array|null)} Object reference if document was found, null if not,
* or an array if 'returnPosition' was passed.
*/
get(id: number): Doc;
get(id: number, returnPosition: boolean): Doc | [Doc, number];
/**
* Retrieve doc by Unique index
* @param {string} field - name of uniquely indexed property to use when doing lookup
* @param {any} value - unique value to search for
* @returns {object} document matching the value passed
*/
by(field: keyof T, value: any): Doc;
/**
* Find one object by index property, by property equal to value
* @param {object} query - query object used to perform search with
* @returns {(object|null)} First matching document, or null if none
*/
findOne(query: ResultSet.Query>): Doc;
/**
* Chain method, used for beginning a series of chained find() and/or view() operations
* on a collection.
*
* @param {array} transform - Ordered array of transform step objects similar to chain
* @param {object} parameters - Object containing properties representing parameters to substitute
* @returns {ResultSet} (this) ResultSet, or data array if any map or join functions where called
*/
chain(transform?: string | Collection.Transform[], parameters?: object): ResultSet;
/**
* Find method, api is similar to mongodb.
* for more complex queries use [chain()]{@link Collection#chain} or [where()]{@link Collection#where}.
* @example {@tutorial Query Examples}
* @param {object} query - 'mongo-like' query object
* @returns {array} Array of matching documents
*/
find(query?: ResultSet.Query>): Doc[];
/**
* Find object by unindexed field by property equal to value,
* simply iterates and returns the first element matching the query
*/
findOneUnindexed(prop: string, value: any): Doc;
/**
* Transaction methods
*/
/**
* start the transation
*/
startTransaction(): void;
/**
* Commit the transaction.
*/
commit(): void;
/**
* Rollback the transaction.
*/
rollback(): void;
/**
* Query the collection by supplying a javascript filter function.
* @example
* let results = coll.where(function(obj) {
* return obj.legs === 8;
* });
* @param {function} fun - filter function to run against all collection docs
* @returns {array} all documents which pass your filter function
*/
where(fun: (obj: Doc) => boolean): Doc[];
/**
* Map Reduce operation
* @param {function} mapFunction - function to use as map function
* @param {function} reduceFunction - function to use as reduce function
* @returns {data} The result of your mapReduce operation
*/
mapReduce(mapFunction: (value: Doc, index: number, array: Doc[]) => U1, reduceFunction: (array: U1[]) => U2): U2;
/**
* Join two collections on specified properties
* @param {array} joinData - array of documents to 'join' to this collection
* @param {string} leftJoinProp - property name in collection
* @param {string} rightJoinProp - property name in joinData
* @param {function} mapFun - (Optional) map function to use
* @param dataOptions - options to data() before input to your map function
* @param [dataOptions.removeMeta] - allows removing meta before calling mapFun
* @param [dataOptions.forceClones] - forcing the return of cloned objects to your map object
* @param [dataOptions.forceCloneMethod] - allows overriding the default or collection specified cloning method
* @returns {ResultSet} Result of the mapping operation
*/
eqJoin(joinData: Collection | ResultSet | any[], leftJoinProp: string | ((obj: any) => string), rightJoinProp: string | ((obj: any) => string), mapFun?: (left: any, right: any) => any, dataOptions?: ResultSet.DataOptions): ResultSet;
/**
* (Staging API) create a stage and/or retrieve it
*/
getStage(name: string): any;
/**
* a collection of objects recording the changes applied through a commmitStage
*/
/**
* (Staging API) create a copy of an object and insert it into a stage
*/
stage(stageName: string, obj: Doc): F;
/**
* (Staging API) re-attach all objects to the original collection, so indexes and views can be rebuilt
* then create a message to be inserted in the commitlog
* @param {string} stageName - name of stage
* @param {string} message
*/
commitStage(stageName: string, message: string): void;
/**
* Returns all values of a field.
* @param {string} field - the field name
* @return {any}: the array of values
*/
extract(field: keyof T): any[];
/**
* Finds the minimum value of a field.
* @param {string} field - the field name
* @return {number} the minimum value
*/
min(field: keyof T): number;
/**
* Finds the maximum value of a field.
* @param {string} field - the field name
* @return {number} the maximum value
*/
max(field: keyof T): number;
/**
* Finds the minimum value and its index of a field.
* @param {string} field - the field name
* @return {object} - index and value
*/
minRecord(field: keyof T): {
index: number;
value: number;
};
/**
* Finds the maximum value and its index of a field.
* @param {string} field - the field name
* @return {object} - index and value
*/
maxRecord(field: keyof T): {
index: number;
value: number;
};
/**
* Returns all values of a field as numbers (if possible).
* @param {string} field - the field name
* @return {number[]} - the number array
*/
extractNumerical(field: keyof T): number[];
/**
* Calculates the average numerical value of a field
* @param {string} field - the field name
* @returns {number} average of property in all docs in the collection
*/
avg(field: keyof T): number;
/**
* Calculate the standard deviation of a field.
* @param {string} field - the field name
* @return {number} the standard deviation
*/
stdDev(field: keyof T): number;
/**
* Calculates the mode of a field.
* @param {string} field - the field name
* @return {number} the mode
*/
mode(field: keyof T): number;
/**
* Calculates the median of a field.
* @param {string} field - the field name
* @return {number} the median
*/
median(field: keyof T): number;
}
export declare namespace Collection {
interface Options {
unique?: (keyof T)[];
unindexedSortComparator?: string;
defaultLokiOperatorPackage?: string;
rangedIndexes?: RangedIndexOptions;
serializableIndexes?: boolean;
asyncListeners?: boolean;
disableMeta?: boolean;
disableChangesApi?: boolean;
disableDeltaChangesApi?: boolean;
clone?: boolean;
serializableIndices?: boolean;
cloneMethod?: CloneMethod;
transactional?: boolean;
ttl?: number;
ttlInterval?: number;
nestedProperties?: (keyof TNested | {
name: keyof TNested;
path: string[];
})[];
fullTextSearch?: FullTextSearch.FieldOptions[];
}
interface RangedIndexOptions {
[prop: string]: RangedIndexMeta;
}
interface DeserializeOptions {
retainDirtyFlags?: boolean;
fullTextSearch?: Dict;
[collName: string]: any | {
proto?: any;
inflate?: (src: object, dest?: object) => void;
};
}
interface BinaryIndex {
dirty: boolean;
values: any;
}
interface RangedIndexMeta {
index?: IRangedIndex;
indexTypeName?: string;
comparatorName?: string;
}
interface Change {
name: string;
operation: string;
obj: any;
}
interface Serialized {
name: string;
unindexedSortComparator: string;
defaultLokiOperatorPackage: string;
_dynamicViews: DynamicView[];
_nestedProperties: {
name: string;
path: string[];
}[];
uniqueNames: string[];
transforms: Dict;
rangedIndexes: RangedIndexOptions;
_data: Doc[];
idIndex: number[];
maxId: number;
_dirty: boolean;
transactional: boolean;
asyncListeners: boolean;
disableMeta: boolean;
disableChangesApi: boolean;
disableDeltaChangesApi: boolean;
cloneObjects: boolean;
cloneMethod: CloneMethod;
changes: any;
_fullTextSearch: FullTextSearch;
}
interface CheckIndexOptions {
randomSampling?: boolean;
randomSamplingFactor?: number;
repair?: boolean;
}
type Transform = {
type: "find";
value: ResultSet.Query> | string;
} | {
type: "where";
value: ((obj: Doc) => boolean) | string;
} | {
type: "simplesort";
property: keyof T;
options?: boolean | ResultSet.SimpleSortOptions;
} | {
type: "compoundsort";
value: (keyof T | [keyof T, boolean])[];
} | {
type: "sort";
value: (a: Doc, b: Doc) => number;
} | {
type: "sortByScoring";
desc?: boolean;
} | {
type: "limit";
value: number;
} | {
type: "offset";
value: number;
} | {
type: "map";
value: (obj: Doc, index: number, array: Doc[]) => any;
dataOptions?: ResultSet.DataOptions;
} | {
type: "eqJoin";
joinData: Collection | ResultSet;
leftJoinKey: string | ((obj: any) => string);
rightJoinKey: string | ((obj: any) => string);
mapFun?: (left: any, right: any) => any;
dataOptions?: ResultSet.DataOptions;
} | {
type: "mapReduce";
mapFunction: (item: Doc, index: number, array: Doc[]) => any;
reduceFunction: (array: any[]) => any;
} | {
type: "update";
value: (obj: Doc) => any;
} | {
type: "remove";
};
interface TTL {
age: number;
ttlInterval: number;
daemon: any;
}
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/comparators.d.ts
================================================
export interface ILokiComparer {
(a: T, b: T): -1 | 0 | 1;
}
export interface IComparatorMap {
[name: string]: ILokiComparer;
}
/** Map/Register of named ILokiComparer functions returning -1, 0, 1 for lt/eq/gt assertions for two passed parameters */
export declare let ComparatorMap: IComparatorMap;
/** Typescript-friendly factory for strongly typed 'js' comparators */
export declare function CreateJavascriptComparator(): ILokiComparer;
/** Typescript-friendly factory for strongly typed 'abstract js' comparators */
export declare function CreateAbstractJavascriptComparator(): ILokiComparer;
/**
* Comparator which attempts to deal with deal with dates at comparator level.
* Should work for dates in any of the object, string, and number formats
*/
export declare function CreateAbstractDateJavascriptComparator(): ILokiComparer;
/** Typescript-friendly factory for strongly typed 'loki' comparators */
export declare function CreateLokiComparator(): ILokiComparer;
================================================
FILE: dist/packages/fs-storage/types/loki/src/dynamic_view.d.ts
================================================
import { LokiEventEmitter } from "./event_emitter";
import { ResultSet } from "./result_set";
import { Collection } from "./collection";
import { Doc } from "../../common/types";
import { Scorer } from "../../full-text-search/src/scorer";
/**
* DynamicView class is a versatile 'live' view class which can have filters and sorts applied.
* Collection.addDynamicView(name) instantiates this DynamicView object and notifies it
* whenever documents are add/updated/removed so it can remain up-to-date. (chainable)
*
* @example
* let mydv = mycollection.addDynamicView('test'); // default is non-persistent
* mydv.applyFind({ 'doors' : 4 });
* mydv.applyWhere(function(obj) { return obj.name === 'Toyota'; });
* let results = mydv.data();
*
* @extends LokiEventEmitter
* @see {@link Collection#addDynamicView} to construct instances of DynamicView
*
* @param - the data type
* @param - nested properties of data type
*/
export declare class DynamicView extends LokiEventEmitter {
readonly name: string;
private _collection;
private _persistent;
private _sortPriority;
private _minRebuildInterval;
private _rebuildPending;
private _resultSet;
private _resultData;
private _resultDirty;
private _cachedResultSet;
private _filterPipeline;
private _sortFunction;
private _sortCriteria;
private _sortCriteriaSimple;
private _sortByScoring;
private _sortDirty;
/**
* Constructor.
* @param {Collection} collection - a reference to the collection to work agains
* @param {string} name - the name of this dynamic view
* @param {object} options - the options
* @param {boolean} [options.persistent=false] - indicates if view is to main internal results array in 'resultdata'
* @param {string} [options.sortPriority="passive"] - the sort priority
* @param {number} [options.minRebuildInterval=1] - minimum rebuild interval (need clarification to docs here)
*/
constructor(collection: Collection, name: string, options?: DynamicView.Options);
/**
* Internally used immediately after deserialization (loading)
* This will clear out and reapply filterPipeline ops, recreating the view.
* Since where filters do not persist correctly, this method allows
* restoring the view to state where user can re-apply those where filters.
*
* @param removeWhereFilters
* @returns {DynamicView} This dynamic view for further chained ops.
* @fires DynamicView.rebuild
*/
private _rematerialize({removeWhereFilters});
/**
* Makes a copy of the internal ResultSet for branched queries.
* Unlike this dynamic view, the branched ResultSet will not be 'live' updated,
* so your branched query should be immediately resolved and not held for future evaluation.
* @param {(string|array=)} transform - Optional name of collection transform, or an array of transform steps
* @param {object} parameters - optional parameters (if optional transform requires them)
* @returns {ResultSet} A copy of the internal ResultSet for branched queries.
*/
branchResultSet(transform?: string | Collection.Transform[], parameters?: object): ResultSet;
/**
* Override of toJSON to avoid circular references.
*/
toJSON(): DynamicView.Serialized;
static fromJSONObject(collection: Collection, obj: DynamicView.Serialized): DynamicView;
/**
* Used to clear pipeline and reset dynamic view to initial state.
* Existing options should be retained.
* @param {boolean} queueSortPhase - (default: false) if true we will async rebuild view (maybe set default to true in future?)
*/
removeFilters({queueSortPhase}?: {
queueSortPhase?: boolean;
}): void;
/**
* Used to apply a sort to the dynamic view
* @example
* dv.applySort(function(obj1, obj2) {
* if (obj1.name === obj2.name) return 0;
* if (obj1.name > obj2.name) return 1;
* if (obj1.name < obj2.name) return -1;
* });
* @param {function} comparefun - a javascript compare function used for sorting
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
applySort(comparefun: (lhs: Doc, rhs: Doc) => number): this;
/**
* Used to specify a property used for view translation.
* @param {string} field - the field name
* @param {boolean|object=} options - boolean for sort descending or options object
* @param {boolean} [options.desc=false] - whether we should sort descending.
* @param {boolean} [options.disableIndexIntersect=false] - whether we should explicity not use array intersection.
* @param {boolean} [options.forceIndexIntersect=false] - force array intersection (if binary index exists).
* @param {boolean} [options.useJavascriptSorting=false] - whether results are sorted via basic javascript sort.
* @returns {DynamicView} this DynamicView object, for further chain ops.
* @example
* dv.applySimpleSort("name");
*/
applySimpleSort(field: keyof T, options?: boolean | ResultSet.SimpleSortOptions): this;
/**
* Allows sorting a ResultSet based on multiple columns.
* @param {Array} criteria - array of property names or subarray of [propertyname, isdesc] used evaluate sort order
* @returns {DynamicView} Reference to this DynamicView, sorted, for future chain operations.
* @example
* // to sort by age and then name (both ascending)
* dv.applySortCriteria(['age', 'name']);
* // to sort by age (ascending) and then by name (descending)
* dv.applySortCriteria(['age', ['name', true]]);
* // to sort by age (descending) and then by name (descending)
* dv.applySortCriteria([['age', true], ['name', true]]);
*/
applySortCriteria(criteria: (keyof T | [keyof T, boolean])[]): this;
/**
* Used to apply a sort by the latest full-text-search scoring.
* @param {boolean} [ascending=false] - sort ascending
*/
applySortByScoring(ascending?: boolean): this;
/**
* Returns the scoring of the last full-text-search.
* @returns {ScoreResult[]}
*/
getScoring(): Scorer.ScoreResult[];
/**
* Marks the beginning of a transaction.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
startTransaction(): this;
/**
* Commits a transaction.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
commit(): this;
/**
* Rolls back a transaction.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
rollback(): this;
/**
* Find the index of a filter in the pipeline, by that filter's ID.
* @param {(string|number)} uid - The unique ID of the filter.
* @returns {number}: index of the referenced filter in the pipeline; -1 if not found.
*/
private _indexOfFilterWithId(uid);
/**
* Add the filter object to the end of view's filter pipeline and apply the filter to the ResultSet.
* @param {object} filter - The filter object. Refer to applyFilter() for extra details.
*/
private _addFilter(filter);
/**
* Reapply all the filters in the current pipeline.
*
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
reapplyFilters(): this;
/**
* Adds or updates a filter in the DynamicView filter pipeline
* @param {object} filter - A filter object to add to the pipeline.
* The object is in the format { 'type': filter_type, 'val', filter_param, 'uid', optional_filter_id }
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
applyFilter(filter: DynamicView.Filter): this;
/**
* applyFind() - Adds or updates a mongo-style query option in the DynamicView filter pipeline
*
* @param {object} query - A mongo-style query object to apply to pipeline
* @param {(string|number)} uid - Optional: The unique ID of this filter, to reference it in the future.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
applyFind(query: object, uid?: string | number): this;
/**
* Adds or updates a javascript filter function in the DynamicView filter pipeline
* @param {function} fun - A javascript filter function to apply to pipeline
* @param {(string|number)} uid - Optional: The unique ID of this filter, to reference it in the future.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
applyWhere(fun: (obj: Doc) => boolean, uid?: string | number): this;
/**
* Remove the specified filter from the DynamicView filter pipeline
* @param {(string|number)} uid - The unique ID of the filter to be removed.
* @returns {DynamicView} this DynamicView object, for further chain ops.
*/
removeFilter(uid: string | number): this;
/**
* Returns the number of documents representing the current DynamicView contents.
* @returns {number} The number of documents representing the current DynamicView contents.
*/
count(): number;
/**
* Resolves and pending filtering and sorting, then returns document array as result.
* @param {object} options - optional parameters to pass to ResultSet.data() if non-persistent
* @param {boolean} [options.forceClones] - Allows forcing the return of cloned objects even when
* the collection is not configured for clone object.
* @param {string} [options.forceCloneMethod] - Allows overriding the default or collection specified cloning method.
* Possible values include 'parse-stringify', 'jquery-extend-deep', 'shallow', 'shallow-assign'
* @param {boolean} [options.removeMeta] - will force clones and strip $loki and meta properties from documents
*
* @returns {Array} An array of documents representing the current DynamicView contents.
*/
data(options?: ResultSet.DataOptions): Doc[];
/**
* When the view is not sorted we may still wish to be notified of rebuild events.
* This event will throttle and queue a single rebuild event when batches of updates affect the view.
*/
private _queueRebuildEvent();
/**
* If the view is sorted we will throttle sorting to either :
* (1) passive - when the user calls data(), or
* (2) active - once they stop updating and yield js thread control
*/
private _queueSortPhase();
/**
* Invoked synchronously or asynchronously to perform final sort phase (if needed)
*/
private _performSortPhase(options?);
/**
* (Re)evaluating document inclusion.
* Called by : collection.insert() and collection.update().
* @param {int} objIndex - index of document to (re)run through filter pipeline.
* @param {boolean} isNew - true if the document was just added to the collection.
* @hidden
*/
_evaluateDocument(objIndex: number, isNew: boolean): void;
/**
* Internal function called on collection.delete().
* @hidden
*/
_removeDocument(objIndex: number): void;
/**
* Data transformation via user supplied functions
* @param {function} mapFunction - this function accepts a single document for you to transform and return
* @param {function} reduceFunction - this function accepts many (array of map outputs) and returns single value
* @returns The output of your reduceFunction
*/
mapReduce(mapFunction: (item: T, index: number, array: T[]) => U1, reduceFunction: (array: U1[]) => U2): U2;
}
export declare namespace DynamicView {
interface Options {
persistent?: boolean;
sortPriority?: SortPriority;
minRebuildInterval?: number;
}
type SortPriority = "passive" | "active";
interface Serialized {
name: string;
_persistent: boolean;
_sortPriority: SortPriority;
_minRebuildInterval: number;
_resultSet: ResultSet;
_filterPipeline: Filter[];
_sortCriteria: (string | [string, boolean])[];
_sortCriteriaSimple: {
field: string;
options: boolean | ResultSet.SimpleSortOptions;
};
_sortByScoring: boolean;
_sortDirty: boolean;
}
type Filter = {
type: "find";
val: ResultSet.Query>;
uid: number | string;
} | {
type: "where";
val: (obj: Doc) => boolean;
uid: number | string;
};
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/event_emitter.d.ts
================================================
/**
* LokiEventEmitter is a minimalist version of EventEmitter. It enables any
* constructor that inherits EventEmitter to emit events and trigger
* listeners that have been added to the event through the on(event, callback) method
*
* @constructor LokiEventEmitter
*/
export declare class LokiEventEmitter {
/**
* A map, with each property being an array of callbacks.
*/
protected _events: object;
/**
* Determines whether or not the callbacks associated with each event should happen in an async fashion or not.
* Default is false, which means events are synchronous
*/
protected _asyncListeners: boolean;
/**
* Adds a listener to the queue of callbacks associated to an event
* @param {string|string[]} eventName - the name(s) of the event(s) to listen to
* @param {function} listener - callback function of listener to attach
* @returns {int} the index of the callback in the array of listeners for a particular event
*/
on(eventName: string | string[], listener: Function): Function;
/**
* Emits a particular event
* with the option of passing optional parameters which are going to be processed by the callback
* provided signatures match (i.e. if passing emit(event, arg0, arg1) the listener should take two parameters)
* @param {string} eventName - the name of the event
* @param {object} data - optional object passed with the event
*/
protected emit(eventName: string, ...data: any[]): void;
/**
* Alias of EventEmitter.on().
*/
addListener(eventName: string | string[], listener: Function): Function;
/**
* Removes the listener at position 'index' from the event 'eventName'
* @param {string|string[]} eventName - the name(s) of the event(s) which the listener is attached to
* @param {function} listener - the listener callback function to remove from emitter
*/
removeListener(eventName: string | string[], listener: Function): void;
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/index.d.ts
================================================
import { Loki } from "./loki";
import { Collection } from "./collection";
export { Loki, Collection };
export default Loki;
================================================
FILE: dist/packages/fs-storage/types/loki/src/loki.d.ts
================================================
import { LokiEventEmitter } from "./event_emitter";
import { Collection } from "./collection";
import { Doc, StorageAdapter } from "../../common/types";
import { IComparatorMap } from "./comparators";
import { IRangedIndexFactoryMap } from "./ranged_indexes";
import { ILokiOperatorPackageMap } from "./operator_packages";
export declare class Loki extends LokiEventEmitter {
filename: string;
private databaseVersion;
private engineVersion;
_collections: Collection[];
private _env;
private _serializationMethod;
private _destructureDelimiter;
private _persistenceMethod;
private _persistenceAdapter;
private _throttledSaves;
private _throttledSaveRunning;
private _throttledSavePending;
private _autosave;
private _autosaveInterval;
private _autosaveRunning;
private _autosaveHandler;
/**
* Constructs the main database class.
* @param {string} filename - name of the file to be saved to
* @param {object} [options={}] - options
* @param {Loki.Environment} [options.env] - the javascript environment
* @param {Loki.SerializationMethod} [options.serializationMethod=NORMAL] - the serialization method
* @param {string} [options.destructureDelimiter="$<\n"] - string delimiter used for destructured serialization
* @param {IComparatorMap} [options.comparatorMap] allows injecting or overriding registered comparators
* @param {IRangedIndexFactoryMap} [options.rangedIndexFactoryMap] allows injecting or overriding registered ranged index factories
* @param {ILokiOperatorPackageMap} [options.lokiOperatorPackageMap] allows injecting or overriding registered loki operator packages
*/
constructor(filename?: string, options?: Loki.Options);
/**
* configures options related to database persistence.
*
* @param {Loki.PersistenceOptions} [options={}] - options
* @param {adapter} [options.adapter=auto] - an instance of a loki persistence adapter
* @param {boolean} [options.autosave=false] - enables autosave
* @param {int} [options.autosaveInterval=5000] - time interval (in milliseconds) between saves (if dirty)
* @param {boolean} [options.autoload=false] - enables autoload on loki instantiation
* @param {object} options.inflate - options that are passed to loadDatabase if autoload enabled
* @param {boolean} [options.throttledSaves=true] - if true, it batches multiple calls to to saveDatabase reducing number of
* disk I/O operations and guaranteeing proper serialization of the calls. Default value is true.
* @param {Loki.PersistenceMethod} options.persistenceMethod - a persistence method which should be used (FS_STORAGE, LOCAL_STORAGE...)
* @returns {Promise} a Promise that resolves after initialization and (if enabled) autoloading the database
*/
initializePersistence(options?: Loki.PersistenceOptions): Promise;
/**
* Copies 'this' database into a new Loki instance. Object references are shared to make lightweight.
* @param {object} options - options
* @param {boolean} options.removeNonSerializable - nulls properties not safe for serialization.
*/
copy(options?: Loki.CopyOptions): Loki;
/**
* Adds a collection to the database.
* @param {string} name - name of collection to add
* @param {object} [options={}] - options to configure collection with.
* @param {array} [options.unique=[]] - array of property names to define unique constraints for
* @param {array} [options.exact=[]] - array of property names to define exact constraints for
* @param {array} [options.indices=[]] - array property names to define binary indexes for
* @param {boolean} [options.asyncListeners=false] - whether listeners are called asynchronously
* @param {boolean} [options.disableMeta=false] - set to true to disable meta property on documents
* @param {boolean} [options.disableChangesApi=true] - set to false to enable Changes Api
* @param {boolean} [options.disableDeltaChangesApi=true] - set to false to enable Delta Changes API (requires Changes API, forces cloning)
* @param {boolean} [options.clone=false] - specify whether inserts and queries clone to/from user
* @param {string} [options.cloneMethod=CloneMethod.DEEP] - the clone method
* @param {number} [options.ttl=] - age of document (in ms.) before document is considered aged/stale
* @param {number} [options.ttlInterval=] - time interval for clearing out 'aged' documents; not set by default
* @returns {Collection} a reference to the collection which was just added
*/
addCollection(name: string, options?: Collection.Options): Collection;
loadCollection(collection: Collection): void;
/**
* Retrieves reference to a collection by name.
* @param {string} name - name of collection to look up
* @returns {Collection} Reference to collection in database by that name, or null if not found
*/
getCollection(name: string): Collection;
/**
* Renames an existing loki collection
* @param {string} oldName - name of collection to rename
* @param {string} newName - new name of collection
* @returns {Collection} reference to the newly renamed collection
*/
renameCollection(oldName: string, newName: string): Collection;
listCollections(): {
name: string;
count: number;
}[];
/**
* Removes a collection from the database.
* @param {string} collectionName - name of collection to remove
*/
removeCollection(collectionName: string): void;
/**
* Serialize database to a string which can be loaded via {@link Loki#loadJSON}
*
* @returns {string} Stringified representation of the loki database.
*/
serialize(options?: Loki.SerializeOptions): string | string[];
toJSON(): Loki.Serialized;
/**
* Database level destructured JSON serialization routine to allow alternate serialization methods.
* Internally, Loki supports destructuring via loki "serializationMethod' option and
* the optional LokiPartitioningAdapter class. It is also available if you wish to do
* your own structured persistence or data exchange.
*
* @param {object} options - output format options for use externally to loki
* @param {boolean} [options.partitioned=false] - whether db and each collection are separate
* @param {int} options.partition - can be used to only output an individual collection or db (-1)
* @param {boolean} [options.delimited=true] - whether subitems are delimited or subarrays
* @param {string} options.delimiter - override default delimiter
*
* @returns {string|Array} A custom, restructured aggregation of independent serializations.
*/
serializeDestructured(options?: Loki.SerializeDestructuredOptions): string | string[];
/**
* Collection level utility method to serialize a collection in a 'destructured' format
*
* @param {object} options - used to determine output of method
* @param {int} options.delimited - whether to return single delimited string or an array
* @param {string} options.delimiter - (optional) if delimited, this is delimiter to use
* @param {int} options.collectionIndex - specify which collection to serialize data for
*
* @returns {string|array} A custom, restructured aggregation of independent serializations for a single collection.
*/
serializeCollection(options?: {
delimited?: boolean;
collectionIndex?: number;
delimiter?: string;
}): string | string[];
/**
* Database level destructured JSON deserialization routine to minimize memory overhead.
* Internally, Loki supports destructuring via loki "serializationMethod' option and
* the optional LokiPartitioningAdapter class. It is also available if you wish to do
* your own structured persistence or data exchange.
*
* @param {string|array} destructuredSource - destructured json or array to deserialize from
* @param {object} options - source format options
* @param {boolean} [options.partitioned=false] - whether db and each collection are separate
* @param {int} options.partition - can be used to deserialize only a single partition
* @param {boolean} [options.delimited=true] - whether subitems are delimited or subarrays
* @param {string} options.delimiter - override default delimiter
*
* @returns {object|array} An object representation of the deserialized database, not yet applied to 'this' db or document array
*/
deserializeDestructured(destructuredSource: string | string[], options?: Loki.SerializeDestructuredOptions): any;
/**
* Collection level utility function to deserializes a destructured collection.
*
* @param {string|string[]} destructuredSource - destructured representation of collection to inflate
* @param {object} options - used to describe format of destructuredSource input
* @param {int} [options.delimited=false] - whether source is delimited string or an array
* @param {string} options.delimiter - if delimited, this is delimiter to use (if other than default)
*
* @returns {Array} an array of documents to attach to collection.data.
*/
deserializeCollection(destructuredSource: string | string[], options?: Loki.DeserializeCollectionOptions): Doc[];
/**
* Inflates a loki database from a serialized JSON string
*
* @param {string} serializedDb - a serialized loki database string
* @param {object} options - apply or override collection level settings
* @param {boolean} options.retainDirtyFlags - whether collection dirty flags will be preserved
*/
loadJSON(serializedDb: string | string[], options?: Collection.DeserializeOptions): void;
/**
* Inflates a loki database from a JS object
*
* @param {object} dbObject - a serialized loki database object
* @param {object} options - apply or override collection level settings
* @param {boolean} options.retainDirtyFlags - whether collection dirty flags will be preserved
*/
loadJSONObject(dbObject: Loki, options?: Collection.DeserializeOptions): void;
loadJSONObject(dbObject: Loki.Serialized, options?: Collection.DeserializeOptions): void;
/**
* Emits the close event. In autosave scenarios, if the database is dirty, this will save and disable timer.
* Does not actually destroy the db.
*
* @returns {Promise} a Promise that resolves after closing the database succeeded
*/
close(): Promise;
/**-------------------------+
| Changes API |
+--------------------------*/
/**
* The Changes API enables the tracking the changes occurred in the collections since the beginning of the session,
* so it's possible to create a differential dataset for synchronization purposes (possibly to a remote db)
*/
/**
* (Changes API) : takes all the changes stored in each
* collection and creates a single array for the entire database. If an array of names
* of collections is passed then only the included collections will be tracked.
*
* @param {Array} [arrayOfCollectionNames=] - array of collection names. No arg means all collections are processed.
* @returns {Array} array of changes
* @see private method _createChange() in Collection
*/
generateChangesNotification(arrayOfCollectionNames?: string[]): Collection.Change[];
/**
* (Changes API) - stringify changes for network transmission
* @returns {string} string representation of the changes
*/
serializeChanges(collectionNamesArray?: string[]): string;
/**
* (Changes API) : clears all the changes in all collections.
*/
clearChanges(): void;
/**
* Wait for throttledSaves to complete and invoke your callback when drained or duration is met.
*
* @param {object} options - configuration options
* @param {boolean} [options.recursiveWait=true] - if after queue is drained, another save was kicked off, wait for it
* @param {boolean} [options.recursiveWaitLimit=false] - limit our recursive waiting to a duration
* @param {number} [options.recursiveWaitLimitDuration=2000] - cutoff in ms to stop recursively re-draining
* @param {Date} [options.started=now()] - the start time of the recursive wait duration
* @returns {Promise} a Promise that resolves when save queue is drained, it is passed a sucess parameter value
*/
throttledSaveDrain(options?: Loki.ThrottledDrainOptions): Promise;
/**
* Internal load logic, decoupled from throttling/contention logic
*
* @param {object} options - an object containing inflation options for each collection
* @param {boolean} ignore_not_found - does not raise an error if database is not found
* @returns {Promise} a Promise that resolves after the database is loaded
*/
private _loadDatabase(options?, ignore_not_found?);
/**
* Handles manually loading from an adapter storage (such as fs-storage)
* This method utilizes loki configuration options (if provided) to determine which
* persistence method to use, or environment detection (if configuration was not provided).
* To avoid contention with any throttledSaves, we will drain the save queue first.
*
* If you are configured with autosave, you do not need to call this method yourself.
*
* @param {object} [options={}] - if throttling saves and loads, this controls how we drain save queue before loading
* @param {boolean} [options.recursiveWait=true] wait recursively until no saves are queued
* @param {boolean} [options.recursiveWaitLimit=false] limit our recursive waiting to a duration
* @param {number} [options.recursiveWaitLimitDelay=2000] cutoff in ms to stop recursively re-draining
* @param {Date} [options.started=now()] - the start time of the recursive wait duration
* @returns {Promise} a Promise that resolves after the database is loaded
*/
loadDatabase(options?: Loki.LoadDatabaseOptions): Promise;
private _saveDatabase();
/**
* Handles manually saving to an adapter storage (such as fs-storage)
* This method utilizes loki configuration options (if provided) to determine which
* persistence method to use, or environment detection (if configuration was not provided).
*
* If you are configured with autosave, you do not need to call this method yourself.
*
* @returns {Promise} a Promise that resolves after the database is persisted
*/
saveDatabase(): Promise;
/**
* Handles deleting a database from the underlying storage adapter
*
* @returns {Promise} a Promise that resolves after the database is deleted
*/
deleteDatabase(): Promise;
/****************
* Autosave API
****************/
/**
* Check whether any collections are "dirty" meaning we need to save the (entire) database
* @returns {boolean} - true if database has changed since last autosave, otherwise false
*/
private _autosaveDirty();
/**
* Resets dirty flags on all collections.
*/
private _autosaveClearFlags();
/**
* Starts periodically saves to the underlying storage adapter.
*/
private _autosaveEnable();
/**
* Stops the autosave interval timer.
*/
private _autosaveDisable();
}
export declare namespace Loki {
interface Options {
env?: Environment;
serializationMethod?: SerializationMethod;
destructureDelimiter?: string;
comparatorMap?: IComparatorMap;
rangedIndexFactoryMap?: IRangedIndexFactoryMap;
lokiOperatorPackageMap?: ILokiOperatorPackageMap;
}
interface PersistenceOptions {
adapter?: StorageAdapter;
autosave?: boolean;
autosaveInterval?: number;
autoload?: boolean;
throttledSaves?: boolean;
persistenceMethod?: Loki.PersistenceMethod;
inflate?: any;
}
interface CopyOptions {
removeNonSerializable?: boolean;
}
interface SerializeOptions {
serializationMethod?: SerializationMethod;
}
interface SerializeDestructuredOptions {
partitioned?: boolean;
partition?: number;
delimited?: boolean;
delimiter?: string;
}
interface DeserializeCollectionOptions {
partitioned?: boolean;
delimited?: boolean;
delimiter?: string;
}
interface ThrottledDrainOptions {
recursiveWait?: boolean;
recursiveWaitLimit?: boolean;
recursiveWaitLimitDuration?: number;
started?: Date;
}
interface Serialized {
_env: Environment;
_serializationMethod: SerializationMethod;
_autosave: boolean;
_autosaveInterval: number;
_collections: Collection[];
databaseVersion: number;
engineVersion: number;
filename: string;
_persistenceAdapter: StorageAdapter;
_persistenceMethod: PersistenceMethod;
_throttledSaves: boolean;
}
type LoadDatabaseOptions = Collection.DeserializeOptions & ThrottledDrainOptions;
type SerializationMethod = "normal" | "pretty" | "destructured";
type PersistenceMethod = "fs-storage" | "local-storage" | "indexed-storage" | "memory-storage" | "adapter";
type Environment = "NATIVESCRIPT" | "NODEJS" | "CORDOVA" | "BROWSER" | "MEMORY";
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/operator_packages.d.ts
================================================
import { ILokiComparer } from "./comparators";
/** Hash interface for named LokiOperatorPackage registration */
export interface ILokiOperatorPackageMap {
[name: string]: LokiOperatorPackage;
}
/**
* Helper function for determining 'loki' abstract equality which is a little more abstract than ==
* aeqHelper(5, '5') === true
* aeqHelper(5.0, '5') === true
* aeqHelper(new Date("1/1/2011"), new Date("1/1/2011")) === true
* aeqHelper({a:1}, {z:4}) === true (all objects sorted equally)
* aeqHelper([1, 2, 3], [1, 3]) === false
* aeqHelper([1, 2, 3], [1, 2, 3]) === true
* aeqHelper(undefined, null) === true
* @param {any} prop1
* @param {any} prop2
* @returns {boolean}
* @hidden
*/
export declare function aeqHelper(prop1: any, prop2: any): boolean;
/**
* Helper function for determining 'less-than' conditions for ops, sorting, and binary indices.
* In the future we might want $lt and $gt ops to use their own functionality/helper.
* Since binary indices on a property might need to index [12, NaN, new Date(), Infinity], we
* need this function (as well as gtHelper) to always ensure one value is LT, GT, or EQ to another.
* @hidden
*/
export declare function ltHelper(prop1: any, prop2: any, equal: boolean): boolean;
/**
* @hidden
* @param {any} prop1
* @param {any} prop2
* @param {boolean} equal
* @returns {boolean}
*/
export declare function gtHelper(prop1: any, prop2: any, equal: boolean): boolean;
/**
* @param {any} prop1
* @param {any} prop2
* @param {boolean} descending
* @returns {number}
* @hidden
*/
export declare function sortHelper(prop1: any, prop2: any, descending: boolean): number;
/**
* Default implementation of LokiOperatorPackage, using fastest javascript comparison operators.
*/
export declare class LokiOperatorPackage {
$eq(a: any, b: any): boolean;
$ne(a: any, b: any): boolean;
$gt(a: any, b: any): boolean;
$gte(a: any, b: any): boolean;
$lt(a: any, b: any): boolean;
$lte(a: any, b: any): boolean;
$between(a: any, range: [any, any]): boolean;
$in(a: any, b: any): boolean;
$nin(a: any, b: any): boolean;
$keyin(a: string, b: object): boolean;
$nkeyin(a: string, b: object): boolean;
$definedin(a: string, b: object): boolean;
$undefinedin(a: string, b: object): boolean;
$regex(a: string, b: RegExp): boolean;
$containsNone(a: any, b: any): boolean;
$containsAny(a: any, b: any): boolean;
$contains(a: any, b: any): boolean;
$type(a: any, b: any): boolean;
$finite(a: number, b: boolean): boolean;
$size(a: any, b: any): boolean;
$len(a: any, b: any): boolean;
$where(a: any, b: any): boolean;
$not(a: any, b: any): boolean;
$and(a: any, b: any): boolean;
$or(a: any, b: any): boolean;
private doQueryOp(val, op);
private containsCheckFn(a);
}
/**
* LokiOperatorPackage which utilizes abstract 'loki' comparisons for basic relational equality op implementations.
*/
export declare class LokiAbstractOperatorPackage extends LokiOperatorPackage {
constructor();
$eq(a: any, b: any): boolean;
$ne(a: any, b: any): boolean;
$gt(a: any, b: any): boolean;
$gte(a: any, b: any): boolean;
$lt(a: any, b: any): boolean;
$lte(a: any, b: any): boolean;
$between(a: any, range: [any, any]): boolean;
}
/**
* LokiOperatorPackage which utilizes provided comparator for basic relational equality op implementations.
*/
export declare class ComparatorOperatorPackage extends LokiOperatorPackage {
comparator: ILokiComparer;
constructor(comparator: ILokiComparer);
$eq(a: any, b: any): boolean;
$ne(a: any, b: any): boolean;
$gt(a: any, b: any): boolean;
$gte(a: any, b: any): boolean;
$lt(a: any, b: any): boolean;
$lte(a: any, b: any): boolean;
$between(a: any, range: [any, any]): boolean;
}
/**
* Map/Register of named LokiOperatorPackages which implement all unindexed query ops within 'find' query objects
*/
export declare let LokiOperatorPackageMap: ILokiOperatorPackageMap;
================================================
FILE: dist/packages/fs-storage/types/loki/src/ranged_indexes.d.ts
================================================
import { ILokiComparer } from "./comparators";
export declare type RangedValueOperator = "$gt" | "$gte" | "$lt" | "$lte" | "$eq" | "$neq" | "$between";
export interface IRangedIndexRequest {
op: RangedValueOperator;
val: T;
high?: T;
}
/** Defines interface which all loki ranged indexes need to implement */
export interface IRangedIndex {
insert(id: number, val: T): void;
update(id: number, val: T): void;
remove(id: number): void;
restore(tree: any): void;
backup(): IRangedIndex;
rangeRequest(range?: IRangedIndexRequest): number[];
validateIndex(): boolean;
}
/** Hash Interface for global ranged index factory map*/
export interface IRangedIndexFactoryMap {
[name: string]: (name: string, comparator: ILokiComparer) => IRangedIndex;
}
/** Map/Register of named factory functions returning IRangedIndex instances */
export declare let RangedIndexFactoryMap: IRangedIndexFactoryMap;
================================================
FILE: dist/packages/fs-storage/types/loki/src/result_set.d.ts
================================================
import { Collection } from "./collection";
import { CloneMethod } from "./clone";
import { Doc } from "../../common/types";
import { Scorer } from "../../full-text-search/src/scorer";
import { Query as FullTextSearchQuery } from "../../full-text-search/src/query_types";
/**
* ResultSet class allowing chainable queries. Intended to be instanced internally.
* Collection.find(), Collection.where(), and Collection.chain() instantiate this.
*
* @example
* mycollection.chain()
* .find({ 'doors' : 4 })
* .where(function(obj) { return obj.name === 'Toyota' })
* .data();
*
* @param - the data type
* @param - nested properties of data type
*/
export declare class ResultSet {
_collection: Collection;
_filteredRows: number[];
_filterInitialized: boolean;
private _scoring;
/**
* Constructor.
* @param {Collection} collection - the collection which this ResultSet will query against
*/
constructor(collection: Collection);
/**
* Reset the ResultSet to its initial state.
* @returns {ResultSet} Reference to this ResultSet, for future chain operations.
*/
reset(): this;
/**
* Override of toJSON to avoid circular references
*/
toJSON(): ResultSet;
/**
* Allows you to limit the number of documents passed to next chain operation.
* A ResultSet copy() is made to avoid altering original ResultSet.
* @param {int} qty - The number of documents to return.
* @returns {ResultSet} Returns a copy of the ResultSet, limited by qty, for subsequent chain ops.
*/
limit(qty: number): this;
/**
* Used for skipping 'pos' number of documents in the ResultSet.
* @param {int} pos - Number of documents to skip; all preceding documents are filtered out.
* @returns {ResultSet} Returns a copy of the ResultSet, containing docs starting at 'pos' for subsequent chain ops.
*/
offset(pos: number): this;
/**
* To support reuse of ResultSet in branched query situations.
* @returns {ResultSet} Returns a copy of the ResultSet (set) but the underlying document references will be the same.
*/
copy(): ResultSet;
/**
* Executes a named collection transform or raw array of transform steps against the ResultSet.
* @param {(string|array)} transform - name of collection transform or raw transform array
* @param {object} [parameters=] - object property hash of parameters, if the transform requires them.
* @returns {ResultSet} either (this) ResultSet or a clone of of this ResultSet (depending on steps)
*/
transform(transform: string | Collection.Transform[], parameters?: object): this;
/**
* User supplied compare function is provided two documents to compare. (chainable)
* @example
* rslt.sort(function(obj1, obj2) {
* if (obj1.name === obj2.name) return 0;
* if (obj1.name > obj2.name) return 1;
* if (obj1.name < obj2.name) return -1;
* });
* @param {function} comparefun - A javascript compare function used for sorting.
* @returns {ResultSet} Reference to this ResultSet, sorted, for future chain operations.
*/
sort(comparefun: (a: Doc, b: Doc) => number): this;
/**
* Simpler, loose evaluation for user to sort based on a property name. (chainable).
* Sorting based on the same lt/gt helper functions used for binary indices.
* @param {string} propname - name of property to sort by.
* @param {boolean|object=} options - boolean for sort descending or options object
* @param {boolean} [options.desc=false] - whether to sort descending
* @param {string} [options.sortComparator] override default with name of comparator registered in ComparatorMap
* @returns {ResultSet} Reference to this ResultSet, sorted, for future chain operations.
*/
simplesort(propname: keyof T, options?: boolean | ResultSet.SimpleSortOptions): this;
/**
* Allows sorting a ResultSet based on multiple columns.
* @example
* // to sort by age and then name (both ascending)
* rs.compoundsort(['age', 'name']);
* // to sort by age (ascending) and then by name (descending)
* rs.compoundsort(['age', ['name', true]);
* @param {array} properties - array of property names or subarray of [propertyname, isdesc] used evaluate sort order
* @returns {ResultSet} Reference to this ResultSet, sorted, for future chain operations.
*/
compoundsort(properties: (keyof T | [keyof T, boolean])[]): this;
/**
* Helper function for compoundsort(), performing individual object comparisons
* @param {Array} properties - array of property names, in order, by which to evaluate sort order
* @param {object} obj1 - first object to compare
* @param {object} obj2 - second object to compare
* @returns {number} 0, -1, or 1 to designate if identical (sortwise) or which should be first
*/
private _compoundeval(properties, obj1, obj2);
/**
* Sorts the ResultSet based on the last full-text-search scoring.
* @param {boolean} [ascending=false] - sort ascending
* @returns {ResultSet}
*/
sortByScoring(ascending?: boolean): this;
/**
* Returns the scoring of the last full-text-search.
* @returns {ScoreResult[]}
*/
getScoring(): Scorer.ScoreResult[];
/**
* Oversee the operation of OR'ed query expressions.
* OR'ed expression evaluation runs each expression individually against the full collection,
* and finally does a set OR on each expression's results.
* Each evaluation can utilize a binary index to prevent multiple linear array scans.
* @param {array} expressionArray - array of expressions
* @returns {ResultSet} this ResultSet for further chain ops.
*/
findOr(expressionArray: ResultSet.Query>[]): this;
$or(expressionArray: ResultSet.Query>[]): this;
/**
* Oversee the operation of AND'ed query expressions.
* AND'ed expression evaluation runs each expression progressively against the full collection,
* internally utilizing existing chained ResultSet functionality.
* Only the first filter can utilize a binary index.
* @param {array} expressionArray - array of expressions
* @returns {ResultSet} this ResultSet for further chain ops.
*/
findAnd(expressionArray: ResultSet.Query>[]): this;
$and(expressionArray: ResultSet.Query>[]): this;
/**
* Used for querying via a mongo-style query object.
*
* @param {object} query - A mongo-style query object used for filtering current results.
* @param {boolean} firstOnly - (Optional) Used by collection.findOne() - flag if this was invoked via findOne()
* @returns {ResultSet} this ResultSet for further chain ops.
*/
find(query?: ResultSet.Query>, firstOnly?: boolean): this;
/**
* Used for filtering via a javascript filter function.
* @param {function} fun - A javascript function used for filtering current results by.
* @returns {ResultSet} this ResultSet for further chain ops.
*/
where(fun: (obj: Doc) => boolean): this;
/**
* Returns the number of documents in the ResultSet.
* @returns {number} The number of documents in the ResultSet.
*/
count(): number;
/**
* Terminates the chain and returns array of filtered documents
* @param {object} options
* @param {boolean} [options.forceClones] - Allows forcing the return of cloned objects even when
* the collection is not configured for clone object.
* @param {string} [options.forceCloneMethod] - Allows overriding the default or collection specified cloning method.
* Possible values 'parse-stringify', 'deep', and 'shallow' and
* @param {boolean} [options.removeMeta] - will force clones and strip $loki and meta properties from documents
*
* @returns {Array} Array of documents in the ResultSet
*/
data(options?: ResultSet.DataOptions): Doc[];
/**
* Used to run an update operation on all documents currently in the ResultSet.
* @param {function} updateFunction - User supplied updateFunction(obj) will be executed for each document object.
* @returns {ResultSet} this ResultSet for further chain ops.
*/
update(updateFunction: (obj: Doc) => Doc): this;
/**
* Removes all document objects which are currently in ResultSet from collection (as well as ResultSet)
* @returns {ResultSet} this (empty) ResultSet for further chain ops.
*/
remove(): this;
/**
* data transformation via user supplied functions
*
* @param {function} mapFunction - this function accepts a single document for you to transform and return
* @param {function} reduceFunction - this function accepts many (array of map outputs) and returns single value
* @returns {value} The output of your reduceFunction
*/
mapReduce(mapFunction: (item: Doc, index: number, array: Doc[]) => U1, reduceFunction: (array: U1[]) => U2): U2;
/**
* Left joining two sets of data. Join keys can be defined or calculated properties
* eqJoin expects the right join key values to be unique. Otherwise left data will be joined on the last joinData object with that key
* @param {Array|ResultSet|Collection} joinData - Data array to join to.
* @param {(string|function)} leftJoinKey - Property name in this result set to join on or a function to produce a value to join on
* @param {(string|function)} rightJoinKey - Property name in the joinData to join on or a function to produce a value to join on
* @param {function} [mapFun=] - a function that receives each matching pair and maps them into output objects - function(left,right){return joinedObject}
* @param {object} [dataOptions=] - optional options to apply to data() calls for left and right sides
* @param {boolean} dataOptions.removeMeta - allows removing meta before calling mapFun
* @param {boolean} dataOptions.forceClones - forcing the return of cloned objects to your map object
* @param {string} dataOptions.forceCloneMethod - allows overriding the default or collection specified cloning method
* @returns {ResultSet} A ResultSet with data in the format [{left: leftObj, right: rightObj}]
*/
eqJoin(joinData: Collection | ResultSet | any[], leftJoinKey: string | ((obj: any) => string), rightJoinKey: string | ((obj: any) => string), mapFun?: (left: any, right: any) => any, dataOptions?: ResultSet.DataOptions): ResultSet;
/**
* Applies a map function into a new collection for further chaining.
* @param {function} mapFun - javascript map function
* @param {object} [dataOptions=] - options to data() before input to your map function
* @param {boolean} dataOptions.removeMeta - allows removing meta before calling mapFun
* @param {boolean} dataOptions.forceClones - forcing the return of cloned objects to your map object
* @param {string} dataOptions.forceCloneMethod - Allows overriding the default or collection specified cloning method
* @return {ResultSet}
*/
map(mapFun: (obj: Doc, index: number, array: Doc[]) => U, dataOptions?: ResultSet.DataOptions): ResultSet;
}
export declare namespace ResultSet {
interface DataOptions {
forceClones?: boolean;
forceCloneMethod?: CloneMethod;
removeMeta?: boolean;
}
interface SimpleSortOptions {
desc?: boolean;
sortComparator?: string;
}
type ContainsHelperType = R extends string ? string | string[] : R extends any[] ? R[number] | R[number][] : R extends object ? keyof R | (keyof R)[] : never;
type LokiOps = {
$eq?: R;
} | {
$ne?: R;
} | {
$gt?: R;
} | {
$gte?: R;
} | {
$lt?: R;
} | {
$lte?: R;
} | {
$between?: [R, R];
} | {
$in?: R[];
} | {
$nin?: R[];
} | {
$keyin?: object;
} | {
$nkeyin?: object;
} | {
$definedin?: object;
} | {
$undefinedin?: object;
} | {
$regex?: RegExp | string | [string, string];
} | {
$containsNone?: ContainsHelperType;
} | {
$containsAny?: ContainsHelperType;
} | {
$contains?: ContainsHelperType;
} | {
$type?: string;
} | {
$finite?: boolean;
} | {
$size?: number;
} | {
$len?: number;
} | {
$where?: (val?: R) => boolean;
};
type Query = {
[P in keyof T]?: LokiOps | T[P];
} & {
$and?: Query[];
} & {
$or?: Query[];
} & {
$fts?: FullTextSearchQuery;
};
}
================================================
FILE: dist/packages/fs-storage/types/loki/src/unique_index.d.ts
================================================
export declare class UniqueIndex {
private _field;
private _lokiMap;
private _valMap;
/**
* Constructs an unique index object.
* @param {string} propertyField - the property field to index
*/
constructor(propertyField: string);
/**
* Sets a document's unique index.
* @param {number} id loki id to associate with value
* @param {*} value value to associate with id
*/
set(id: number, value: any): void;
/**
* Returns the $loki id of an unique value.
* @param {*} value the value to retrieve a loki id match for
*/
get(value: any): number;
/**
* Updates a document's unique index.
* @param {number} id (loki) id of document to update the value to
* @param {*} value value to associate with loki id
*/
update(id: number, value: any): void;
/**
* Removes an unique index.
* @param {number} id (loki) id to remove from index
*/
remove(id: number): void;
/**
* Clears the unique index.
*/
clear(): void;
}
================================================
FILE: dist/packages/fs-storage/types/memory-storage/src/index.d.ts
================================================
import { MemoryStorage } from "./memory_storage";
export { MemoryStorage };
export default MemoryStorage;
================================================
FILE: dist/packages/fs-storage/types/memory-storage/src/memory_storage.d.ts
================================================
import { Dict, StorageAdapter } from "../../common/types";
/**
* An in-memory persistence adapter for an in-memory database.
* This simple 'key/value' adapter is intended for unit testing and diagnostics.
*/
export declare class MemoryStorage implements StorageAdapter {
hashStore: Dict<{
savecount: number;
lastsave: Date;
value: string;
}>;
options: MemoryStorage.Options;
/**
* Registers the local storage as plugin.
*/
static register(): void;
/**
* Deregisters the local storage as plugin.
*/
static deregister(): void;
/**
* @param {object} options - memory storage options
* @param {boolean} [options.asyncResponses=false] - whether callbacks are invoked asynchronously (default: false)
* @param {int} [options.asyncTimeout=50] - timeout in ms to queue callbacks (default: 50)
*/
constructor(options?: MemoryStorage.Options);
/**
* Loads a serialized database from its in-memory store.
* (Loki persistence adapter interface function)
*
* @param {string} dbname - name of the database (filename/keyname)
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* Saves a serialized database to its in-memory store.
* (Loki persistence adapter interface function)
*
* @param {string} dbname - name of the database (filename/keyname)
* @param {string} dbstring - the database content
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* Deletes a database from its in-memory store.
*
* @param {string} dbname - name of the database (filename/keyname)
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
}
export declare namespace MemoryStorage {
interface Options {
asyncResponses?: boolean;
asyncTimeout?: number;
}
}
================================================
FILE: dist/packages/fs-storage/types/partitioning-adapter/src/index.d.ts
================================================
import { PartitioningAdapter } from "./partitioning_adapter";
export { PartitioningAdapter };
export default PartitioningAdapter;
================================================
FILE: dist/packages/fs-storage/types/partitioning-adapter/src/partitioning_adapter.d.ts
================================================
import { Loki } from "../../loki/src/loki";
import { StorageAdapter } from "../../common/types";
/**
* An adapter for adapters. Converts a non reference mode adapter into a reference mode adapter
* which can perform destructuring and partitioning. Each collection will be stored in its own key/save and
* only dirty collections will be saved. If you turn on paging with default page size of 25megs and save
* a 75 meg collection it should use up roughly 3 save slots (key/value pairs sent to inner adapter).
* A dirty collection that spans three pages will save all three pages again
* Paging mode was added mainly because Chrome has issues saving 'too large' of a string within a
* single IndexedDB row. If a single document update causes the collection to be flagged as dirty, all
* of that collection's pages will be written on next save.
*/
export declare class PartitioningAdapter implements StorageAdapter {
mode: string;
private _adapter;
private _dbref;
private _dbname;
private _pageIterator;
private _paging;
private _pageSize;
private _delimiter;
private _dirtyPartitions;
/**
* Registers the partitioning adapter as plugin.
*/
static register(): void;
/**
* Deregisters the partitioning storage as plugin.
*/
static deregister(): void;
/**
* @param {object} adapter - reference to a 'non-reference' mode loki adapter instance.
* @param {boolean} paging - (default: false) set to true to enable paging collection data.
* @param {number} pageSize - (default : 25MB) you can use this to limit size of strings passed to inner adapter.
* @param {string} delimiter - allows you to override the default delimiter
*/
constructor(adapter: StorageAdapter, {paging, pageSize, delimiter}?: {
paging?: boolean;
pageSize?: number;
delimiter?: string;
});
/**
* Loads a database which was partitioned into several key/value saves.
* (Loki persistence adapter interface function)
*
* @param {string} dbname - name of the database (filename/keyname)
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* Used to sequentially load each collection partition, one at a time.
*
* @param {int} partition - ordinal collection position to load next
* @returns {Promise} a Promise that resolves after the next partition is loaded
*/
private _loadNextPartition(partition);
/**
* Used to sequentially load the next page of collection partition, one at a time.
*
* @returns {Promise} a Promise that resolves after the next page is loaded
*/
private _loadNextPage();
/**
* Saves a database by partioning into separate key/value saves.
* (Loki 'reference mode' persistence adapter interface function)
*
* @param {string} dbname - name of the database (filename/keyname)
* @param {object} dbref - reference to database which we will partition and save.
* @returns {Promise} a Promise that resolves after the database was deleted
*
*/
exportDatabase(dbname: string, dbref: Loki): Promise;
/**
* Helper method used internally to save each dirty collection, one at a time.
*
* @returns {Promise} a Promise that resolves after the next partition is saved
*/
private _saveNextPartition();
/**
* Helper method used internally to generate and save the next page of the current (dirty) partition.
*
* @returns {Promise} a Promise that resolves after the next partition is saved
*/
private _saveNextPage();
}
================================================
FILE: dist/packages/full-text-search/lokidb.full-text-search.js
================================================
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("@lokidb/full-text-search", [], factory);
else if(typeof exports === 'object')
exports["@lokidb/full-text-search"] = factory();
else
{ root["@lokidb/full-text-search"] = factory(); root["LokiFullTextSearch"] = root["@lokidb/full-text-search"].default; }
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PLUGINS; });
function getGlobal() {
let glob;
(function (global) {
glob = global;
})(global !== undefined && global || this);
return glob;
}
function create() {
const global = getGlobal();
const sym = Symbol.for("LOKI");
if (global[sym] === undefined) {
global[sym] = {};
}
return global[sym];
}
/**
* @hidden
*/
const PLUGINS = create();
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(2)))
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// CONCATENATED MODULE: ./packages/full-text-search/src/analyzer/tokenizer.ts
/**
* Splits a string at whitespace characters into tokens.
* @param {string} value - the string
* @returns {string[]} - the tokens
*/
function whitespaceTokenizer(value) {
return value.split(/[\s]+/);
}
// CONCATENATED MODULE: ./packages/full-text-search/src/analyzer/token_filter.ts
/**
* Converts a token to lowercase.
* @param {string} token - the token
* @returns {string} - the lowercased token
*/
function lowercaseTokenFilter(token) {
return token.toLowerCase();
}
/**
* Converts a token to uppercase.
* @param {string} token - the token
* @returns {string} - the uppercased token
*/
function uppercaseTokenFilter(token) {
return token.toUpperCase();
}
// CONCATENATED MODULE: ./packages/full-text-search/src/analyzer/analyzer.ts
/**
* Analyzes a given string.
* @param {Analyzer} analyzer - the analyzer
* @param {string} str - the string
* @returns {string[]} - the tokens
*/
function analyze(analyzer, str) {
if (analyzer.char_filter) {
for (let j = 0; j < analyzer.char_filter.length; j++) {
str = analyzer.char_filter[j](str);
}
}
const tokens = analyzer.tokenizer(str);
if (analyzer.token_filter) {
for (let i = 0; i < tokens.length; i++) {
for (let k = 0; k < analyzer.token_filter.length; k++) {
tokens[i] = analyzer.token_filter[k](tokens[i], i, tokens);
}
}
}
// Remove empty tokens.
return tokens.filter((token) => token);
}
/**
* An analyzer with the whitespace tokenizer and the lowercase token filter.
*/
class analyzer_StandardAnalyzer {
constructor() {
this.tokenizer = whitespaceTokenizer;
this.token_filter = [lowercaseTokenFilter];
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/inverted_index.ts
/**
* Converts a string into an array of code points.
* @param str - the string
* @returns {number[]} to code points
* @hidden
*/
function toCodePoints(str) {
const r = [];
for (let i = 0; i < str.length;) {
const chr = str.charCodeAt(i++);
if (chr >= 0xD800 && chr <= 0xDBFF) {
// surrogate pair
const low = str.charCodeAt(i++);
r.push(0x10000 + ((chr - 0xD800) << 10) | (low - 0xDC00));
}
else {
// ordinary character
r.push(chr);
}
}
return r;
}
/**
* Inverted index class handles featured text search for specific document fields.
* @hidden
*/
class inverted_index_InvertedIndex {
/**
* @param {boolean} [options.store=true] - inverted index will be stored at serialization rather than rebuilt on load
* @param {boolean} [options.optimizeChanges=true] - flag to store additional metadata inside the index for better
* performance if an existing field is updated or removed
* @param {Analyzer} [options.analyzer=] - the analyzer of this inverted index
*/
constructor(options = {}) {
this.docCount = 0;
this.docStore = new Map();
this.totalFieldLength = 0;
this.root = new Map();
({
store: this._store = true,
optimizeChanges: this._optimizeChanges = true,
analyzer: this.analyzer = new analyzer_StandardAnalyzer()
} = options);
}
/**
* Adds defined fields of a document to the inverted index.
* @param {string} field - the field to add
* @param {number} docId - the doc id of the field
*/
insert(field, docId) {
if (this.docStore.has(docId)) {
throw Error("Field already added.");
}
// Tokenize document field.
const fieldTokens = analyze(this.analyzer, field);
if (fieldTokens.length == 0) {
// Add empty field at least to document store for query 'exists'.
this.docStore.set(docId, { fieldLength: 0 });
return;
}
this.totalFieldLength += fieldTokens.length;
this.docCount += 1;
this.docStore.set(docId, { fieldLength: fieldTokens.length });
// Holds references to each index of a document.
const indexRef = [];
if (this._optimizeChanges) {
Object.defineProperties(this.docStore.get(docId), {
indexRef: { enumerable: false, configurable: true, writable: true, value: indexRef }
});
}
// Iterate over all unique field terms.
for (const token of new Set(fieldTokens)) {
// Calculate term frequency.
let tf = 0;
for (let j = 0; j < fieldTokens.length; j++) {
if (fieldTokens[j] === token) {
++tf;
}
}
// Add term to index tree.
let branch = this.root;
for (const c of toCodePoints(token)) {
let child = branch.get(c);
if (child === undefined) {
child = new Map();
if (this._optimizeChanges) {
child.pa = branch;
}
branch.set(c, child);
}
branch = child;
}
// Add term info to index leaf.
if (branch.dc === undefined) {
branch.dc = new Map();
branch.df = 0;
}
branch.dc.set(docId, tf);
branch.df += 1;
// Store index leaf for deletion.
indexRef.push(branch);
}
}
/**
* Removes all relevant terms of a document from the inverted index.
* @param {number} docId - the document.
*/
remove(docId) {
if (!this.docStore.has(docId)) {
return;
}
const docStore = this.docStore.get(docId);
// Remove document.
this.docStore.delete(docId);
if (docStore.fieldLength === 0) {
return;
}
this.docCount -= 1;
// Reduce total field length.
this.totalFieldLength -= docStore.fieldLength;
if (this._optimizeChanges) {
// Iterate over all term references.
// Remove docId from docs and decrement document frequency.
const indexRef = docStore.indexRef;
for (let j = 0; j < indexRef.length; j++) {
let index = indexRef[j];
index.df -= 1;
index.dc.delete(docId);
// Check if no document is left for current tree.
if (index.df === 0) {
// Delete unused meta data of branch.
delete index.df;
delete index.dc;
// Check for sub branches.
if (index.size !== 0) {
continue;
}
// Delete term branch if not used anymore.
do {
// Go tree upwards.
const parent = index.pa;
// Delete parent reference for preventing memory leak (cycle reference).
delete index.pa;
// Iterate over all children.
for (const key of parent.keys()) {
// Remove previous child form parent.
if (parent.get(key) === index) {
parent.delete(key);
break;
}
}
index = parent;
} while (index.pa !== undefined && index.size === 0 && index.df === undefined);
}
}
}
else {
this._remove(this.root, docId);
}
}
/**
* Gets the term index of a term.
* @param {string} term - the term
* @param {object} root - the term index to start from
* @param {number} start - the position of the term string to start from
* @return {object} - The term index or null if the term is not in the term tree.
*/
static getTermIndex(term, root, start = 0) {
if (start >= term.length) {
return null;
}
for (let i = start; i < term.length; i++) {
let child = root.get(term[i]);
if (child === undefined) {
return null;
}
root = child;
}
return root;
}
/**
* Extends a term index to all available term leafs.
* @param {object} idx - the term index to start from
* @param {number[]} [term=[]] - the current term
* @param {Array} termIndices - all extended indices with their term
* @returns {Array} - Array with term indices and extension
*/
static extendTermIndex(idx, term = [], termIndices = []) {
if (idx.df !== undefined) {
termIndices.push({ index: idx, term: term.slice() });
}
term.push(0);
for (const child of idx) {
term[term.length - 1] = child[0];
inverted_index_InvertedIndex.extendTermIndex(child[1], term, termIndices);
}
term.pop();
return termIndices;
}
/**
* Serialize the inverted index.
* @returns {{docStore: *, _fields: *, index: *}}
*/
toJSON() {
if (this._store) {
return {
_store: true,
_optimizeChanges: this._optimizeChanges,
docCount: this.docCount,
docStore: [...this.docStore],
totalFieldLength: this.totalFieldLength,
root: inverted_index_InvertedIndex._serializeIndex(this.root)
};
}
return {
_store: false,
_optimizeChanges: this._optimizeChanges,
};
}
/**
* Deserialize the inverted index.
* @param {{docStore: *, _fields: *, index: *}} serialized - The serialized inverted index.
* @param {Analyzer} analyzer[undefined] - an analyzer
*/
static fromJSONObject(serialized, analyzer) {
const invIdx = new inverted_index_InvertedIndex({
store: serialized._store,
optimizeChanges: serialized._optimizeChanges,
analyzer: analyzer
});
if (serialized._store) {
invIdx.docCount = serialized.docCount;
invIdx.docStore = new Map(serialized.docStore);
invIdx.totalFieldLength = serialized.totalFieldLength;
invIdx.root = inverted_index_InvertedIndex._deserializeIndex(serialized.root);
}
if (invIdx._optimizeChanges) {
invIdx._regenerate(invIdx.root, null);
}
return invIdx;
}
static _serializeIndex(idx) {
const serialized = {};
if (idx.dc !== undefined) {
serialized.d = { df: idx.df, dc: [...idx.dc] };
}
if (idx.size === 0) {
return serialized;
}
const keys = [];
const values = [];
for (const child of idx) {
keys.push(child[0]);
values.push(inverted_index_InvertedIndex._serializeIndex(child[1]));
}
serialized.k = keys;
serialized.v = values;
return serialized;
}
static _deserializeIndex(serialized) {
const idx = new Map();
if (serialized.k !== undefined) {
for (let i = 0; i < serialized.k.length; i++) {
idx.set(serialized.k[i], inverted_index_InvertedIndex._deserializeIndex(serialized.v[i]));
}
}
if (serialized.d !== undefined) {
idx.df = serialized.d.df;
idx.dc = new Map(serialized.d.dc);
}
return idx;
}
/**
* Set parent of to each index and regenerate the indexRef.
* @param {Index} index - the index
* @param {Index} parent - the parent
*/
_regenerate(index, parent) {
// Set parent.
if (parent !== null) {
index.pa = parent;
}
// Iterate over subtree.
for (const child of index.values()) {
this._regenerate(child, index);
}
if (index.dc !== undefined) {
// Get documents of term.
for (const docId of index.dc.keys()) {
// Get document store at specific document/field.
const ref = this.docStore.get(docId);
if (ref.indexRef === undefined) {
Object.defineProperties(ref, {
indexRef: { enumerable: false, configurable: true, writable: true, value: [] }
});
}
// Set reference to term index.
ref.indexRef.push(index);
}
}
}
/**
* Iterate over the whole inverted index and remove the document.
* Delete branch if not needed anymore.
* Function is needed if index is used without optimization.
* @param {Index} idx - the index
* @param {number} docId - the doc id
* @returns {boolean} true if index is empty
*/
_remove(idx, docId) {
for (const child of idx) {
// Checkout branch.
if (this._remove(child[1], docId)) {
idx.delete(child[0]);
}
}
// Remove docId from docs and decrement document frequency.
if (idx.df !== undefined) {
if (idx.dc.has(docId)) {
idx.df -= 1;
idx.dc.delete(docId);
// Delete unused meta data of branch.
if (idx.df === 0) {
delete idx.df;
delete idx.dc;
}
}
}
return idx.size === 0 && idx.dc === undefined;
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/scorer.ts
/**
* @hidden
*/
class Scorer {
constructor(invIdxs) {
this._cache = {};
this._invIdxs = invIdxs;
}
setDirty() {
this._cache = {};
}
score(fieldName, boost, termIdx, doScoring, queryResults, term, df = 0) {
if (termIdx === null || termIdx.dc === undefined) {
return;
}
const idf = this._idf(fieldName, df || termIdx.df);
for (const [docId, tf] of termIdx.dc) {
if (!queryResults.has(docId)) {
queryResults.set(docId, []);
}
if (doScoring === true) {
// BM25 scoring.
queryResults.get(docId).push({ tf, idf, boost, fieldName, term });
}
else if (doScoring === false) {
// Constant scoring.
queryResults.set(docId, [{ boost }]);
}
else {
// Zero scoring.
queryResults.set(docId, [{ boost: 0 }]);
}
}
}
scoreConstant(boost, docId, queryResults) {
if (!queryResults.has(docId)) {
queryResults.set(docId, []);
}
queryResults.get(docId).push({ boost });
return queryResults;
}
finalScore(query, queryResults) {
const finalResult = {};
const k1 = query.bm25 !== undefined ? query.bm25.k1 : 1.2;
const b = query.bm25 !== undefined ? query.bm25.b : 0.75;
const explain = query.explain !== undefined ? query.explain : false;
for (const [docId, result] of queryResults) {
let docScore = 0;
let docExplanation = [];
for (let i = 0; i < result.length; i++) {
const queryResult = result[i];
let score = 0;
if (queryResult.tf !== undefined) {
// BM25 scoring.
const tf = queryResult.tf;
const fieldLength = Scorer._calculateFieldLength(this._invIdxs[queryResult.fieldName].docStore.get(docId)
.fieldLength);
const avgFieldLength = this._avgFieldLength(queryResult.fieldName);
const tfNorm = (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * (fieldLength / avgFieldLength)));
score = queryResult.idf * tfNorm * queryResult.boost;
if (explain) {
docExplanation.push({
boost: queryResult.boost,
score: score,
docID: docId,
fieldName: queryResult.fieldName,
index: String.fromCharCode(...queryResult.term),
idf: queryResult.idf,
tfNorm: tfNorm,
tf: tf,
fieldLength: fieldLength,
avgFieldLength: avgFieldLength,
});
}
}
else {
// Constant scoring.
score = queryResult.boost;
if (explain) {
docExplanation.push({
boost: queryResult.boost,
score: score
});
}
}
docScore += score;
}
if (explain) {
finalResult[docId] = {
score: docScore,
explanation: docExplanation
};
}
else {
finalResult[docId] = {
score: docScore
};
}
}
return finalResult;
}
static _calculateFieldLength(fieldLength) {
// Dummy function to be compatible to lucene in unit tests.
return fieldLength;
}
_getCache(fieldName) {
if (this._cache[fieldName] === undefined) {
const avgFieldLength = this._invIdxs[fieldName].totalFieldLength / this._invIdxs[fieldName].docCount;
this._cache[fieldName] = { idfs: {}, avgFieldLength };
}
return this._cache[fieldName];
}
/**
* Returns the idf by either calculate it or use a cached one.
* @param {string} fieldName - the name of the field
* @param {number} docFreq - the doc frequency of the term
* @returns {number} the idf
* @private
*/
_idf(fieldName, docFreq) {
const cache = this._getCache(fieldName);
if (cache.idfs[docFreq] !== undefined) {
return cache.idfs[docFreq];
}
return cache.idfs[docFreq] = Math.log(1 + (this._invIdxs[fieldName].docCount - docFreq + 0.5) / (docFreq + 0.5));
}
_avgFieldLength(fieldName) {
return this._getCache(fieldName).avgFieldLength;
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/run_automaton.ts
/**
* From org/apache/lucene/util/automaton/RunAutomaton.java
* @hidden
*/
class RunAutomaton {
constructor(automaton) {
const size = automaton.getNumStates();
this._points = automaton.getStartPoints();
this._accept = new Array(size);
this._transitions = new Array(size * this._points.length);
for (let n = 0; n < size; n++) {
this._accept[n] = automaton.isAccept(n);
for (let c = 0; c < this._points.length; c++) {
// assert dest === -1 || dest < size;
this._transitions[n * this._points.length + c] = automaton.step(n, this._points[c]);
}
}
this._classmap = new Array(256 /* alphaSize */);
for (let i = 0, j = 0; j < this._classmap.length; j++) {
if (i + 1 < this._points.length && j === this._points[i + 1]) {
i++;
}
this._classmap[j] = i;
}
}
getCharClass(c) {
// binary search
let a = 0;
let b = this._points.length;
while (b - a > 1) {
const d = (a + b) >>> 1;
if (this._points[d] > c) {
b = d;
}
else if (this._points[d] < c) {
a = d;
}
else {
return d;
}
}
return a;
}
step(state, c) {
if (c >= this._classmap.length) {
return this._transitions[state * this._points.length + this.getCharClass(c)];
}
else {
return this._transitions[state * this._points.length + this._classmap[c]];
}
}
isAccept(state) {
return this._accept[state];
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/automaton.ts
/**
* @type {number}
* @hidden
*/
const MIN_CODE_POINT = 0;
/**
* @type {number}
* @hidden
*/
const MAX_CODE_POINT = 1114111;
function sortByDestMinMax(a, b) {
if (a[0] < b[0]) {
return -1;
}
else if (a[0] > b[0]) {
return 1;
}
if (a[1] < b[1]) {
return -1;
}
else if (a[1] > b[1]) {
return 1;
}
if (a[2] < b[2]) {
return -1;
}
else if (a[2] > b[2]) {
return 1;
}
return 0;
}
function sortByMinMaxDest(a, b) {
if (a[1] < b[1]) {
return -1;
}
else if (a[1] > b[1]) {
return 1;
}
if (a[2] < b[2]) {
return -1;
}
else if (a[2] > b[2]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
else if (a[0] > b[0]) {
return 1;
}
return 0;
}
/**
* From org/apache/lucene/util/automaton/Automaton.java
* @hidden
*/
class Automaton {
constructor() {
this._stateTransitions = [];
this._stateTransitions = [];
this._accept = new Set();
this._nextState = 0;
this._currState = -1;
// this.deterministic = true;
this._transitions = {};
}
isAccept(n) {
return this._accept.has(n);
}
createState() {
return this._nextState++;
}
setAccept(state, accept) {
if (accept) {
this._accept.add(state);
}
else {
this._accept.delete(state);
}
}
finishState() {
if (this._currState !== -1) {
this._finishCurrentState();
this._currState = -1;
}
}
_finishCurrentState() {
// Sort all transitions.
this._stateTransitions.sort(sortByDestMinMax);
let upto = 0;
let p = [-1, -1, -1];
for (let i = 0, len = this._stateTransitions.length; i < len; i++) {
let t = this._stateTransitions[i];
if (p[0] === t[0]) {
if (t[1] <= p[2] + 1) {
if (t[2] > p[2]) {
p[2] = t[2];
}
}
else {
if (p[0] !== -1) {
this._stateTransitions[upto][0] = p[0];
this._stateTransitions[upto][1] = p[1];
this._stateTransitions[upto][2] = p[2];
upto++;
}
p[1] = t[1];
p[2] = t[2];
}
}
else {
if (p[0] !== -1) {
this._stateTransitions[upto][0] = p[0];
this._stateTransitions[upto][1] = p[1];
this._stateTransitions[upto][2] = p[2];
upto++;
}
p[0] = t[0];
p[1] = t[1];
p[2] = t[2];
}
}
if (p[0] !== -1) {
// Last transition
this._stateTransitions[upto][0] = p[0];
this._stateTransitions[upto][1] = p[1];
this._stateTransitions[upto][2] = p[2];
upto++;
}
this._transitions[this._currState] = this._stateTransitions.slice(0, upto).sort(sortByMinMaxDest);
// if (this.deterministic && upto > 1) {
// let lastMax = this.stateTransitions[0][2];
// for (let i = 1; i < upto; i++) {
// let min = this.stateTransitions[i][1];
// if (min <= lastMax) {
// this.deterministic = false;
// break;
// }
// lastMax = this.stateTransitions[i][2];
// }
// }
this._stateTransitions = [];
}
getStartPoints() {
const pointset = new Set();
pointset.add(MIN_CODE_POINT);
const states = Object.keys(this._transitions);
for (let i = 0; i < states.length; i++) {
let trans = this._transitions[states[i]];
for (let j = 0; j < trans.length; j++) {
let tran = trans[j];
pointset.add(tran[1]);
if (tran[2] < MAX_CODE_POINT) {
pointset.add(tran[2] + 1);
}
}
}
return Array.from(pointset).sort((a, b) => a - b);
}
step(state, label) {
let trans = this._transitions[state];
if (trans) {
for (let i = 0; i < trans.length; i++) {
let tran = trans[i];
if (tran[1] <= label && label <= tran[2]) {
return tran[0];
}
}
}
return -1;
}
getNumStates() {
return this._nextState;
}
addTransition(source, dest, min, max) {
if (this._currState !== source) {
if (this._currState !== -1) {
this._finishCurrentState();
}
this._currState = source;
}
this._stateTransitions.push([dest, min, max]);
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/long.ts
/**
* Class supports 64Bit integer operations.
* A cut-down version of dcodeIO/long.js.
* @hidden
*/
class Long {
constructor(low = 0, high = 0) {
this._low = low;
this._high = high;
}
/**
* Returns this long with bits arithmetically shifted to the right by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftRight(numBits) {
if ((numBits &= 63) === 0)
return this;
else if (numBits < 32)
return new Long((this._low >>> numBits) | (this._high << (32 - numBits)), this._high >> numBits);
else
return new Long((this._high >> (numBits - 32)), this._high >= 0 ? 0 : -1);
}
/**
* Returns this long with bits arithmetically shifted to the left by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftLeft(numBits) {
if ((numBits &= 63) === 0)
return this;
else if (numBits < 32)
return new Long(this._low << numBits, (this._high << numBits) | (this._low >>> (32 - numBits)));
else
return new Long(0, this._low << (numBits - 32));
}
/**
* Returns the bitwise AND of this Long and the specified.
* @param {Long} other - the other Long
* @returns {Long} the long
*/
and(other) {
return new Long(this._low & other._low, this._high & other._high);
}
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
* @returns {number}
*/
toInt() {
return this._low;
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/parametric_description.ts
const MASKS = [new Long(0x1), new Long(0x3), new Long(0x7), new Long(0xf),
new Long(0x1f), new Long(0x3f), new Long(0x7f), new Long(0xff),
new Long(0x1ff), new Long(0x3ff), new Long(0x7ff), new Long(0xfff),
new Long(0x1fff), new Long(0x3fff), new Long(0x7fff), new Long(0xffff),
new Long(0xf, 0x1fff), new Long(0xf, 0x3fff), new Long(0xf, 0x7fff), new Long(0xf, 0xffff),
new Long(0xff, 0x1fff), new Long(0xff, 0x3fff), new Long(0xff, 0x7fff), new Long(0xff, 0xffff),
new Long(0xfff, 0x1fff), new Long(0xfff, 0x3fff), new Long(0xfff, 0x7fff), new Long(0xfff, 0xffff),
new Long(0xffff, 0x1fff), new Long(0xffff, 0x3fff), new Long(0xffff, 0x7fff), new Long(0xffff, 0xffff),
new Long(0xfffff, 0x1fff), new Long(0xfffff, 0x3fff), new Long(0xfffff, 0x7fff), new Long(0xfffff, 0xffff),
new Long(0xffffff, 0x1fff), new Long(0xffffff, 0x3fff), new Long(0xffffff, 0x7fff), new Long(0xffffff, 0xffff),
new Long(0xfffffff, 0x1fff), new Long(0xfffffff, 0x3fff), new Long(0xfffffff, 0x7fff), new Long(0xfffffff, 0xffff),
new Long(0xffffffff, 0x1fff), new Long(0xffffffff, 0x3fff), new Long(0xffffffff, 0x7fff), new Long(0xffffffff, 0xffff),
new Long(0xfffffffff, 0x1fff), new Long(0xfffffffff, 0x3fff), new Long(0xfffffffff, 0x7fff), new Long(0xfffffffff, 0xffff),
new Long(0xffffffffff, 0x1fff), new Long(0xffffffffff, 0x3fff), new Long(0xffffffffff, 0x7fff), new Long(0xffffffffff, 0xffff),
new Long(0xfffffffffff, 0x1fff), new Long(0xfffffffffff, 0x3fff), new Long(0xfffffffffff, 0x7fff), new Long(0xfffffffffff, 0xffff),
new Long(0xffffffffffff, 0x1fff), new Long(0xffffffffffff, 0x3fff), new Long(0xffffffffffff, 0x7fff)];
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java#ParametricDescription
* @hidden
*/
class ParametricDescription {
constructor(w, n, minErrors) {
this._w = w;
this._n = n;
this._minErrors = minErrors;
}
/**
* Return the number of states needed to compute a Levenshtein DFA
*/
size() {
return this._minErrors.length * (this._w + 1);
}
/**
* Returns true if the state in any Levenshtein DFA is an accept state (final state).
*/
isAccept(absState) {
// decode absState -> state, offset
let state = Math.floor(absState / (this._w + 1));
let offset = absState % (this._w + 1);
//assert offset >= 0;
return this._w - offset + this._minErrors[state] <= this._n;
}
/**
* Returns the position in the input word for a given state.
* This is the minimal boundary for the state.
*/
getPosition(absState) {
return absState % (this._w + 1);
}
static unpack(data, index, bitsPerValue) {
const bitLoc = bitsPerValue * index;
const dataLoc = (bitLoc >> 6);
const bitStart = (bitLoc & 63);
if (bitStart + bitsPerValue <= 64) {
// not split
return data[dataLoc].shiftRight(bitStart).and(MASKS[bitsPerValue - 1]).toInt();
}
else {
// split
const part = 64 - bitStart;
return (data[dataLoc].shiftRight(bitStart).and(MASKS[part - 1])).toInt()
+ (data[1 + dataLoc].and(MASKS[bitsPerValue - part - 1]).shiftLeft(part)).toInt();
}
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/lev1t_parametric_description.ts
// 1 vectors; 2 states per vector; array length = 2
const toStates0 = [new Long(0x2)];
const offsetIncrs0 = [new Long(0x0)];
// 2 vectors; 3 states per vector; array length = 6
const toStates1 = [new Long(0xa43)];
const offsetIncrs1 = [new Long(0x38)];
// 4 vectors; 6 states per vector; array length = 24
const toStates2 = [new Long(0x82140003, 0x34534914), new Long(0x6d)];
const offsetIncrs2 = [new Long(0x55a20000, 0x5555)];
// 8 vectors; 6 states per vector; array length = 48
const toStates3 = [new Long(0x900C0003, 0x21520854), new Long(0x4534916d, 0x5b4d19a2), new Long(0xda34)];
const offsetIncrs3 = [new Long(0x20fc0000, 0x5555ae0a), new Long(0x55555555)];
// state map
// 0 -> [(0, 0)]
// 1 -> [(0, 1)]
// 2 -> [(0, 1), (1, 1)]
// 3 -> [(0, 1), (2, 1)]
// 4 -> [t(0, 1), (0, 1), (1, 1), (2, 1)]
// 5 -> [(0, 1), (1, 1), (2, 1)]
/**
* From org/apache/lucene/util/automaton/Lev1TParametricDescription.java
* @hidden
*/
class lev1t_parametric_description_Lev1TParametricDescription extends ParametricDescription {
constructor(w) {
super(w, 1, [0, 1, 0, -1, -1, -1]);
}
transition(absState, position, vector) {
// null absState should never be passed in
//assert absState != -1;
// decode absState -> state, offset
let state = Math.floor(absState / (this._w + 1));
let offset = absState % (this._w + 1);
//assert offset >= 0;
if (position === this._w) {
if (state < 2) {
const loc = vector * 2 + state;
offset += ParametricDescription.unpack(offsetIncrs0, loc, 1);
state = ParametricDescription.unpack(toStates0, loc, 2) - 1;
}
}
else if (position === this._w - 1) {
if (state < 3) {
const loc = vector * 3 + state;
offset += ParametricDescription.unpack(offsetIncrs1, loc, 1);
state = ParametricDescription.unpack(toStates1, loc, 2) - 1;
}
}
else if (position === this._w - 2) {
if (state < 6) {
const loc = vector * 6 + state;
offset += ParametricDescription.unpack(offsetIncrs2, loc, 2);
state = ParametricDescription.unpack(toStates2, loc, 3) - 1;
}
}
else {
if (state < 6) {
const loc = vector * 6 + state;
offset += ParametricDescription.unpack(offsetIncrs3, loc, 2);
state = ParametricDescription.unpack(toStates3, loc, 3) - 1;
}
}
if (state === -1) {
// null state
return -1;
}
else {
// translate back to abs
return state * (this._w + 1) + offset;
}
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/lev2t_parametric_description.ts
// 1 vectors; 3 states per vector; array length = 3
const lev2t_parametric_description_toStates0 = /*2 bits per value */ [
new Long(0x23)
];
const lev2t_parametric_description_offsetIncrs0 = /*1 bits per value */ [
new Long(0x0)
];
// 2 vectors; 5 states per vector; array length = 10
const lev2t_parametric_description_toStates1 = /*3 bits per value */ [
new Long(0x13688b44)
];
const lev2t_parametric_description_offsetIncrs1 = /*1 bits per value */ [
new Long(0x3e0)
];
// 4 vectors; 13 states per vector; array length = 52
const lev2t_parametric_description_toStates2 = /*4 bits per value */ [
new Long(0x5200b504, 0x60dbb0b0), new Long(0x27062227, 0x52332176), new Long(0x14323235, 0x23555432), new Long(0x4354)
];
const lev2t_parametric_description_offsetIncrs2 = /*2 bits per value */ [
new Long(0x00002000, 0x555080a8), new Long(0x55555555, 0x55)
];
// 8 vectors; 28 states per vector; array length = 224
const lev2t_parametric_description_toStates3 = /*5 bits per value */ [
new Long(0x40059404, 0xe701c029), new Long(0x00a50000, 0xa0101620), new Long(0xa1416288, 0xb02c8c40), new Long(0x310858c0, 0xa821032),
new Long(0x0d28b201, 0x31442398), new Long(0x847788e0, 0x5281e528), new Long(0x08c2280e, 0xa23980d3), new Long(0xa962278c, 0x1e3294b1),
new Long(0x2288e528, 0x8c41309e), new Long(0x021aca21, 0x11444409), new Long(0x86b1086b, 0x11a46248), new Long(0x1d6240c4, 0x2a625894),
new Long(0x489074ad, 0x5024a50b), new Long(0x520c411a, 0x14821aca), new Long(0x0b594a44, 0x5888b589), new Long(0xc411a465, 0x941d6520),
new Long(0xad6a62d4, 0x8b589075), new Long(0x1a5055a4)
];
const lev2t_parametric_description_offsetIncrs3 = /*2 bits per value */ [
new Long(0x00002000, 0x30c302), new Long(0xc3fc333c, 0x2a0030f3), new Long(0x8282a820, 0x233a0032), new Long(0x32b283a8, 0x55555555),
new Long(0x55555555, 0x55555555), new Long(0x55555555, 0x55555555), new Long(0x55555555, 0x55555555)
];
// 16 vectors; 45 states per vector; array length = 720
const toStates4 = /*6 bits per value */ [
new Long(0x002c5004, 0x3801450), new Long(0x00000e38, 0xc500014b), new Long(0x51401402, 0x514), new Long(0x0),
new Long(0x14010000, 0x518000b), new Long(0x28e20230, 0x9f1c208), new Long(0x830a70c2, 0x219f0df0), new Long(0x08208200, 0x82000082),
new Long(0x60800800, 0x8050501), new Long(0x02602643, 0x30820986), new Long(0x50508064, 0x45640142), new Long(0x20000831, 0x8500514),
new Long(0x85002082, 0x41405820), new Long(0x0990c201, 0x45618098), new Long(0x50a01051, 0x8316d0c), new Long(0x050df0e0, 0x21451420),
new Long(0x14508214, 0xd142140), new Long(0x50821c60, 0x3c21c018), new Long(0xcb142087, 0x1cb1403), new Long(0x1851822c, 0x80082145),
new Long(0x20800020, 0x200208), new Long(0x87180345, 0xd0061820), new Long(0x24976b09, 0xcb0a81cb), new Long(0x624709d1, 0x8b1a60e),
new Long(0x82249089, 0x2490820), new Long(0x00d2c024, 0xc31421c6), new Long(0x15454423, 0x3c314515), new Long(0xc21cb140, 0x31853c22),
new Long(0x2c208214, 0x4514500b), new Long(0x508b0051, 0x8718034), new Long(0x5108f0c5, 0xb2cb4551), new Long(0x1cb0a810, 0xe824715d),
new Long(0x908b0e60, 0x1422cb14), new Long(0xc02cb145, 0x30812c22), new Long(0x0cb1420c, 0x84202202), new Long(0x20ce0850, 0x5c20ce08),
new Long(0x8b0d70c2, 0x20820820), new Long(0x14214208, 0x42085082), new Long(0x50830c20, 0x9208340), new Long(0x13653592, 0xc6134dc6),
new Long(0x6dc4db4d, 0xd309341c), new Long(0x54d34d34, 0x6424d908), new Long(0x030814c2, 0x92072c22), new Long(0x24a30930, 0x4220724b),
new Long(0x25c920e2, 0x2470d720), new Long(0x975c9082, 0x92c92d70), new Long(0x04924e08, 0xcb0880c2), new Long(0xc24c2481, 0x45739728),
new Long(0xda6174da, 0xc6da4db5), new Long(0x5d30971d, 0x4b5d35d7), new Long(0x93825ce2, 0x1030815c), new Long(0x020cb145, 0x51442051),
new Long(0x2c220e2c, 0xc538210e), new Long(0x52cb0d70, 0x8514214), new Long(0x85145142, 0x204b0850), new Long(0x4051440c, 0x92156083),
new Long(0xa60e6595, 0x4d660e4d), new Long(0x1c6dc658, 0x94d914e4), new Long(0x1454d365, 0x82642659), new Long(0x51030813, 0x2892072c),
new Long(0xcb2ca30b, 0xe2c22072), new Long(0x20538910, 0x452c70d7), new Long(0x708e3891, 0x8b2cb2d), new Long(0xc204b24e, 0x81cb1440),
new Long(0x28c2ca24, 0xda44e38e), new Long(0x85d660e4, 0x1dc6da65), new Long(0x8e5d914e, 0xe2cb5d33), new Long(0x38938238)
];
const offsetIncrs4 = /*3 bits per value */ [
new Long(0x00080000, 0x30020000), new Long(0x20c060), new Long(0x04000000, 0x81490000), new Long(0x10824824, 0x40249241),
new Long(0x60002082, 0xdb6030c3), new Long(0x301b0d80, 0x6c36c06c), new Long(0x000db0db, 0xb01861b0), new Long(0x9188e06d, 0x1b703620),
new Long(0x06d86db7, 0x8009200), new Long(0x02402490, 0x4920c24), new Long(0x08249009, 0x490002), new Long(0x28124804, 0x49081281),
new Long(0x124a44a2, 0x34800104), new Long(0x0d24020c, 0xc3093090), new Long(0x24c24d24, 0x40009a09), new Long(0x9201061a, 0x4984a06),
new Long(0x71269262, 0x494d0492), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249),
new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924),
new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492),
new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249),
new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x2492)
];
// 32 vectors; 45 states per vector; array length = 1440
const toStates5 = /*6 bits per value */ [
new Long(0x002c5004, 0x3801450), new Long(0x00000e38, 0xc500014b), new Long(0x51401402, 0x514), new Long(0x0),
new Long(0x14010000, 0x514000b), new Long(0x038e00e0, 0x550000), new Long(0x0600b180, 0x26451850), new Long(0x08208208, 0x82082082),
new Long(0x40820820, 0x2c500), new Long(0x808c0146, 0x70820a38), new Long(0x9c30827c, 0xc37c20c2), new Long(0x20800867, 0x208208),
new Long(0x02002080, 0xb1401020), new Long(0x00518000, 0x828e2023), new Long(0x209f1c20, 0x830a70c), new Long(0x853df0df, 0x51451450),
new Long(0x14508214, 0x16142142), new Long(0x30805050, 0x60260264), new Long(0x43082098, 0x25050806), new Long(0x14564014, 0x42000083),
new Long(0x20850051, 0x8500208), new Long(0x14140582, 0x80990c20), new Long(0x08261809, 0x82019202), new Long(0x90060941, 0x8920519),
new Long(0xc22cb242, 0x22492492), new Long(0x0162492c, 0x43080505), new Long(0x86026026, 0x80414515), new Long(0xc5b43142, 0x37c38020),
new Long(0x14508014, 0x42085085), new Long(0x50850051, 0x1414058), new Long(0x980990c2, 0x51456180), new Long(0x0c50a010, 0xe008316d),
new Long(0x508b21f0, 0x2c52cb2c), new Long(0xc22cb249, 0x600d2c92), new Long(0x1850821c, 0x873c21c0), new Long(0x03cb1420, 0x2c01cb14),
new Long(0x45185182, 0x20800821), new Long(0x08208000, 0x45002002), new Long(0x20871803, 0x8700614), new Long(0x050821cf, 0x740500f5),
new Long(0x18609000, 0x934d9646), new Long(0x30824d30, 0x4c24d34d), new Long(0xc600d642, 0x1860821), new Long(0x25dac274, 0xc2a072c9),
new Long(0x91c27472, 0x2c698398), new Long(0x89242242, 0x92420820), new Long(0x34b00900, 0x82087180), new Long(0xb09d0061, 0x1cb24976),
new Long(0x9d1cb0a8, 0x60e62470), new Long(0x1574ce3e, 0xd31455d7), new Long(0x25c25d74, 0x1c600d38), new Long(0x423c3142, 0x51515454),
new Long(0x1403c314, 0xc22c21cb), new Long(0x21431853, 0xb2c208), new Long(0x05145145, 0x34508b0), new Long(0x0c508718, 0x5515108f),
new Long(0xf2051454, 0x8740500), new Long(0x0618f090, 0xe2534d92), new Long(0x6592c238, 0x49382659), new Long(0x21c600d6, 0x4423c314),
new Long(0xcb2d1545, 0x72c2a042), new Long(0xa091c574, 0x422c3983), new Long(0x508b2c52, 0xb2c514), new Long(0x8034b08b, 0xf0c50871),
new Long(0x45515108, 0xa810b2cb), new Long(0x715d1cb0, 0x2260e824), new Long(0x8e2d74ce, 0xe6592c53), new Long(0x38938238, 0x420c3081),
new Long(0x22020cb1, 0x8508420), new Long(0xce0820ce, 0x70c25c20), new Long(0x08208b0d, 0x42082082), new Long(0x50821421, 0xc204208),
new Long(0x832c5083, 0x21080880), new Long(0x0838c214, 0xa5083882), new Long(0xa9c39430, 0xaaaaaaaa), new Long(0x9fa9faaa, 0x1aaa7eaa),
new Long(0x1420c308, 0x824820d0), new Long(0x84d94d64, 0x7184d371), new Long(0x1b7136d3, 0x34c24d07), new Long(0x1534d34d, 0x99093642),
new Long(0x30c20530, 0x8340508), new Long(0x53592092, 0x34dc6136), new Long(0x4db4dc61, 0xa479c6dc), new Long(0x4924924a, 0x920a9f92),
new Long(0x8192a82a, 0x72c22030), new Long(0x30930920, 0x724b24a), new Long(0x920e2422, 0xd72025c), new Long(0xc9082247, 0x92d70975),
new Long(0x24e0892c, 0x880c2049), new Long(0xc2481cb0, 0x2c928c24), new Long(0x89088749, 0x80a52488), new Long(0xaac74394, 0x6a861b2a),
new Long(0xab27b278, 0x81b2ca6), new Long(0x072c2203, 0xa3093092), new Long(0x6915ce5c, 0xd76985d3), new Long(0x771b6936, 0x5d74c25c),
new Long(0x892d74d7, 0x724e0973), new Long(0x0880c205, 0x4c2481cb), new Long(0x739728c2, 0x6174da45), new Long(0xda4db5da, 0x4aa175c6),
new Long(0x86486186, 0x6a869b27), new Long(0x308186ca, 0xcb14510), new Long(0x44205102, 0x220e2c51), new Long(0x38210e2c, 0xcb0d70c5),
new Long(0x51421452, 0x14514208), new Long(0x4b085085, 0x51440c20), new Long(0x1440832c, 0xcb145108), new Long(0x488b0888, 0x94316208),
new Long(0x9f7e79c3, 0xfaaa7dfa), new Long(0x7ea7df7d, 0x30819ea), new Long(0x20d01451, 0x65648558), new Long(0x93698399, 0x96135983),
new Long(0x39071b71, 0xd9653645), new Long(0x96451534, 0x4e09909), new Long(0x051440c2, 0x21560834), new Long(0x60e65959, 0xd660e4da),
new Long(0xc6dc6584, 0x9207e979), new Long(0xdf924820, 0xa82a8207), new Long(0x103081a6, 0x892072c5), new Long(0xb2ca30b2, 0x2c22072c),
new Long(0x0538910e, 0x52c70d72), new Long(0x08e38914, 0x8b2cb2d7), new Long(0x204b24e0, 0x1cb1440c), new Long(0x8c2ca248, 0x874b2cb2),
new Long(0x24488b08, 0x43948162), new Long(0x9b1f7e77, 0x9e786aa6), new Long(0xeca6a9e7, 0x51030819), new Long(0x2892072c, 0x8e38a30b),
new Long(0x83936913, 0x69961759), new Long(0x4538771b, 0x74ce3976), new Long(0x08e38b2d, 0xc204e24e), new Long(0x81cb1440, 0x28c2ca24),
new Long(0xda44e38e, 0x85d660e4), new Long(0x75c6da65, 0x698607e9), new Long(0x99e7864a, 0xa6ca6aa6)
];
const offsetIncrs5 = /*3 bits per value */ [
new Long(0x00080000, 0x30020000), new Long(0x20c060), new Long(0x04000000, 0x1000000), new Long(0x50603018, 0xdb6db6db),
new Long(0x00002db6, 0xa4800002), new Long(0x41241240, 0x12492088), new Long(0x00104120, 0x40000100), new Long(0x92092052, 0x2492c420),
new Long(0x096592d9, 0xc30d800), new Long(0xc36036d8, 0xb01b0c06), new Long(0x6c36db0d, 0x186c0003), new Long(0xb01b6c06, 0xad860361),
new Long(0x5b6dd6dd, 0x360001b7), new Long(0x0db6030c, 0xc412311c), new Long(0xb6e36e06, 0xdb0d), new Long(0xdb01861b, 0x9188e06),
new Long(0x71b72b62, 0x6dd6db), new Long(0x00800920, 0x40240249), new Long(0x904920c2, 0x20824900), new Long(0x40049000, 0x12012480),
new Long(0xa4906120, 0x5524ad4a), new Long(0x02480015, 0x40924020), new Long(0x48409409, 0x92522512), new Long(0x24000820, 0x49201001),
new Long(0x204a04a0, 0x29128924), new Long(0x00055549, 0x900830d2), new Long(0x24c24034, 0x934930c), new Long(0x02682493, 0x4186900),
new Long(0x61201a48, 0x9a498612), new Long(0x355249d4, 0xc348001), new Long(0x940d2402, 0x24c40930), new Long(0x0924e24d, 0x1a40009a),
new Long(0x06920106, 0x6204984a), new Long(0x92712692, 0x92494d54), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924),
new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492),
new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249),
new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924),
new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492),
new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249),
new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924),
new Long(0x49249249, 0x92492492), new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492),
new Long(0x24924924, 0x49249249), new Long(0x92492492, 0x24924924), new Long(0x49249249, 0x92492492), new Long(0x24924924)
];
// state map
// 0 -> [(0, 0)]
// 1 -> [(0, 2)]
// 2 -> [(0, 1)]
// 3 -> [(0, 1), (1, 1)]
// 4 -> [(0, 2), (1, 2)]
// 5 -> [t(0, 2), (0, 2), (1, 2), (2, 2)]
// 6 -> [(0, 2), (2, 1)]
// 7 -> [(0, 1), (2, 2)]
// 8 -> [(0, 2), (2, 2)]
// 9 -> [(0, 1), (1, 1), (2, 1)]
// 10 -> [(0, 2), (1, 2), (2, 2)]
// 11 -> [(0, 1), (2, 1)]
// 12 -> [t(0, 1), (0, 1), (1, 1), (2, 1)]
// 13 -> [(0, 2), (1, 2), (2, 2), (3, 2)]
// 14 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (3, 2)]
// 15 -> [(0, 2), t(1, 2), (1, 2), (2, 2), (3, 2)]
// 16 -> [(0, 2), (2, 1), (3, 1)]
// 17 -> [(0, 1), t(1, 2), (2, 2), (3, 2)]
// 18 -> [(0, 2), (3, 2)]
// 19 -> [(0, 2), (1, 2), t(1, 2), (2, 2), (3, 2)]
// 20 -> [t(0, 2), (0, 2), (1, 2), (3, 1)]
// 21 -> [(0, 1), (1, 1), (3, 2)]
// 22 -> [(0, 2), (2, 2), (3, 2)]
// 23 -> [(0, 2), (1, 2), (3, 1)]
// 24 -> [(0, 2), (1, 2), (3, 2)]
// 25 -> [(0, 1), (2, 2), (3, 2)]
// 26 -> [(0, 2), (3, 1)]
// 27 -> [(0, 1), (3, 2)]
// 28 -> [(0, 2), (2, 1), (4, 2)]
// 29 -> [(0, 2), t(1, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
// 30 -> [(0, 2), (1, 2), (4, 2)]
// 31 -> [(0, 2), (1, 2), (3, 2), (4, 2)]
// 32 -> [(0, 2), (2, 2), (3, 2), (4, 2)]
// 33 -> [(0, 2), (1, 2), t(2, 2), (2, 2), (3, 2), (4, 2)]
// 34 -> [(0, 2), (1, 2), (2, 2), t(2, 2), (3, 2), (4, 2)]
// 35 -> [(0, 2), (3, 2), (4, 2)]
// 36 -> [(0, 2), t(2, 2), (2, 2), (3, 2), (4, 2)]
// 37 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (4, 2)]
// 38 -> [(0, 2), (1, 2), (2, 2), (4, 2)]
// 39 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
// 40 -> [(0, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
// 41 -> [(0, 2), (4, 2)]
// 42 -> [t(0, 2), (0, 2), (1, 2), (2, 2), t(2, 2), (3, 2), (4, 2)]
// 43 -> [(0, 2), (2, 2), (4, 2)]
// 44 -> [(0, 2), (1, 2), t(1, 2), (2, 2), (3, 2), (4, 2)]
/**
* From org/apache/lucene/util/automaton/Lev2TParametricDescription.java
* @hidden
*/
class lev2t_parametric_description_Lev2TParametricDescription extends ParametricDescription {
constructor(w) {
super(w, 2, [0, 2, 1, 0, 1, 0, -1, 0, 0, -1, 0, -1, -1, -1, -1, -1, -2, -1, -1, -1, -2, -1, -1, -2, -1, -1, -2, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2]);
}
transition(absState, position, vector) {
// null absState should never be passed in
// assert absState != -1;
// decode absState -> state, offset
let state = Math.floor(absState / (this._w + 1));
let offset = absState % (this._w + 1);
// assert offset >= 0;
if (position === this._w) {
if (state < 3) {
const loc = vector * 3 + state;
offset += ParametricDescription.unpack(lev2t_parametric_description_offsetIncrs0, loc, 1);
state = ParametricDescription.unpack(lev2t_parametric_description_toStates0, loc, 2) - 1;
}
}
else if (position === this._w - 1) {
if (state < 5) {
const loc = vector * 5 + state;
offset += ParametricDescription.unpack(lev2t_parametric_description_offsetIncrs1, loc, 1);
state = ParametricDescription.unpack(lev2t_parametric_description_toStates1, loc, 3) - 1;
}
}
else if (position === this._w - 2) {
if (state < 13) {
const loc = vector * 13 + state;
offset += ParametricDescription.unpack(lev2t_parametric_description_offsetIncrs2, loc, 2);
state = ParametricDescription.unpack(lev2t_parametric_description_toStates2, loc, 4) - 1;
}
}
else if (position === this._w - 3) {
if (state < 28) {
const loc = vector * 28 + state;
offset += ParametricDescription.unpack(lev2t_parametric_description_offsetIncrs3, loc, 2);
state = ParametricDescription.unpack(lev2t_parametric_description_toStates3, loc, 5) - 1;
}
}
else if (position === this._w - 4) {
if (state < 45) {
const loc = vector * 45 + state;
offset += ParametricDescription.unpack(offsetIncrs4, loc, 3);
state = ParametricDescription.unpack(toStates4, loc, 6) - 1;
}
}
else {
if (state < 45) {
const loc = vector * 45 + state;
offset += ParametricDescription.unpack(offsetIncrs5, loc, 3);
state = ParametricDescription.unpack(toStates5, loc, 6) - 1;
}
}
if (state === -1) {
// null state
return -1;
}
else {
// translate back to abs
return state * (this._w + 1) + offset;
}
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/fuzzy/levenshtein_automata.ts
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java
* @hidden
*/
class levenshtein_automata_LevenshteinAutomata {
constructor(input, editDistance) {
this._word = input;
this._editDistance = editDistance;
this._alphabet = [...new Set(this._word)].sort((a, b) => a - b);
this._numRanges = 0;
this._rangeLower = new Array(this._alphabet.length + 2);
this._rangeUpper = new Array(this._alphabet.length + 2);
// calculate the unicode range intervals that exclude the alphabet
// these are the ranges for all unicode characters not in the alphabet
let lower = 0;
for (let i = 0; i < this._alphabet.length; i++) {
const higher = this._alphabet[i];
if (higher > lower) {
this._rangeLower[this._numRanges] = lower;
this._rangeUpper[this._numRanges] = higher - 1;
this._numRanges++;
}
lower = higher + 1;
}
/* add the final endpoint */
if (lower <= MAX_CODE_POINT) {
this._rangeLower[this._numRanges] = lower;
this._rangeUpper[this._numRanges] = MAX_CODE_POINT;
this._numRanges++;
}
if (editDistance === 1) {
this._description = new lev1t_parametric_description_Lev1TParametricDescription(input.length);
}
else {
this._description = new lev2t_parametric_description_Lev2TParametricDescription(input.length);
}
}
/**
* Transforms the NDFA to a DFA.
* @returns {Automaton}
*/
toAutomaton() {
let automat = new Automaton();
const range = 2 * this._editDistance + 1;
// the number of states is based on the length of the word and the edit distance
const numStates = this._description.size();
// Prefix is not needed to be handled by the automaton.
// stateOffset = 0;
automat.createState();
// create all states, and mark as accept states if appropriate
for (let i = 1; i < numStates; i++) {
let state = automat.createState();
automat.setAccept(state, this._description.isAccept(i));
}
for (let k = 0; k < numStates; k++) {
const xpos = this._description.getPosition(k);
if (xpos < 0) {
continue;
}
const end = xpos + Math.min(this._word.length - xpos, range);
for (let x = 0; x < this._alphabet.length; x++) {
const ch = this._alphabet[x];
const cvec = this._getVector(ch, xpos, end);
const dest = this._description.transition(k, xpos, cvec);
if (dest >= 0) {
automat.addTransition(k, dest, ch, ch);
}
}
const dest = this._description.transition(k, xpos, 0);
if (dest >= 0) {
for (let r = 0; r < this._numRanges; r++) {
automat.addTransition(k, dest, this._rangeLower[r], this._rangeUpper[r]);
}
}
}
// assert automat.deterministic;
automat.finishState();
return automat;
}
_getVector(x, pos, end) {
let vector = 0;
for (let i = pos; i < end; i++) {
vector <<= 1;
if (this._word[i] === x) {
vector |= 1;
}
}
return vector;
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/index_searcher.ts
function calculateMinShouldMatch(optionalClauseCount, spec) {
if (spec === undefined) {
return 1;
}
if (typeof spec === "number") {
return (spec < 0) ? optionalClauseCount + spec : spec;
}
let result = optionalClauseCount;
if (spec.includes("<")) {
// Parse conditional minimumShouldMatch.;
for (const s of spec.split(" ")) {
const parts = s.split("<");
const upperBound = parseInt(parts[0]);
if (optionalClauseCount <= upperBound) {
return result;
}
else {
result = calculateMinShouldMatch(optionalClauseCount, parts[1]);
}
}
return result;
}
if (spec.includes("%")) {
// Parse percentage.
const percent = parseInt(spec.slice(0, -1));
const calc = (result * percent) * (1 / 100);
result = (calc < 0) ? result + Math.ceil(calc) : Math.floor(calc);
}
else {
const calc = parseInt(spec);
result = (calc < 0) ? result + calc : calc;
}
return (result < 1) ? 1 : result;
}
/**
* @hidden
*/
class index_searcher_IndexSearcher {
/**
* Constructs an index searcher.
* @param {Dict} invIdxs - the inverted indexes
* @param {Set} docs - the ids of the documents
*/
constructor(invIdxs, docs) {
this._invIdxs = invIdxs;
this._docs = docs;
this._scorer = new Scorer(this._invIdxs);
}
search(query) {
let queryResults = this._recursive(query.query, true);
// Do final scoring.
if (query.calculate_scoring !== undefined ? query.calculate_scoring : true) {
return this._scorer.finalScore(query, queryResults);
}
const result = {};
for (const key of queryResults.keys()) {
result[key] = { score: 1 };
}
return result;
}
setDirty() {
this._scorer.setDirty();
}
_recursive(query, doScoring) {
let queryResults = new Map();
const boost = query.boost !== undefined ? query.boost : 1;
const fieldName = query.field !== undefined ? query.field : null;
let root = null;
let analyzer = null;
if (this._invIdxs[fieldName] !== undefined) {
root = this._invIdxs[fieldName].root;
analyzer = this._invIdxs[fieldName].analyzer;
}
switch (query.type) {
case "bool": {
queryResults = null;
if (query.must !== undefined) {
queryResults = this._getUnique(query.must, doScoring, queryResults);
}
if (query.filter !== undefined) {
queryResults = this._getUnique(query.filter, null, queryResults);
}
if (query.should !== undefined) {
const shouldDocs = this._getAll(query.should, doScoring);
let empty = false;
if (queryResults === null) {
empty = true;
queryResults = new Map();
}
const msm = Math.max(1, calculateMinShouldMatch(query.should.length, query.minimum_should_match));
if (empty && msm === 1) {
// Take all documents.
queryResults = shouldDocs;
}
else {
// Remove documents with fewer matches.
for (const [docId, res] of shouldDocs) {
if (res.length >= msm) {
if (queryResults.has(docId)) {
queryResults.get(docId).push(...res);
}
else if (empty) {
queryResults.set(docId, res);
}
else {
queryResults.delete(docId);
}
}
}
}
}
// Match all documents if must/filter/should is not defined.
if (queryResults === null) {
queryResults = this._recursive({ type: "match_all" }, false);
}
if (query.not !== undefined) {
let notDocs = this._getAll(query.not, null);
// Remove all matching documents.
for (const docId of notDocs.keys()) {
if (queryResults.has(docId)) {
queryResults.delete(docId);
}
}
}
// Boost query results afterwards.
if (boost !== 1) {
for (const [_, result] of queryResults) {
for (let i = 0; i < result.length; i++) {
result[i].boost *= boost;
}
}
}
break;
}
case "term": {
const cps = toCodePoints(query.value);
let termIdx = inverted_index_InvertedIndex.getTermIndex(cps, root);
this._scorer.score(fieldName, boost, termIdx, doScoring, queryResults, cps);
break;
}
case "terms": {
for (let i = 0; i < query.value.length; i++) {
const cps = toCodePoints(query.value[i]);
let termIdx = inverted_index_InvertedIndex.getTermIndex(cps, root);
this._scorer.score(fieldName, boost, termIdx, doScoring, queryResults, cps);
}
break;
}
case "fuzzy": {
const [f, idf] = fuzzySearch(query, root);
for (let i = 0; i < f.length; i++) {
this._scorer.score(fieldName, boost * f[i].boost, f[i].index, doScoring, queryResults, f[i].term, idf);
}
break;
}
case "wildcard": {
const enableScoring = query.enable_scoring !== undefined ? query.enable_scoring : false;
const w = wildcardSearch(query, root);
for (let i = 0; i < w.length; i++) {
this._scorer.score(fieldName, boost, w[i].index, doScoring && enableScoring, queryResults, w[i].term);
}
break;
}
case "match_all": {
for (let docId of this._docs) {
this._scorer.scoreConstant(boost, docId, queryResults);
}
break;
}
case "constant_score": {
let tmpQueryResults = this._getAll(query.filter, false);
// Add to each document a constant score.
for (const docId of tmpQueryResults.keys()) {
this._scorer.scoreConstant(boost, docId, queryResults);
}
break;
}
case "prefix": {
const enableScoring = query.enable_scoring !== undefined ? query.enable_scoring : false;
const cps = toCodePoints(query.value);
const termIdx = inverted_index_InvertedIndex.getTermIndex(cps, root);
if (termIdx !== null) {
const termIdxs = inverted_index_InvertedIndex.extendTermIndex(termIdx);
for (let i = 0; i < termIdxs.length; i++) {
this._scorer.score(fieldName, boost, termIdxs[i].index, doScoring && enableScoring, queryResults, [...cps, ...termIdxs[i].term]);
}
}
break;
}
case "exists": {
if (root !== null) {
for (const docId of this._invIdxs[fieldName].docStore.keys()) {
this._scorer.scoreConstant(boost, docId, queryResults);
}
}
break;
}
case "match": {
const terms = analyze(analyzer, query.value);
const operator = query.operator !== undefined ? query.operator : "or";
const boolQuery = { type: "bool" };
const subQueries = [];
if (operator === "or") {
if (query.minimum_should_match !== undefined) {
boolQuery.minimum_should_match = query.minimum_should_match;
}
// Create a should query.
boolQuery.should = subQueries;
}
else {
// Create a must query.
boolQuery.must = subQueries;
}
boolQuery.boost = boost;
if (query.fuzziness !== undefined) {
let prefixLength = query.prefix_length !== undefined ? query.prefix_length : 2;
let extended = query.extended !== undefined ? query.extended : false;
// Add each fuzzy.
for (let i = 0; i < terms.length; i++) {
subQueries.push({
type: "fuzzy", field: fieldName, value: terms[i], fuzziness: query.fuzziness,
prefix_length: prefixLength, extended: extended
});
}
}
else {
// Add each term.
for (let i = 0; i < terms.length; i++) {
subQueries.push({ type: "term", field: fieldName, value: terms[i] });
}
}
queryResults = this._recursive(boolQuery, doScoring);
break;
}
default:
break;
}
return queryResults;
}
_getUnique(queries, doScoring, queryResults) {
if (queries.length === 0) {
return queryResults;
}
for (let i = 0; i < queries.length; i++) {
let currDocs = this._recursive(queries[i], doScoring);
if (queryResults === null) {
queryResults = this._recursive(queries[0], doScoring);
continue;
}
for (const docId of queryResults.keys()) {
if (!currDocs.has(docId)) {
queryResults.delete(docId);
}
else {
queryResults.get(docId).push(...currDocs.get(docId));
}
}
}
return queryResults;
}
_getAll(queries, doScoring, queryResults = new Map()) {
for (let i = 0; i < queries.length; i++) {
let currDocs = this._recursive(queries[i], doScoring);
for (const docId of currDocs.keys()) {
if (!queryResults.has(docId)) {
queryResults.set(docId, currDocs.get(docId));
}
else {
queryResults.get(docId).push(...currDocs.get(docId));
}
}
}
return queryResults;
}
}
/**
* Calculates the levenshtein distance. Specialized version.
* Copyright Kigiri: https://github.com/kigiri
* Milot Mirdita: https://github.com/milot-mirdita
* Toni Neubert: https://github.com/Viatorus/
* @param {string} a - a string
* @param {string} b - a string
*/
function calculateLevenshteinDistance(a, b) {
let i;
let j;
let prev;
let val;
const row = Array(a.length + 1);
// init the row
for (i = 0; i <= a.length; i++) {
row[i] = i;
}
// fill in the rest
for (i = 1; i <= b.length; i++) {
prev = i;
for (j = 1; j <= a.length; j++) {
if (b[i - 1] === a[j - 1]) { // match
val = row[j - 1];
}
else {
val = Math.min(row[j - 1] + 1, // substitution
Math.min(prev + 1, // insertion
row[j] + 1)); // deletion
// transposition
if (i > 1 && j > 1 && b[i - 2] === a[j - 1] && a[j - 2] === b[i - 1]) {
val = Math.min(val, row[j - 1] - (a[j - 1] === b[i - 1] ? 1 : 0));
}
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
/**
* Performs a fuzzy search.
* @param {FuzzyQuery} query - the fuzzy query
* @param {Index} root - the root index
* @returns {[FuzzyResult, number]} - the fuzzy results and the maximum df
*/
function fuzzySearch(query, root) {
let value = toCodePoints(query.value);
let fuzziness = query.fuzziness !== undefined ? query.fuzziness : "AUTO";
if (fuzziness === "AUTO") {
if (value.length <= 2) {
fuzziness = 0;
}
else if (value.length <= 5) {
fuzziness = 1;
}
else {
fuzziness = 2;
}
}
let prefixLength = query.prefix_length !== undefined ? query.prefix_length : 0;
let extended = query.extended !== undefined ? query.extended : false;
// Do just a prefix search if zero fuzziness.
if (fuzziness === 0) {
prefixLength = value.length;
}
let result = [];
let startIdx = root;
let prefix = value.slice(0, prefixLength);
let fuzzy = value;
let df = 0;
// Perform a prefix search.
if (prefixLength !== 0) {
startIdx = inverted_index_InvertedIndex.getTermIndex(prefix, startIdx);
fuzzy = fuzzy.slice(prefixLength);
}
// No startIdx found.
if (startIdx === null) {
return [result, df];
}
// Fuzzy is not necessary anymore, because prefix search includes the whole query value.
if (fuzzy.length === 0) {
if (extended) {
// Add all terms down the index.
const all = inverted_index_InvertedIndex.extendTermIndex(startIdx);
for (let i = 0; i < all.length; i++) {
result.push({ index: all[i].index, term: all[i].term, boost: 1 });
df = Math.max(df, all[i].index.df);
}
}
else if (startIdx.dc !== undefined) {
// Add prefix search result.
result.push({ index: startIdx, term: value, boost: 1 });
df = startIdx.df;
}
return [result, df];
}
// The matching term.
const term = [0];
// Create an automaton from the fuzzy.
const automaton = new RunAutomaton(new levenshtein_automata_LevenshteinAutomata(fuzzy, fuzziness).toAutomaton());
function determineEditDistance(state, term, fuzzy) {
// Check how many edits this fuzzy can still do.
let ed = 0;
state = automaton.step(state, 0);
if (state !== -1 && automaton.isAccept(state)) {
ed++;
state = automaton.step(state, 0);
if (state !== -1 && automaton.isAccept(state)) {
ed++;
}
// Special handling for smaller terms.
if (term.length < fuzzy.length) {
if (ed !== fuzziness) {
return calculateLevenshteinDistance(term, fuzzy);
}
// Include the term and fuzzy length.
ed -= fuzzy.length - term.length;
}
}
return fuzziness - ed;
}
function recursive(state, key, idx) {
term[term.length - 1] = key;
// Check the current key of term with the automaton.
state = automaton.step(state, key);
if (state === -1) {
return;
}
if (automaton.isAccept(state)) {
if (extended) {
// Add all terms down the index.
const all = inverted_index_InvertedIndex.extendTermIndex(idx);
for (let i = 0; i < all.length; i++) {
result.push({ index: all[i].index, term: all[i].term, boost: 1 });
df = Math.max(df, all[i].index.df);
}
return;
}
else if (idx.df !== undefined) {
// Calculate boost.
const distance = determineEditDistance(state, term, fuzzy);
const boost = Math.max(0, 1 - distance / Math.min(prefix.length + term.length, value.length));
result.push({ index: idx, term: [...prefix, ...term], boost });
df = Math.max(df, idx.df);
}
}
term.push(0);
for (const child of idx) {
recursive(state, child[0], child[1]);
}
term.pop();
}
for (const child of startIdx) {
recursive(0, child[0], child[1]);
}
return [result, df];
}
/**
* Performs a wildcard search.
* @param {WildcardQuery} query - the wildcard query
* @param {Index} root - the root index
* @returns {Array} - the results
*/
function wildcardSearch(query, root) {
let wildcard = toCodePoints(query.value);
let result = [];
function recursive(index, idx = 0, term = [], escaped = false) {
if (index === null) {
return;
}
if (idx === wildcard.length) {
if (index.df !== undefined) {
result.push({ index: index, term: term.slice() });
}
return;
}
// Escaped character.
if (!escaped && wildcard[idx] === 92 /* \ */) {
recursive(index, idx + 1, term, true);
}
else if (!escaped && wildcard[idx] === 63 /* ? */) {
for (const child of index) {
recursive(child[1], idx + 1, [...term, child[0]]);
}
}
else if (!escaped && wildcard[idx] === 42 /* * */) {
// Check if asterisk is last wildcard character
if (idx + 1 === wildcard.length) {
const all = inverted_index_InvertedIndex.extendTermIndex(index);
for (let i = 0; i < all.length; i++) {
recursive(all[i].index, idx + 1, [...term, ...all[i].term]);
}
}
else {
// Iterate over the whole tree.
recursive(index, idx + 1, term, false);
const indices = [{ index: index, term: [] }];
do {
const index = indices.pop();
for (const child of index.index) {
recursive(child[1], idx + 1, [...term, ...index.term, child[0]]);
indices.push({ index: child[1], term: [...index.term, child[0]] });
}
} while (indices.length !== 0);
}
}
else {
recursive(inverted_index_InvertedIndex.getTermIndex([wildcard[idx]], index), idx + 1, [...term, wildcard[idx]]);
}
}
recursive(root);
return result;
}
// EXTERNAL MODULE: ./packages/common/plugin.ts
var common_plugin = __webpack_require__(0);
// CONCATENATED MODULE: ./packages/full-text-search/src/full_text_search.ts
class full_text_search_FullTextSearch {
/**
* Initialize the full-text search for the given fields.
* @param {object[]} fieldOptions - the field options
* @param {string} fieldOptions.field - the name of the property field
* @param {boolean=true} fieldOptions.store - flag to indicate if the full-text search should be stored on serialization or
* rebuild on deserialization
* @param {boolean=true} fieldOptions.optimizeChanges - flag to optimize updating and deleting of documents
* (requires more memory but performs faster)
* @param {Analyzer} fieldOptions.analyzer - an analyzer for the field
* @param {string} [id] - the property name of the document index
*/
constructor(fieldOptions = [], id) {
this._invIdxs = {};
// Create an inverted index for each field.
for (let i = 0; i < fieldOptions.length; i++) {
let fieldOption = fieldOptions[i];
this._invIdxs[fieldOption.field] = new inverted_index_InvertedIndex(fieldOption);
}
this._id = id;
this._docs = new Set();
this._idxSearcher = new index_searcher_IndexSearcher(this._invIdxs, this._docs);
}
/**
* Registers the full-text search as plugin.
*/
static register() {
common_plugin["a" /* PLUGINS */]["FullTextSearch"] = full_text_search_FullTextSearch;
}
addDocument(doc, id = doc[this._id]) {
let fieldNames = Object.keys(this._invIdxs);
for (let i = 0, fieldName; i < fieldNames.length, fieldName = fieldNames[i]; i++) {
let field = doc[fieldName];
// Skip null and undefined.
if (field === null || field === undefined) {
continue;
}
if (typeof field !== "string") {
// Convert number to string.
if (typeof field === "number") {
field = field.toString();
}
else {
throw TypeError("Unsupported field type for full text search.");
}
}
this._invIdxs[fieldName].insert(field, id);
}
this._docs.add(id);
this._idxSearcher.setDirty();
}
removeDocument(doc, id = doc[this._id]) {
let fieldNames = Object.keys(this._invIdxs);
for (let i = 0; i < fieldNames.length; i++) {
this._invIdxs[fieldNames[i]].remove(id);
}
this._docs.delete(id);
this._idxSearcher.setDirty();
}
updateDocument(doc, id = doc[this._id]) {
this.removeDocument(doc, id);
this.addDocument(doc, id);
}
clear() {
for (let id of this._docs) {
this.removeDocument(null, id);
}
}
search(query) {
return this._idxSearcher.search(query);
}
toJSON() {
let serialized = { id: this._id, ii: {} };
let fieldNames = Object.keys(this._invIdxs);
for (let i = 0; i < fieldNames.length; i++) {
const fieldName = fieldNames[i];
serialized.ii[fieldName] = this._invIdxs[fieldName].toJSON();
}
return serialized;
}
static fromJSONObject(serialized, analyzers = {}) {
let fts = new full_text_search_FullTextSearch([], serialized.id);
let fieldNames = Object.keys(serialized.ii);
for (let i = 0; i < fieldNames.length; i++) {
const fieldName = fieldNames[i];
fts._invIdxs[fieldName] = inverted_index_InvertedIndex.fromJSONObject(serialized.ii[fieldName], analyzers[fieldName]);
}
return fts;
}
}
// CONCATENATED MODULE: ./packages/full-text-search/src/index.ts
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "FullTextSearch", function() { return full_text_search_FullTextSearch; });
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "analyze", function() { return analyze; });
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "StandardAnalyzer", function() { return analyzer_StandardAnalyzer; });
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "whitespaceTokenizer", function() { return whitespaceTokenizer; });
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "lowercaseTokenFilter", function() { return lowercaseTokenFilter; });
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "uppercaseTokenFilter", function() { return uppercaseTokenFilter; });
full_text_search_FullTextSearch["Analyzer"] = {};
full_text_search_FullTextSearch["Analyzer"]["analyze"] = analyze;
full_text_search_FullTextSearch["Analyzer"]["StandardAnalyzer"] = analyzer_StandardAnalyzer;
full_text_search_FullTextSearch["Tokenizer"] = {};
full_text_search_FullTextSearch["Tokenizer"]["whitespaceTokenizer"] = whitespaceTokenizer;
full_text_search_FullTextSearch["TokenFilter"] = {};
full_text_search_FullTextSearch["TokenFilter"]["lowercaseTokenFilter"] = lowercaseTokenFilter;
full_text_search_FullTextSearch["TokenFilter"]["uppercaseTokenFilter"] = uppercaseTokenFilter;
/* harmony default export */ var src = __webpack_exports__["default"] = (full_text_search_FullTextSearch);
/***/ }),
/* 2 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ })
/******/ ]);
});
//# sourceMappingURL=lokidb.full-text-search.js.map
================================================
FILE: dist/packages/full-text-search/types/common/plugin.d.ts
================================================
/**
* @hidden
*/
export declare const PLUGINS: void;
================================================
FILE: dist/packages/full-text-search/types/common/types.d.ts
================================================
/**
* @hidden
*/
import { Loki } from "../loki/src/loki";
export interface StorageAdapter {
loadDatabase(dbname: string): Promise;
saveDatabase?(dbname: string, serialization: string): Promise;
deleteDatabase?(dbname: string): Promise;
mode?: string;
exportDatabase?(dbname: string, dbref: Loki): Promise;
}
export declare type Doc = T & {
$loki: number;
meta?: {
created: number;
revision: number;
version: number;
updated?: number;
};
};
export interface Dict {
[index: string]: T;
[index: number]: T;
}
================================================
FILE: dist/packages/full-text-search/types/fs-storage/src/fs_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* A loki persistence adapter which persists using node fs module.
*/
export declare class FSStorage implements StorageAdapter {
/**
* Registers the fs storage as plugin.
*/
static register(): void;
/**
* Deregisters the fs storage as plugin.
*/
static deregister(): void;
/**
* Load data from file, will throw an error if the file does not exist
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* Save data to file, will throw an error if the file can't be saved
* might want to expand this to avoid dataloss on partial save
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* Delete the database file, will throw an error if the
* file can't be deleted
* @param {string} dbname - the filename of the database to delete
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
}
================================================
FILE: dist/packages/full-text-search/types/fs-storage/src/index.d.ts
================================================
import { FSStorage } from "./fs_storage";
export { FSStorage };
export default FSStorage;
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/analyzer/analyzer.d.ts
================================================
import { CharacterFilter } from "./character_filter";
import { Tokenizer, whitespaceTokenizer } from "./tokenizer";
import { lowercaseTokenFilter, TokenFilter } from "./token_filter";
/**
* A analyzer converts a string into tokens which are added to the inverted index for searching.
*/
export interface Analyzer {
/**
* The character filters of the analyzer.
*/
char_filter?: CharacterFilter[];
/**
* The tokenizer of the analyzer.
*/
tokenizer: Tokenizer;
/**
* The token filters of the analyzer.
*/
token_filter?: TokenFilter[];
}
/**
* Analyzes a given string.
* @param {Analyzer} analyzer - the analyzer
* @param {string} str - the string
* @returns {string[]} - the tokens
*/
export declare function analyze(analyzer: Analyzer, str: string): string[];
/**
* An analyzer with the whitespace tokenizer and the lowercase token filter.
*/
export declare class StandardAnalyzer implements Analyzer {
tokenizer: typeof whitespaceTokenizer;
token_filter: (typeof lowercaseTokenFilter)[];
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/analyzer/character_filter.d.ts
================================================
/**
* A character filter is used to preprocess a string before it is passed to a tokenizer.
*/
export declare type CharacterFilter = (value: string) => string;
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/analyzer/token_filter.d.ts
================================================
/**
* A token filter takes tokens from a tokenizer and modify, delete or add tokens.
*/
export declare type TokenFilter = (value: string, index: number, array: string[]) => string;
/**
* Converts a token to lowercase.
* @param {string} token - the token
* @returns {string} - the lowercased token
*/
export declare function lowercaseTokenFilter(token: string): string;
/**
* Converts a token to uppercase.
* @param {string} token - the token
* @returns {string} - the uppercased token
*/
export declare function uppercaseTokenFilter(token: string): string;
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/analyzer/tokenizer.d.ts
================================================
/**
* A tokenizer splits a string into individual tokens.
*/
export declare type Tokenizer = (value: string) => string[];
/**
* Splits a string at whitespace characters into tokens.
* @param {string} value - the string
* @returns {string[]} - the tokens
*/
export declare function whitespaceTokenizer(value: string): string[];
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/full_text_search.d.ts
================================================
import { InvertedIndex } from "./inverted_index";
import { Dict } from "../../common/types";
import { Query } from "./query_types";
import { Scorer } from "./scorer";
import { Analyzer } from "./analyzer/analyzer";
export declare class FullTextSearch {
private _id;
private _docs;
private _idxSearcher;
private _invIdxs;
/**
* Registers the full-text search as plugin.
*/
static register(): void;
/**
* Initialize the full-text search for the given fields.
* @param {object[]} fieldOptions - the field options
* @param {string} fieldOptions.field - the name of the property field
* @param {boolean=true} fieldOptions.store - flag to indicate if the full-text search should be stored on serialization or
* rebuild on deserialization
* @param {boolean=true} fieldOptions.optimizeChanges - flag to optimize updating and deleting of documents
* (requires more memory but performs faster)
* @param {Analyzer} fieldOptions.analyzer - an analyzer for the field
* @param {string} [id] - the property name of the document index
*/
constructor(fieldOptions?: FullTextSearch.FieldOptions[], id?: string);
addDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
removeDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
updateDocument(doc: object, id?: InvertedIndex.DocumentIndex): void;
clear(): void;
search(query: Query): Scorer.ScoreResults;
toJSON(): FullTextSearch.Serialization;
static fromJSONObject(serialized: FullTextSearch.Serialization, analyzers?: Dict): FullTextSearch;
}
export declare namespace FullTextSearch {
interface FieldOptions extends InvertedIndex.FieldOptions {
field: string;
}
interface Serialization {
id: string;
ii: Dict;
}
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/automaton.d.ts
================================================
/**
* Transition with dest, min and max.
* @hidden
*/
export declare type Transition = [number, number, number];
/**
* @type {number}
* @hidden
*/
export declare const MIN_CODE_POINT = 0;
/**
* @type {number}
* @hidden
*/
export declare const MAX_CODE_POINT = 1114111;
/**
* From org/apache/lucene/util/automaton/Automaton.java
* @hidden
*/
export declare class Automaton {
private _stateTransitions;
private _accept;
private _nextState;
private _currState;
private _transitions;
constructor();
isAccept(n: number): boolean;
createState(): number;
setAccept(state: number, accept: boolean): void;
finishState(): void;
private _finishCurrentState();
getStartPoints(): number[];
step(state: number, label: number): number;
getNumStates(): number;
addTransition(source: number, dest: number, min: number, max: number): void;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/lev1t_parametric_description.d.ts
================================================
import { ParametricDescription } from "./parametric_description";
/**
* From org/apache/lucene/util/automaton/Lev1TParametricDescription.java
* @hidden
*/
export declare class Lev1TParametricDescription extends ParametricDescription {
constructor(w: number);
transition(absState: number, position: number, vector: number): number;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/lev2t_parametric_description.d.ts
================================================
import { ParametricDescription } from "./parametric_description";
/**
* From org/apache/lucene/util/automaton/Lev2TParametricDescription.java
* @hidden
*/
export declare class Lev2TParametricDescription extends ParametricDescription {
constructor(w: number);
transition(absState: number, position: number, vector: number): number;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/levenshtein_automata.d.ts
================================================
import { Automaton } from "./automaton";
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java
* @hidden
*/
export declare class LevenshteinAutomata {
private _word;
private _numRanges;
private _rangeLower;
private _rangeUpper;
private _description;
private _alphabet;
private _editDistance;
constructor(input: number[], editDistance: number);
/**
* Transforms the NDFA to a DFA.
* @returns {Automaton}
*/
toAutomaton(): Automaton;
private _getVector(x, pos, end);
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/long.d.ts
================================================
/**
* Class supports 64Bit integer operations.
* A cut-down version of dcodeIO/long.js.
* @hidden
*/
export declare class Long {
private _low;
private _high;
constructor(low?: number, high?: number);
/**
* Returns this long with bits arithmetically shifted to the right by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftRight(numBits: number): Long;
/**
* Returns this long with bits arithmetically shifted to the left by the given amount.
* @param {number} numBits - number of bits
* @returns {Long} the long
*/
shiftLeft(numBits: number): Long;
/**
* Returns the bitwise AND of this Long and the specified.
* @param {Long} other - the other Long
* @returns {Long} the long
*/
and(other: Long): Long;
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
* @returns {number}
*/
toInt(): number;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/parametric_description.d.ts
================================================
import { Long } from "./long";
/**
* From org/apache/lucene/util/automaton/LevenshteinAutomata.java#ParametricDescription
* @hidden
*/
export declare class ParametricDescription {
protected _w: number;
private _n;
private _minErrors;
constructor(w: number, n: number, minErrors: number[]);
/**
* Return the number of states needed to compute a Levenshtein DFA
*/
size(): number;
/**
* Returns true if the state in any Levenshtein DFA is an accept state (final state).
*/
isAccept(absState: number): boolean;
/**
* Returns the position in the input word for a given state.
* This is the minimal boundary for the state.
*/
getPosition(absState: number): number;
static unpack(data: Long[], index: number, bitsPerValue: number): number;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/fuzzy/run_automaton.d.ts
================================================
import { Automaton } from "./automaton";
/**
* From org/apache/lucene/util/automaton/RunAutomaton.java
* @hidden
*/
export declare class RunAutomaton {
private _points;
private _accept;
private _transitions;
private _classmap;
constructor(automaton: Automaton);
getCharClass(c: number): number;
step(state: number, c: number): number;
isAccept(state: number): boolean;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/index.d.ts
================================================
import { FullTextSearch } from "./full_text_search";
import { analyze, StandardAnalyzer } from "./analyzer/analyzer";
import { whitespaceTokenizer } from "./analyzer/tokenizer";
import { lowercaseTokenFilter, uppercaseTokenFilter } from "./analyzer/token_filter";
export { FullTextSearch, analyze, StandardAnalyzer, whitespaceTokenizer, lowercaseTokenFilter, uppercaseTokenFilter };
export default FullTextSearch;
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/index_searcher.d.ts
================================================
import { Scorer } from "./scorer";
import { InvertedIndex } from "./inverted_index";
import { Query } from "./query_types";
import { Dict } from "../../common/types";
/**
* @hidden
*/
export declare class IndexSearcher {
private _invIdxs;
private _docs;
private _scorer;
/**
* Constructs an index searcher.
* @param {Dict} invIdxs - the inverted indexes
* @param {Set} docs - the ids of the documents
*/
constructor(invIdxs: Dict, docs: Set);
search(query: Query): Scorer.ScoreResults;
setDirty(): void;
private _recursive(query, doScoring);
private _getUnique(queries, doScoring, queryResults);
private _getAll(queries, doScoring, queryResults?);
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/inverted_index.d.ts
================================================
import { Analyzer } from "./analyzer/analyzer";
/**
* Converts a string into an array of code points.
* @param str - the string
* @returns {number[]} to code points
* @hidden
*/
export declare function toCodePoints(str: string): number[];
/**
* Inverted index class handles featured text search for specific document fields.
* @hidden
*/
export declare class InvertedIndex {
analyzer: Analyzer;
docCount: number;
docStore: Map;
totalFieldLength: number;
root: InvertedIndex.Index;
private _store;
private _optimizeChanges;
/**
* @param {boolean} [options.store=true] - inverted index will be stored at serialization rather than rebuilt on load
* @param {boolean} [options.optimizeChanges=true] - flag to store additional metadata inside the index for better
* performance if an existing field is updated or removed
* @param {Analyzer} [options.analyzer=] - the analyzer of this inverted index
*/
constructor(options?: InvertedIndex.FieldOptions);
/**
* Adds defined fields of a document to the inverted index.
* @param {string} field - the field to add
* @param {number} docId - the doc id of the field
*/
insert(field: string, docId: InvertedIndex.DocumentIndex): void;
/**
* Removes all relevant terms of a document from the inverted index.
* @param {number} docId - the document.
*/
remove(docId: InvertedIndex.DocumentIndex): void;
/**
* Gets the term index of a term.
* @param {string} term - the term
* @param {object} root - the term index to start from
* @param {number} start - the position of the term string to start from
* @return {object} - The term index or null if the term is not in the term tree.
*/
static getTermIndex(term: number[], root: InvertedIndex.Index, start?: number): InvertedIndex.Index;
/**
* Extends a term index to all available term leafs.
* @param {object} idx - the term index to start from
* @param {number[]} [term=[]] - the current term
* @param {Array} termIndices - all extended indices with their term
* @returns {Array} - Array with term indices and extension
*/
static extendTermIndex(idx: InvertedIndex.Index, term?: number[], termIndices?: InvertedIndex.IndexTerm[]): InvertedIndex.IndexTerm[];
/**
* Serialize the inverted index.
* @returns {{docStore: *, _fields: *, index: *}}
*/
toJSON(): InvertedIndex.Serialization;
/**
* Deserialize the inverted index.
* @param {{docStore: *, _fields: *, index: *}} serialized - The serialized inverted index.
* @param {Analyzer} analyzer[undefined] - an analyzer
*/
static fromJSONObject(serialized: InvertedIndex.Serialization, analyzer?: Analyzer): InvertedIndex;
private static _serializeIndex(idx);
private static _deserializeIndex(serialized);
/**
* Set parent of to each index and regenerate the indexRef.
* @param {Index} index - the index
* @param {Index} parent - the parent
*/
private _regenerate(index, parent);
/**
* Iterate over the whole inverted index and remove the document.
* Delete branch if not needed anymore.
* Function is needed if index is used without optimization.
* @param {Index} idx - the index
* @param {number} docId - the doc id
* @returns {boolean} true if index is empty
*/
private _remove(idx, docId);
}
export declare namespace InvertedIndex {
interface FieldOptions {
store?: boolean;
optimizeChanges?: boolean;
analyzer?: Analyzer;
}
type Index = Map & {
dc?: Map;
df?: number;
pa?: Index;
};
type IndexTerm = {
index: Index;
term: number[];
};
interface SerializedIndex {
d?: {
df: number;
dc: [DocumentIndex, number][];
};
k?: number[];
v?: SerializedIndex[];
}
type Serialization = SpareSerialization | FullSerialization;
type SpareSerialization = {
_store: false;
_optimizeChanges: boolean;
};
type FullSerialization = {
_store: true;
_optimizeChanges: boolean;
docCount: number;
docStore: [DocumentIndex, DocStore][];
totalFieldLength: number;
root: SerializedIndex;
};
interface DocStore {
fieldLength?: number;
indexRef?: Index[];
}
type DocumentIndex = number | string;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/query_types.d.ts
================================================
/**
* Base query to enable boost to a query type.
*/
export interface BaseQuery {
type: Type;
boost?: number;
}
/**
* A query which finds documents where a document field contains a term.
*/
export interface TermQuery extends BaseQuery<"term"> {
field: string;
value: string;
}
/**
* A query which finds documents where a document field contains any of the terms.
*/
export interface TermsQuery extends BaseQuery<"terms"> {
field: string;
value: string[];
}
/**
* A query which finds documents where the wildcard term can be applied at an existing document field term.
*/
export interface WildcardQuery extends BaseQuery<"wildcard"> {
field: string;
value: string;
enable_scoring?: boolean;
}
/**
* A query which finds documents where the fuzzy term can be transformed into an existing document field term within a
* given edit distance.
*/
export interface FuzzyQuery extends BaseQuery<"fuzzy"> {
field: string;
value: string;
fuzziness?: 0 | 1 | 2 | "AUTO";
prefix_length?: number;
extended?: boolean;
}
/**
* A query which matches documents containing the prefix of a term inside a field.
*/
export interface PrefixQuery extends BaseQuery<"prefix"> {
field: string;
value: string;
enable_scoring?: boolean;
}
/**
* A query which matches all documents with a given field.
*/
export interface ExistsQuery extends BaseQuery<"exists"> {
field: string;
}
/**
* A query which tokenizes the given text into tokens and performs a sub query for each token. The results are combined
* using a boolean operator.
*/
export interface MatchQuery extends BaseQuery<"match"> {
field: string;
value: string;
minimum_should_match?: number | string;
operator?: "and" | "or";
fuzziness?: 0 | 1 | 2 | "AUTO";
prefix_length?: number;
extended?: boolean;
}
/**
* A query that matches all documents and giving them a constant score equal to the query boost.
*/
export interface MatchQueryAll extends BaseQuery<"match_all"> {
}
/**
* A query that wraps sub queries and returns a constant score equal to the query boost for every document in the filter.
*/
export interface ConstantScoreQuery extends BaseQuery<"constant_score"> {
filter: QueryTypes[];
}
/**
* A query that matches documents matching boolean combinations of sub queries.
*/
export interface BoolQuery extends BaseQuery<"bool"> {
must?: QueryTypes[];
filter?: QueryTypes[];
should?: QueryTypes[];
not?: QueryTypes[];
minimum_should_match?: number | string;
}
/**
* Union type of possible query types.
*/
export declare type QueryTypes = BoolQuery | ConstantScoreQuery | TermQuery | TermsQuery | WildcardQuery | FuzzyQuery | MatchQuery | MatchQueryAll | PrefixQuery | ExistsQuery;
/**
* The main query with the actually full-text search query and the scoring parameters.
*/
export interface Query {
query: QueryTypes;
calculate_scoring?: boolean;
explain?: boolean;
bm25?: {
k1: number;
b: number;
};
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search/src/scorer.d.ts
================================================
import { InvertedIndex } from "./inverted_index";
import { Dict } from "../../common/types";
import { Query } from "./query_types";
/**
* @hidden
*/
export declare class Scorer {
private _invIdxs;
private _cache;
constructor(invIdxs: Dict);
setDirty(): void;
score(fieldName: string, boost: number, termIdx: InvertedIndex.Index, doScoring: boolean | null, queryResults: Scorer.QueryResults, term: number[], df?: number): void;
scoreConstant(boost: number, docId: InvertedIndex.DocumentIndex, queryResults: Scorer.QueryResults): Scorer.QueryResults;
finalScore(query: Query, queryResults: Scorer.QueryResults): Scorer.ScoreResults;
private static _calculateFieldLength(fieldLength);
private _getCache(fieldName);
/**
* Returns the idf by either calculate it or use a cached one.
* @param {string} fieldName - the name of the field
* @param {number} docFreq - the doc frequency of the term
* @returns {number} the idf
* @private
*/
private _idf(fieldName, docFreq);
private _avgFieldLength(fieldName);
}
export declare namespace Scorer {
interface IDFCache {
idfs: Dict;
avgFieldLength: number;
}
interface QueryResult {
tf?: number;
idf?: number;
boost: number;
fieldName?: string;
term?: number[];
}
type QueryResults = Map;
interface BM25Explanation {
boost: number;
score: number;
docID: number;
fieldName: string;
index: string;
idf: number;
tfNorm: number;
tf: number;
fieldLength: number;
avgFieldLength: number;
}
interface ConstantExplanation {
boost: number;
score: number;
}
type ScoreExplanation = BM25Explanation | ConstantExplanation;
type ScoreResult = {
score: number;
explanation?: ScoreExplanation[];
};
type ScoreResults = Dict;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language/src/index.d.ts
================================================
export { generateStopWordFilter, generateTrimmer, Among, SnowballProgram } from "./language";
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language/src/language.d.ts
================================================
export declare function generateTrimmer(wordCharacters: string): (token: string) => string;
export declare function generateStopWordFilter(stopWords: string[]): (token: string) => string;
export declare class Among {
s_size: number;
s: number[];
substring_i: number;
result: number;
method: any;
constructor(s: string, substring_i: number, result: number, method?: any);
}
export declare class SnowballProgram {
current: string;
bra: number;
ket: number;
limit: number;
cursor: number;
limit_backward: number;
constructor();
setCurrent(word: string): void;
getCurrent(): string;
in_grouping(s: number[], min: number, max: number): boolean;
in_grouping_b(s: number[], min: number, max: number): boolean;
out_grouping(s: number[], min: number, max: number): boolean;
out_grouping_b(s: number[], min: number, max: number): boolean;
eq_s(s_size: number, s: string): boolean;
eq_s_b(s_size: number, s: string): boolean;
find_among(v: Among[], v_size: number): number;
find_among_b(v: Among[], v_size: number): number;
replace_s(c_bra: number, c_ket: number, s: string): number;
slice_check(): void;
slice_from(s: string): void;
slice_del(): void;
insert(c_bra: number, c_ket: number, s: string): void;
slice_to(): string;
eq_v_b(s: string): boolean;
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language-de/src/german_analyzer.d.ts
================================================
import { Analyzer } from "../../full-text-search/src/analyzer/analyzer";
export declare class GermanAnalyzer implements Analyzer {
tokenizer: (str: string) => string[];
token_filter: ((token: string) => string)[];
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language-de/src/index.d.ts
================================================
import { GermanAnalyzer } from "./german_analyzer";
export { GermanAnalyzer };
export default GermanAnalyzer;
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language-en/src/english_analyzer.d.ts
================================================
import { Analyzer } from "../../full-text-search/src/analyzer/analyzer";
export declare class EnglishAnalyzer implements Analyzer {
tokenizer: (str: string) => string[];
token_filter: ((token: string) => string)[];
}
================================================
FILE: dist/packages/full-text-search/types/full-text-search-language-en/src/index.d.ts
================================================
import { EnglishAnalyzer } from "./english_analyzer";
export { EnglishAnalyzer };
export default EnglishAnalyzer;
================================================
FILE: dist/packages/full-text-search/types/indexed-storage/src/index.d.ts
================================================
import { IndexedStorage } from "./indexed_storage";
export { IndexedStorage };
export default IndexedStorage;
================================================
FILE: dist/packages/full-text-search/types/indexed-storage/src/indexed_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* Loki persistence adapter class for indexedDb.
* This class fulfills abstract adapter interface which can be applied to other storage methods.
* Utilizes the included LokiCatalog app/key/value database for actual database persistence.
* IndexedDb storage is provided per-domain, so we implement app/key/value database to
* allow separate contexts for separate apps within a domain.
*/
export declare class IndexedStorage implements StorageAdapter {
private _appname;
private catalog;
/**
* Registers the indexed storage as plugin.
*/
static register(): void;
/**
* Deregisters the indexed storage as plugin.
*/
static deregister(): void;
/**
* @param {string} [appname=loki] - Application name context can be used to distinguish subdomains, "loki" by default
*/
constructor(appname?: string);
/**
* Retrieves a serialized db string from the catalog.
*
* @example
* // LOAD
* var idbAdapter = new LokiIndexedAdapter("finance");
* var db = new loki("test", { adapter: idbAdapter });
* db.base(function(result) {
* console.log("done");
* });
*
* @param {string} dbname - the name of the database to retrieve.
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise<{}>;
/**
* Saves a serialized db to the catalog.
*
* @example
* // SAVE : will save App/Key/Val as "finance"/"test"/{serializedDb}
* let idbAdapter = new LokiIndexedAdapter("finance");
* let db = new loki("test", { adapter: idbAdapter });
* let coll = db.addCollection("testColl");
* coll.insert({test: "val"});
* db.saveDatabase(); // could pass callback if needed for async complete
*
* @param {string} dbname - the name to give the serialized database within the catalog.
* @param {string} dbstring - the serialized db string to save.
* @returns {Promise} a Promise that resolves after the database was persisted
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* Deletes a serialized db from the catalog.
*
* @example
* // DELETE DATABASE
* // delete "finance"/"test" value from catalog
* idbAdapter.deleteDatabase("test", function {
* // database deleted
* });
*
* @param {string} dbname - the name of the database to delete from the catalog.
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
/**
* Removes all database partitions and pages with the base filename passed in.
* This utility method does not (yet) guarantee async deletions will be completed before returning
*
* @param {string} dbname - the base filename which container, partitions, or pages are derived
*/
deleteDatabasePartitions(dbname: string): void;
/**
* Retrieves object array of catalog entries for current app.
*
* @example
* idbAdapter.getDatabaseList(function(result) {
* // result is array of string names for that appcontext ("finance")
* result.forEach(function(str) {
* console.log(str);
* });
* });
*
* @param {function} callback - should accept array of database names in the catalog for current app.
*/
getDatabaseList(callback: (names: string[]) => void): void;
/**
* Allows retrieval of list of all keys in catalog along with size
* @param {function} callback - (Optional) callback to accept result array.
*/
getCatalogSummary(callback: (entry: Entry[]) => void): void;
}
export interface Entry {
app: string;
key: string;
size: number;
}
export default IndexedStorage;
================================================
FILE: dist/packages/full-text-search/types/local-storage/src/index.d.ts
================================================
import { LocalStorage } from "./local_storage";
export { LocalStorage };
export default LocalStorage;
================================================
FILE: dist/packages/full-text-search/types/local-storage/src/local_storage.d.ts
================================================
import { StorageAdapter } from "../../common/types";
/**
* A loki persistence adapter which persists to web browser's local storage object
* @constructor LocalStorageAdapter
*/
export declare class LocalStorage implements StorageAdapter {
/**
* Registers the local storage as plugin.
*/
static register(): void;
/**
* Deregisters the local storage as plugin.
*/
static deregister(): void;
/**
* loadDatabase() - Load data from localstorage
* @param {string} dbname - the name of the database to load
* @returns {Promise} a Promise that resolves after the database was loaded
*/
loadDatabase(dbname: string): Promise;
/**
* saveDatabase() - save data to localstorage, will throw an error if the file can't be saved
* might want to expand this to avoid dataloss on partial save
* @param {string} dbname - the filename of the database to load
* @returns {Promise} a Promise that resolves after the database was saved
*/
saveDatabase(dbname: string, dbstring: string): Promise;
/**
* deleteDatabase() - delete the database from localstorage, will throw an error if it
* can't be deleted
* @param {string} dbname - the filename of the database to delete
* @returns {Promise} a Promise that resolves after the database was deleted
*/
deleteDatabase(dbname: string): Promise;
}
export default LocalStorage;
================================================
FILE: dist/packages/full-text-search/types/loki/src/avl_index.d.ts
================================================
import { IRangedIndex, IRangedIndexRequest } from "./ranged_indexes";
import { ILokiComparer } from "./comparators";
/**
* Treenode type for binary search tree (BST) implementation.
*
* To support duplicates, we may need to either repurpose parent to
* point to 'elder' sibling or add a siblingId to point to owner of
* node represented in tree.
*/
export declare type TreeNode = {
id: number;
value: T;
parent: number | null;
balance: number;
height: number;
left: number | null;
right: number | null;
siblings: number[];
};
export interface ITreeNodeHash {
[id: number]: TreeNode;
}
/**
* LokiDB AVL Balanced Binary Tree Index implementation.
* To support duplicates, we use siblings (array) in tree nodes.
* Basic AVL components guided by William Fiset tutorials at :
* https://github.com/williamfiset/data-structures/blob/master/com/williamfiset/datastructures/balancedtree/AVLTreeRecursive.java
* https://www.youtube.com/watch?v=g4y2h70D6Nk&list=PLDV1Zeh2NRsD06x59fxczdWLhDDszUHKt
*/
export declare class AvlTreeIndex implements IRangedIndex {
name: string;
comparator: ILokiComparer;
nodes: ITreeNodeHash;
apex: number | null;
/**
* Initializes index with property name and a comparer function.
*/
constructor(name: string, comparator: ILokiComparer);
backup(): AvlTreeIndex;
restore(tree: AvlTreeIndex): void;
/**
* Used for inserting a new value into the BinaryTreeIndex
* @param id Unique Id (such as $loki) to associate with value
* @param val Value to be indexed and inserted into binary tree
*/
insert(id: number, val: T): void;
/**
* Recursively inserts a treenode and re-balances if needed.
* @param current
* @param node
*/
insertNode(current: TreeNode