@ahsankhanamu/json-transformer 0.1.0 → 0.1.1
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/README.md +158 -0
- package/package.json +24 -3
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @ahsankhanamu/json-transformer
|
|
2
|
+
|
|
3
|
+
A lightweight JSON query and transformation language that compiles to JavaScript.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ahsankhanamu/json-transformer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Examples
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { evaluate } from '@ahsankhanamu/json-transformer';
|
|
15
|
+
|
|
16
|
+
const data = {
|
|
17
|
+
user: { name: 'John', age: 30 },
|
|
18
|
+
orders: [
|
|
19
|
+
{ product: 'Widget', price: 25.99 },
|
|
20
|
+
{ product: 'Gadget', price: 49.99 }
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Property access
|
|
25
|
+
evaluate('user.name', data); // "John"
|
|
26
|
+
|
|
27
|
+
// Array operations
|
|
28
|
+
evaluate('orders[].product', data); // ["Widget", "Gadget"]
|
|
29
|
+
evaluate('orders[? .price > 30]', data); // Filter by price
|
|
30
|
+
|
|
31
|
+
// Transformations
|
|
32
|
+
evaluate('orders.map(x => x.price * 2)', data); // [51.98, 99.98]
|
|
33
|
+
evaluate('user.name | upper', data); // "JOHN"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { compile, evaluate, validate, toJavaScript, parse } from '@ahsankhanamu/json-transformer';
|
|
40
|
+
|
|
41
|
+
// compile(expr, options?) - Returns reusable function (fastest for repeated use)
|
|
42
|
+
const fn = compile('user.name | upper');
|
|
43
|
+
fn({ user: { name: 'john' } }); // 'JOHN'
|
|
44
|
+
|
|
45
|
+
// evaluate(expr, data, options?) - One-shot evaluation with caching
|
|
46
|
+
evaluate('price * qty', { price: 10, qty: 5 }); // 50
|
|
47
|
+
|
|
48
|
+
// validate(expr) - Check syntax without executing
|
|
49
|
+
validate('user.name'); // null (valid)
|
|
50
|
+
validate('user.'); // ParseError
|
|
51
|
+
|
|
52
|
+
// toJavaScript(expr, options?) - Generate JS source code
|
|
53
|
+
toJavaScript('a + b'); // 'return (input?.a + input?.b);'
|
|
54
|
+
|
|
55
|
+
// parse(expr) - Get AST for inspection
|
|
56
|
+
parse('a.b'); // { type: 'Program', expression: { type: 'MemberAccess', ... } }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Options
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
interface Options {
|
|
63
|
+
strict?: boolean; // Throw errors vs return undefined (default: false)
|
|
64
|
+
cache?: boolean; // Cache compiled functions (default: true)
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Syntax
|
|
69
|
+
|
|
70
|
+
### Property Access
|
|
71
|
+
```javascript
|
|
72
|
+
user.firstName // Simple access
|
|
73
|
+
user.address.city // Nested access
|
|
74
|
+
user?.middleName // Optional chaining
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Array Operations
|
|
78
|
+
```javascript
|
|
79
|
+
orders[0] // First element
|
|
80
|
+
orders[-1] // Last element
|
|
81
|
+
orders[].product // Property projection → ["Widget", "Gadget"]
|
|
82
|
+
orders[0:3] // Slice
|
|
83
|
+
orders[? .price > 20] // Filter
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Array Methods
|
|
87
|
+
```javascript
|
|
88
|
+
orders.map(x => x.price) // Map
|
|
89
|
+
orders.filter(x => x.price > 20) // Filter
|
|
90
|
+
orders.find(x => x.id == 1) // Find
|
|
91
|
+
orders[].sort(.price) // Sort
|
|
92
|
+
orders[].groupBy(.category) // Group
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Pipe Operations
|
|
96
|
+
```javascript
|
|
97
|
+
name | upper | trim // Chain functions
|
|
98
|
+
orders.find(x => x.id === 3) | .status // jq-style property access
|
|
99
|
+
"hello" | .toUpperCase() // Method calls
|
|
100
|
+
user | { name: .firstName, city: .address.city } // Object construction
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Expressions
|
|
104
|
+
```javascript
|
|
105
|
+
price * quantity + tax // Arithmetic
|
|
106
|
+
firstName & " " & lastName // String concatenation
|
|
107
|
+
`Hello ${user.name}!` // Template literals
|
|
108
|
+
age >= 18 ? "Adult" : "Minor" // Ternary
|
|
109
|
+
nickname ?? "Anonymous" // Null coalescing
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Object Construction
|
|
113
|
+
```javascript
|
|
114
|
+
{ name: user.firstName, city: user.address.city }
|
|
115
|
+
{ ...user, fullName: firstName & " " & lastName }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Variable Bindings
|
|
119
|
+
```javascript
|
|
120
|
+
let total = price * qty;
|
|
121
|
+
let tax = total * 0.1;
|
|
122
|
+
{ subtotal: total, tax, total: total + tax }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Built-in Functions
|
|
126
|
+
|
|
127
|
+
| Category | Functions |
|
|
128
|
+
|----------|-----------|
|
|
129
|
+
| String | `upper`, `lower`, `trim`, `split`, `join`, `replace`, `substring`, `contains`, `capitalize`, `camelCase`, `snakeCase`, `kebabCase` |
|
|
130
|
+
| Math | `round`, `floor`, `ceil`, `abs`, `min`, `max`, `clamp` |
|
|
131
|
+
| Array | `sum`, `avg`, `count`, `first`, `last`, `unique`, `flatten`, `reverse`, `sort`, `groupBy`, `keyBy`, `take`, `drop` |
|
|
132
|
+
| Object | `keys`, `values`, `entries`, `pick`, `omit`, `merge`, `get`, `set` |
|
|
133
|
+
| Type | `type`, `isString`, `isNumber`, `isArray`, `isObject`, `isEmpty` |
|
|
134
|
+
| Conversion | `toString`, `toNumber`, `toJSON`, `fromJSON` |
|
|
135
|
+
|
|
136
|
+
## Code Generation Modes
|
|
137
|
+
|
|
138
|
+
**Forgiving Mode** (default) - Returns undefined for missing paths:
|
|
139
|
+
```javascript
|
|
140
|
+
toJavaScript('user.address.city');
|
|
141
|
+
// → input?.user?.address?.city
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Strict Mode** - Throws descriptive errors:
|
|
145
|
+
```javascript
|
|
146
|
+
toJavaScript('user.address.city', { strict: true });
|
|
147
|
+
// Throws: "Property 'city' does not exist at path 'user.address'"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Links
|
|
151
|
+
|
|
152
|
+
- [Documentation](https://json-transformer-docs.vercel.app)
|
|
153
|
+
- [Playground](https://json-transformer-docs.vercel.app/playground)
|
|
154
|
+
- [GitHub](https://github.com/ahsankhanamu/json-transformer)
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahsankhanamu/json-transformer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "JSON Query and Transformation Language",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,15 +11,36 @@
|
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
15
18
|
"scripts": {
|
|
16
19
|
"build": "tsc",
|
|
17
20
|
"dev": "tsc --watch",
|
|
18
21
|
"test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js",
|
|
19
22
|
"prepublishOnly": "npm run build && npm test"
|
|
20
23
|
},
|
|
21
|
-
"keywords": [
|
|
24
|
+
"keywords": [
|
|
25
|
+
"json",
|
|
26
|
+
"query",
|
|
27
|
+
"transformation",
|
|
28
|
+
"parser",
|
|
29
|
+
"jq",
|
|
30
|
+
"jsonpath",
|
|
31
|
+
"compile"
|
|
32
|
+
],
|
|
33
|
+
"author": "Ahsan Khan",
|
|
22
34
|
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/ahsankhanamu/json-transformer.git",
|
|
38
|
+
"directory": "packages/core"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://json-transformer-docs.vercel.app",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/ahsankhanamu/json-transformer/issues"
|
|
43
|
+
},
|
|
23
44
|
"devDependencies": {
|
|
24
45
|
"@types/jest": "^29.5.12",
|
|
25
46
|
"@types/node": "^20.11.0",
|