lacspace-json 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +51 -0
- package/README.md +159 -0
- package/dist/cli.js +2245 -0
- package/dist/lib.cjs +1980 -0
- package/dist/lib.d.cts +151 -0
- package/dist/lib.d.ts +151 -0
- package/dist/lib.js +1921 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Lacspace Free Licence
|
|
2
|
+
Version 1.0, August 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Lacspace
|
|
5
|
+
|
|
6
|
+
PREAMBLE
|
|
7
|
+
|
|
8
|
+
This software is published by Lacspace under the Lacspace Free Licence — a free,
|
|
9
|
+
permissive licence that lets you use this software for any purpose, including in
|
|
10
|
+
commercial products and services, at no cost. It grants the same freedoms as
|
|
11
|
+
common permissive open-source licences; the only condition is that this notice
|
|
12
|
+
travels with the software. The canonical, always-current text of this licence is
|
|
13
|
+
maintained at https://lacspace.com/licenses/lacspace-free-1.0
|
|
14
|
+
|
|
15
|
+
GRANT OF RIGHTS
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person or organisation
|
|
18
|
+
obtaining a copy of this software and its associated documentation and data files
|
|
19
|
+
(the "Software"), to deal in the Software without restriction, including without
|
|
20
|
+
limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
21
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
|
22
|
+
Software is furnished to do so, subject to the conditions below. These rights are
|
|
23
|
+
granted for any purpose, personal or commercial, and are perpetual, worldwide,
|
|
24
|
+
non-exclusive, and royalty-free.
|
|
25
|
+
|
|
26
|
+
CONDITIONS
|
|
27
|
+
|
|
28
|
+
The above copyright notice, this permission notice, and the name of this licence
|
|
29
|
+
("Lacspace Free Licence") shall be included in all copies or substantial portions
|
|
30
|
+
of the Software.
|
|
31
|
+
|
|
32
|
+
TRADEMARKS
|
|
33
|
+
|
|
34
|
+
This licence does not grant permission to use the trade names, trademarks, service
|
|
35
|
+
marks, logos, or product names of Lacspace, except as required to reproduce the
|
|
36
|
+
notice above or to describe the origin of the Software in a truthful manner.
|
|
37
|
+
|
|
38
|
+
DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
42
|
+
FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
43
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN
|
|
44
|
+
AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
|
45
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
The Lacspace Free Licence is a source-available, permissive licence and is not (as
|
|
50
|
+
of this version) an OSI-approved licence. In substance it grants the same freedoms
|
|
51
|
+
as the MIT Licence. Learn more at https://lacspace.com/licenses
|
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# lacspace-json
|
|
2
|
+
|
|
3
|
+
**The friendly `jq`.** A keyless, zero-dependency CLI + typed library to **query, convert, validate, diff and merge** structured data — JSON, YAML, TOML, CSV and NDJSON. Reads from a file, a glob or **stdin**, prints human-pretty by default, exits non-zero on failure so it drops straight into CI.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
echo '{"users":[{"name":"Ada","age":36,"active":true},{"name":"Ivy","age":19,"active":false}]}' \
|
|
7
|
+
| npx lacspace-json query -q '.users[] | select(.age > 21) | .name' -r
|
|
8
|
+
# Ada
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Everything runs locally. No API key, no account, no network, no telemetry — your data never leaves your machine.
|
|
12
|
+
|
|
13
|
+
## Why it exists
|
|
14
|
+
|
|
15
|
+
`jq` is brilliant but its language is a cliff, and it only speaks JSON. `lacspace-json` gives you the 80% of jq you actually use every day — paths, `select`, `map`, `sort_by`, `group_by`, aggregates — plus first-class **format conversion**, **JSON Schema validation**, **structural diff** and **deep merge**, all behind one small binary with **zero runtime dependencies**. The query engine is a hand-written tokenizer → evaluator: **no `eval`**, and object building is guarded against prototype pollution.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# one-off, no install
|
|
21
|
+
npx lacspace-json data.json -q ".users[].email"
|
|
22
|
+
|
|
23
|
+
# or globally
|
|
24
|
+
npm i -g lacspace-json
|
|
25
|
+
|
|
26
|
+
# or as a library
|
|
27
|
+
npm i lacspace-json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## CLI
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
lacspace-json <command> [input] [flags]
|
|
34
|
+
cat data.json | lacspace-json <command> [flags]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Command | Purpose |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `query` / `get` | Run a jq-style query (default when `-q`/`--get` is given) |
|
|
40
|
+
| `convert` | JSON ⇄ YAML ⇄ TOML ⇄ CSV ⇄ NDJSON |
|
|
41
|
+
| `validate` | Validate a document against a JSON Schema (draft-07 subset) |
|
|
42
|
+
| `diff` | Structural diff of two documents |
|
|
43
|
+
| `merge` | Deep-merge N documents |
|
|
44
|
+
| `format` | Pretty-print / minify (the default when only an input is given) |
|
|
45
|
+
|
|
46
|
+
| Flag | Description |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `--from <fmt>` | Input format override: `json` \| `yaml` \| `toml` \| `csv` \| `ndjson` (else auto-detected) |
|
|
49
|
+
| `--to <fmt>` | Output format (for `convert`, and `merge`/`format`) |
|
|
50
|
+
| `-q, --query <expr>` | Query expression (see the language below) |
|
|
51
|
+
| `--get <path>` | Shorthand: extract a single value at `.a.b[0]` |
|
|
52
|
+
| `--schema <file>` | JSON Schema file (for `validate`) |
|
|
53
|
+
| `--indent <n>` | Indent width for pretty JSON/YAML (default `2`) |
|
|
54
|
+
| `--sort-keys` | Sort object keys recursively |
|
|
55
|
+
| `--min` | Minify JSON output |
|
|
56
|
+
| `-r, --raw` | Print string scalars unquoted (great for shell pipelines) |
|
|
57
|
+
| `--json` | Force machine-readable JSON output (`diff` / `validate`) |
|
|
58
|
+
| `--array <mode>` | Merge array strategy: `concat` \| `replace` \| `by-key` |
|
|
59
|
+
| `--array-key <k>` | Key field for `--array by-key` |
|
|
60
|
+
| `-h, --help` / `-v, --version` | Help / version |
|
|
61
|
+
|
|
62
|
+
Data goes to **stdout**, messages and errors to **stderr**. Invalid input, a failed validation, or a non-empty diff exits **non-zero**.
|
|
63
|
+
|
|
64
|
+
## Query language
|
|
65
|
+
|
|
66
|
+
A small, safe subset of jq — a hand-written tokenizer and evaluator, no `eval`.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
paths .users[0].name .items[].price .["a key with spaces"]
|
|
70
|
+
pipe .users[] | select(.age > 21) | .name
|
|
71
|
+
select == != > < >= <= , and / or / not, truthiness
|
|
72
|
+
funcs keys values length type has(k) map(.x) unique reverse flatten
|
|
73
|
+
sort_by(.x) group_by(.x) first last min max sum avg add
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Unsupported (on purpose):** arithmetic on outputs, string interpolation, object/array construction (`{a: .b}`, `[...]`), `//` alternative, `..` recursive descent, `def`/functions, and `@base64`-style builtins. For those, reach for real `jq`.
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Pull a single value out of nested data (stdin)
|
|
82
|
+
echo '{"a":{"b":[10,20,30]}}' | lacspace-json --get '.a.b[1]'
|
|
83
|
+
# 20
|
|
84
|
+
|
|
85
|
+
# Filter + project, unquoted for the shell
|
|
86
|
+
lacspace-json query users.json -q '.users[] | select(.active) | .email' -r
|
|
87
|
+
|
|
88
|
+
# Aggregate
|
|
89
|
+
echo '{"orders":[{"total":9},{"total":21},{"total":6}]}' \
|
|
90
|
+
| lacspace-json -q '.orders | map(.total) | sum'
|
|
91
|
+
# 36
|
|
92
|
+
|
|
93
|
+
# Convert a TOML config to YAML
|
|
94
|
+
lacspace-json convert config.toml --to yaml
|
|
95
|
+
|
|
96
|
+
# CSV → pretty JSON (header row becomes object keys)
|
|
97
|
+
cat people.csv | lacspace-json convert --from csv --to json
|
|
98
|
+
|
|
99
|
+
# Validate against a JSON Schema (exit 1 if invalid)
|
|
100
|
+
lacspace-json validate user.json --schema user.schema.json
|
|
101
|
+
|
|
102
|
+
# See exactly what changed between two docs
|
|
103
|
+
lacspace-json diff old.yaml new.yaml
|
|
104
|
+
|
|
105
|
+
# Deep-merge, matching array items by their id
|
|
106
|
+
lacspace-json merge base.json patch.json --array by-key --array-key id
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Example diff output:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
◆ lacspace-json diff · 3 changes
|
|
113
|
+
|
|
114
|
+
~ b 2 → 3
|
|
115
|
+
+ c 9
|
|
116
|
+
~ tags[1] "y" → "z"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Library API
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { query, convert, validateSchema, diff, merge } from "lacspace-json";
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
| Export | Signature |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| `query` | `(data, expr: string) => unknown` — single result, or array if the query streams many |
|
|
128
|
+
| `queryAll` | `(data, expr) => unknown[]` — always the full result stream |
|
|
129
|
+
| `compileQuery` | `(expr) => (data) => unknown[]` — reusable compiled query |
|
|
130
|
+
| `isValidQuery` | `(expr) => boolean` |
|
|
131
|
+
| `convert` | `(src, from: Format, to: Format, opts?) => string` |
|
|
132
|
+
| `parseFormat` / `stringifyFormat` | `(text, fmt)` / `(value, fmt, opts?)` |
|
|
133
|
+
| `detectFormat` / `formatFromExt` | `(src) => Format` / `(filename) => Format \| undefined` |
|
|
134
|
+
| `parseYaml` / `stringifyYaml` | YAML subset codec |
|
|
135
|
+
| `parseToml` / `stringifyToml` | TOML subset codec |
|
|
136
|
+
| `parseCsv` / `stringifyCsv` | CSV ⇄ array-of-objects |
|
|
137
|
+
| `parseNdjson` / `stringifyNdjson` | NDJSON ⇄ array |
|
|
138
|
+
| `validateSchema` | `(data, schema) => { valid: boolean; errors: { path; message }[] }` |
|
|
139
|
+
| `diff` / `isEqual` | `(a, b) => DiffEntry[]` / `(a, b) => boolean` |
|
|
140
|
+
| `merge` / `parseArrayStrategy` | `(values[], opts?) => value` |
|
|
141
|
+
| `formatJson` / `getPath` / `parsePath` | pretty/minify · single-value getter · path tokenizer |
|
|
142
|
+
|
|
143
|
+
`Format` is `"json" | "yaml" | "toml" | "csv" | "ndjson"`. Types (`JsonValue`, `DiffEntry`, `ValidationResult`, `ArrayStrategy`, …) are exported too. Fully typed, dual ESM + CJS.
|
|
144
|
+
|
|
145
|
+
## Limitations (honest)
|
|
146
|
+
|
|
147
|
+
- **YAML** covers the common cases — block maps/sequences, nesting, plain/quoted scalars, flow `[...]`/`{...}`, `#` comments, and `|`/`>` block scalars. **Not** supported: anchors & aliases (`&`/`*`), tags (`!!type`), multi-document streams, and merge keys (`<<`).
|
|
148
|
+
- **TOML** covers keys, tables, arrays-of-tables, dotted keys, inline tables, and the standard scalar types. Date-times are kept as **strings** (no native date typing); multi-line strings (`"""`) aren't parsed.
|
|
149
|
+
- **CSV** assumes a header row and flat rows; nested values are JSON-encoded on write.
|
|
150
|
+
- **JSON Schema** is a draft-07 **subset** (see `validateSchema`'s doc): local `$ref` only, no `if/then/else`, `dependencies`, or draft-2020 keywords.
|
|
151
|
+
- The **query language** is deliberately a subset of jq (see above).
|
|
152
|
+
|
|
153
|
+
## Licence
|
|
154
|
+
|
|
155
|
+
Lacspace Free Licence v1.0 — see [LICENSE](./LICENSE). Free to use, permissive, Lacspace-branded.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
Part of the free [Lacspace developer tools](https://developer.lacspace.com/tools). Built keyless, local-first and zero-dependency.
|