UNPKG

jora

Version:

JavaScript object query engine

272 lines (200 loc) 10.2 kB
# Jora [![NPM version](https://img.shields.io/npm/v/jora.svg)](https://www.npmjs.com/package/jora) [![Build Status](https://github.com/discoveryjs/jora/actions/workflows/build.yml/badge.svg)](https://github.com/discoveryjs/jora/actions/workflows/build.yml) [![Coverage Status](https://coveralls.io/repos/github/discoveryjs/jora/badge.svg?branch=master)](https://coveralls.io/github/discoveryjs/jora?branch=master) [![Twitter](https://badgen.net/badge/follow/@js_discovery?icon=twitter)](https://twitter.com/js_discovery) JavaScript object query language, and a library to process and perform Jora queries on data. > STATUS: Jora is stable, but syntax may change in next releases. Still very much work in progress ([ideas and thoughts](https://gist.github.com/lahmatiy/d5af7a987e9548e80eae5f46e6edc931)). Features: - Tolerant to data stucture queries (e.g. just returns *nothing* for paths that not reachable) - Compact syntax for common tasks - Aggregate values across arrays and eliminate duplicates by default - Stat collecting mode (powers suggestions) - Tolerant parsing mode (useful to provide suggestions for query in an editor) - Extensible DSL on query build by custom method list Related projects: - [Discovery](https://github.com/discoveryjs/discovery) – Uses jora as core fuctionality to transform a data flow for views and query data for reports - [JsonDiscovery](https://github.com/discoveryjs/browser-extension-json-discovery) – a browser’s extension based on Discovery for viewing JSON documents, available for [Chrome](https://chrome.google.com/webstore/detail/jsondiscovery/pamhglogfolfbmlpnenhpeholpnlcclo) and [Firefox](https://addons.mozilla.org/en-GB/firefox/addon/jsondiscovery/) (read more [Changing a way we’re viewing JSON in a browser](https://medium.com/@rdvornov/changing-a-way-were-viewing-json-in-a-browser-51eda9103fa2)) - [jora-cli](https://github.com/discoveryjs/jora-cli) – Command line interface for transforming data using Jora - [Jora sandbox](https://discoveryjs.github.io/jora-sandbox/) – A Web interface where you can play with jora syntax or transform some JSON with zero setup Table of content: <!-- TOC depthfrom:2 --> - [Query syntax overview](#query-syntax-overview) - [Comments](#comments) - [Expressions](#expressions) - [Literals](#literals) - [Operators](#operators) - [Dot, bracket and slice notations](#dot-bracket-and-slice-notations) - [Methods and functions](#methods-and-functions) - [Mapping and filtering](#mapping-and-filtering) - [Variables](#variables) - [NPM package](#npm-package) - [Install & import](#install--import) - [API](#api) - [Quick demo](#quick-demo) <!-- /TOC --> ## Query syntax overview Jora is a query language designed for JSON-like data structures. It extends [JSON5](https://json5.org/) and shares many similarities with JavaScript. See [Docs & playground](https://discoveryjs.github.io/jora/). ### Comments ```js // single-line comment /* multi-line comment */ ``` ### Expressions Jora expressions are the building blocks of Jora queries. Expressions can include comments, literals, operators, functions, and variables. ### Literals Jora supports literals, which include: - Numbers: `42`, `-3.14`, `6.022e23` - Strings: `"hello"`, `'world'`, <code>\`template${yes}\`</code>, `"\u{1F600}"` - Booleans: `true`, `false` - Regular expressions: `/regexp/flags` - Object literals: `{ hello: 'world' }` (see [Object literals](https://discoveryjs.github.io/jora/#article:jora-syntax-object-literal)) - Array literals: `[1, 2, 3]` (see [Array literals](https://discoveryjs.github.io/jora/#article:jora-syntax-array-literal)) - Functions: `=> …` (see [Functions](https://discoveryjs.github.io/jora/#article:jora-syntax-functions)) - Keywords: `NaN`, `Infinity`, `null` and `undefined` See [Literals](https://discoveryjs.github.io/jora/#article:jora-syntax-literals) ### Operators Jora supports most JavaScript operators, including: - Arithmetic: `+`, `-`, `*`, `/`, `%` - Comparison: `=`, `!=`, `<`, `<=`, `>`, `>=`, `~=` - Logical: `and`, `or`, `not` (alias `no`), `??`, `is`, `in`, `not in`, `has`, `has no` - Ternary: `?:` - Grouing: `( )` - Pipeline: `|` See [Operators](https://discoveryjs.github.io/jora/#article:jora-syntax-operators) ### Dot, bracket and slice notations Jora provides notations for accessing properties and elements: dot, bracket and slice notations. Dot notation is similar to JavaScript's property access notation, using a period followed by the property name (e.g., `$.propertyName`). Bracket notation encloses the property name or index within square brackets (e.g., `$['propertyName']` or `$[0]`), it's also possible to use functions to choose. Slice notation provides a concise syntax to slice elements with optional step (`array[5:10:2]` selects each odd element from 5th to 10th indecies). - [Dot notation](https://discoveryjs.github.io/jora/#article:jora-syntax-dot-notation) - [Bracket notation](https://discoveryjs.github.io/jora/#article:jora-syntax-bracket-notation) - [Slice notation](https://discoveryjs.github.io/jora/#article:jora-syntax-slice-notation) ### Methods and functions Jora provides a rich set of built-in methods for manipulating data, such as `map()`, `filter()`, `group()`, `sort()`, `reduce()`, and many others. You can also define custom functions using the `=>` arrow function syntax, and use them as a method. - [Functions](https://discoveryjs.github.io/jora/#article:jora-syntax-functions) - [Methods](https://discoveryjs.github.io/jora/#article:jora-syntax-methods) - [Built-in methods](https://discoveryjs.github.io/jora/#article:jora-syntax-methods-builtin) - [Grouping](https://discoveryjs.github.io/jora/#article:jora-syntax-group): `group()` method - [Sorting](https://discoveryjs.github.io/jora/#article:jora-syntax-sort): `sort()` method ### Mapping and filtering Jora has a concise syntax for mapping and filtering. The `map(fn)` method is equivalent to `.(fn())`, while the `filter(fn)` method is equivalent to `.[fn()]`. - [Filtering](https://discoveryjs.github.io/jora/#article:jora-syntax-filter): `.[…]` and `filter()` method - [Mapping](https://discoveryjs.github.io/jora/#article:jora-syntax-map): `.(…)` and `map()` method - [Recursive mapping](https://discoveryjs.github.io/jora/#article:jora-syntax-recursive-map): `..(…)` ### Variables Variables in Jora are helpful for storing intermediate results or simplifying complex expressions. To define a variable, use the `$variableName: expression;` syntax. See [Variables](https://discoveryjs.github.io/jora/#article:jora-syntax-variables) ## NPM package ### Install & import Install with npm: ``` npm install jora ``` Basic usage: ```js // ESM import jora from 'jora'; // CommonJS const jora = require('jora'); ``` Bundles are available for use in a browser: - `dist/jora.js` – minified IIFE with `jora` as global ```html <script src="node_modules/jora/dist/jora.js"></script> <script> jora('query')(data, context); </script> ``` - `dist/jora.esm.js` – minified ES module ```html <script type="module"> import jora from 'node_modules/jora/dist/jora.esm.js' // ... </script> ``` By default (for short path) a ESM version is exposing. For IIFE version a full path to a bundle should be specified. One of CDN services like `unpkg` or `jsDelivr` can be used: - `jsDeliver` ```html <!-- ESM --> <script type="module"> import jora from 'https://cdn.jsdelivr.net/npm/jora'; </script> ``` ```html <!-- IIFE with an export `jora` to global --> <script src="https://cdn.jsdelivr.net/npm/jora/dist/jora.js"></script> ``` - `unpkg` ```html <!-- ESM --> <script type="module"> import jora from 'https://unpkg.com/jora'; </script> ``` ```html <!-- IIFE with an export `jora` to global --> <script src="https://unpkg.com/jora/dist/jora.js"></script> ``` ### API ```js import jora from 'jora'; // create a query const query = jora('foo.bar'); // perform a query const result = query(data, context); ``` See the details in [Jora library API](https://discoveryjs.github.io/jora/#article:api) ### Quick demo Get npm dependency paths (as a tree) that have packages with more than one version: ```js import jora from 'jora'; import { exec } from 'child_process'; function printTree() { // see implementation in examples/npm-ls.js } exec('npm ls --all --json', (error, stdout) => { if (error) { return; } const npmTree = JSON.parse(stdout); const depsPathsToMultipleVersionPackages = jora(` $normalizedDeps: => dependencies.entries().({ name: key, ...value }); $multiVersionPackages: ..$normalizedDeps() .group(=>name, =>version) .({ name: key, versions: value.sort() }) .[versions.size() > 1]; $pathToMultiVersionPackages: => .($name; { name, version, otherVersions: $multiVersionPackages[=>name=$name].versions - version, dependencies: $normalizedDeps() .$pathToMultiVersionPackages() .[name in $multiVersionPackages.name or dependencies] }); $pathToMultiVersionPackages() `)(npmTree); printTree(depsPathsToMultipleVersionPackages); }); ``` Example of output: ``` jora@1.0.0 ├─ c8@7.11.0 │ ├─ istanbul-lib-report@3.0.0 │ │ └─ supports-color@7.2.0 [more versions: 8.1.1] │ ├─ test-exclude@6.0.0 │ │ └─ minimatch@3.1.2 [more versions: 3.0.4] │ ├─ v8-to-istanbul@8.1.1 │ │ └─ convert-source-map@1.8.0 │ │ └─ safe-buffer@5.1.2 [more versions: 5.2.1] │ ├─ yargs-parser@20.2.9 [more versions: 20.2.4] │ └─ yargs@16.2.0 │ └─ yargs-parser@20.2.9 [more versions: 20.2.4] ├─ eslint@8.10.0 │ ├─ @eslint/eslintrc@1.2.0 │ │ ├─ ignore@4.0.6 [more versions: 5.2.0] │ │ └─ minimatch@3.1.2 [more versions: 3.0.4] ... ``` See more examples in [Complex Jora query examples](https://discoveryjs.github.io/jora/#article:jora-syntax-complex-examples)