data-path 1.0.0 → 1.0.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/LICENSE +22 -22
- package/README.md +75 -8
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Sergei Shmakov
|
|
4
|
-
https://github.com/sergeyshmakov
|
|
5
|
-
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
-
in the Software without restriction, including without limitation the rights
|
|
9
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
-
furnished to do so, subject to the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be included in all
|
|
14
|
-
copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sergei Shmakov
|
|
4
|
+
https://github.com/sergeyshmakov
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ A simple, modern, zero-dependency, and fully type-safe library for building, com
|
|
|
5
5
|
[](https://badge.fury.io/js/data-path)
|
|
6
6
|
[](https://opensource.org/licenses/ISC)
|
|
7
7
|
|
|
8
|
-
## The Problem
|
|
8
|
+
## ⚠️ The Problem
|
|
9
9
|
|
|
10
10
|
When working with deep object structures, forms, or nested state, we often rely on string-based paths (e.g., `"users.0.name"` or `"company.departments[1].budget"`). This approach is fundamentally flawed in modern TypeScript development:
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ When working with deep object structures, forms, or nested state, we often rely
|
|
|
14
14
|
- **No Autocomplete:** Your IDE cannot guide you through the object structure.
|
|
15
15
|
- **No Mathematics:** It is difficult to programmatically determine if path `A` is a child of path `B`, or if they overlap.
|
|
16
16
|
|
|
17
|
-
## The Solution
|
|
17
|
+
## 🚀 The Solution
|
|
18
18
|
|
|
19
19
|
`data-path` solves this by using **Proxy-based lambda expressions** to capture paths. It gives you 100% type safety, IDE autocomplete, and a rich API for interacting with data and other paths.
|
|
20
20
|
|
|
@@ -49,7 +49,7 @@ const updatedUser = firstNamePath.set(user, "Bob");
|
|
|
49
49
|
console.log(updatedUser.profile.firstName); // "Bob"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
## Installation
|
|
52
|
+
## 📦 Installation
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
npm install data-path
|
|
@@ -57,14 +57,61 @@ npm install data-path
|
|
|
57
57
|
|
|
58
58
|
_(or use `yarn add data-path`, `pnpm add data-path`, `bun add data-path`)_
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## 🤖 AI Ready
|
|
61
|
+
|
|
62
|
+
This package is available in [Context7](https://context7.com/) MCP, so AI assistants can load it directly into context when working with your object property paths.
|
|
63
|
+
|
|
64
|
+
It also ships an [Agent Skills](https://agentskills.io/) – compatible skill. Install it so your AI assistant loads data-path guidance:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx ctx7 skills install /sergeyshmakov/data-path data-path
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The skill lives in `skills/data-path/SKILL.md`.
|
|
71
|
+
|
|
72
|
+
## 💡 Philosophy
|
|
61
73
|
|
|
62
74
|
- **Stack Agnostic:** Pure data manipulation. Works perfectly with React, Vue, Node.js, or vanilla JavaScript.
|
|
63
75
|
- **Zero Dependencies:** A tiny, efficient footprint that doesn't bloat your bundle.
|
|
64
76
|
- **Fully Type-Safe:** Built strictly for TypeScript. If the structure changes, the compiler will instantly catch broken paths.
|
|
65
77
|
- **Immutable:** All `.set()` operations return structurally cloned objects, making it the perfect companion for modern state managers (Redux, Zustand) and reactive frameworks.
|
|
66
78
|
|
|
67
|
-
## Core API
|
|
79
|
+
## 📚 Core API
|
|
80
|
+
|
|
81
|
+
### 🏷️ API Cheatsheet
|
|
82
|
+
|
|
83
|
+
| API | Description |
|
|
84
|
+
|-----|-------------|
|
|
85
|
+
| **Creation** | |
|
|
86
|
+
| `path<T>()` | Create root path |
|
|
87
|
+
| `path<T>(p => p.a.b)` | Create path from lambda, generic type |
|
|
88
|
+
| `path((p: T) => p.a.b)` | Create path from lambda, infer type |
|
|
89
|
+
| `path(base, p => p.c)` | Extend existing path |
|
|
90
|
+
| `unsafePath<T>("a.b")` | Create path from raw string |
|
|
91
|
+
| **Properties** | |
|
|
92
|
+
| `path.$` | String representation (e.g. `"users.0.name"`) |
|
|
93
|
+
| `path.segments` | Array of segments |
|
|
94
|
+
| `path.length` | Number of segments |
|
|
95
|
+
| `path.fn` | Accessor function for `.map()`, `.filter()` |
|
|
96
|
+
| **Data Access** | |
|
|
97
|
+
| `path.get(data)` | Read value at path (returns `undefined` if missing) |
|
|
98
|
+
| `path.set(data, value)` | Immutable write, returns new object |
|
|
99
|
+
| **Traversal** | |
|
|
100
|
+
| `path.to(p => p.x)` | Extend path from current value |
|
|
101
|
+
| `path.each(p => p.x)` | Template: match all items in collection |
|
|
102
|
+
| `path.each().to(p => p.x)` | Same as above |
|
|
103
|
+
| `path.deep(node => node.id)` | Template: match property at any depth |
|
|
104
|
+
| **Manipulation** | |
|
|
105
|
+
| `path.merge(other)` | Append path (deduplicates overlap) |
|
|
106
|
+
| `path.subtract(other)` | Remove prefix/suffix, or `null` |
|
|
107
|
+
| `path.slice(start?, end?)` | Slice segments (like `Array.prototype.slice`) |
|
|
108
|
+
| **Relational** | |
|
|
109
|
+
| `path.startsWith(other)` | True if path is prefix |
|
|
110
|
+
| `path.includes(other)` | True if path contains other |
|
|
111
|
+
| `path.equals(other)` | True if paths are identical |
|
|
112
|
+
| `path.match(other)` | Returns `{ relation, params }` or `null` |
|
|
113
|
+
| **Template-only** | |
|
|
114
|
+
| `templatePath.expand(data)` | Resolve template to concrete paths |
|
|
68
115
|
|
|
69
116
|
### Path Creation
|
|
70
117
|
|
|
@@ -78,6 +125,9 @@ const profile = root.to(p => p.profile);
|
|
|
78
125
|
// Direct lambda
|
|
79
126
|
const tagsPath = path<User>(p => p.tags[0]);
|
|
80
127
|
|
|
128
|
+
// Infer type from argument (often preferred)
|
|
129
|
+
const lastNamePath = path((user: User) => user.profile.lastName);
|
|
130
|
+
|
|
81
131
|
// From raw string (dynamic contexts)
|
|
82
132
|
import { unsafePath } from "data-path";
|
|
83
133
|
const dynamicPath = unsafePath<User>("profile.firstName");
|
|
@@ -201,7 +251,24 @@ namePath.match(profilePath); // { relation: 'child', params: {} }
|
|
|
201
251
|
profilePath.match(namePath); // { relation: 'parent', params: {} }
|
|
202
252
|
```
|
|
203
253
|
|
|
204
|
-
|
|
254
|
+
### Utility Types
|
|
255
|
+
|
|
256
|
+
The library exports several TypeScript types that are useful when writing helper functions or React components that accept paths as props:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import type { Path, TemplatePath, ResolvedType } from "data-path";
|
|
260
|
+
|
|
261
|
+
// 1. Accept a specific path structure
|
|
262
|
+
function NameInput({ fieldPath }: { fieldPath: Path<User, string> }) {
|
|
263
|
+
return <input name={fieldPath.$} />;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 2. Extract the resolved value type from an existing path
|
|
267
|
+
const agePath = path<User>(p => p.profile.age);
|
|
268
|
+
type Age = ResolvedType<typeof agePath>; // number
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## 💼 Real-World Examples
|
|
205
272
|
|
|
206
273
|
### 1. React Hook Form
|
|
207
274
|
|
|
@@ -368,10 +435,10 @@ const columns = [
|
|
|
368
435
|
];
|
|
369
436
|
```
|
|
370
437
|
|
|
371
|
-
## Contributing
|
|
438
|
+
## 🤝 Contributing
|
|
372
439
|
|
|
373
440
|
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.
|
|
374
441
|
|
|
375
|
-
## License
|
|
442
|
+
## 📄 License
|
|
376
443
|
|
|
377
444
|
This project is licensed under the [ISC License](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-path",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A simple, modern, zero-dependency, and fully type-safe library for building, comparing, and manipulating object property paths using TypeScript lambda expressions.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "commonjs",
|