data-path 1.0.0 → 1.0.2

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.
Files changed (3) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +75 -8
  3. package/package.json +1 -6
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
  [![npm version](https://badge.fury.io/js/data-path.svg)](https://badge.fury.io/js/data-path)
6
6
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](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
- ## Philosophy
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](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
- ## Real-World Examples
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.0",
3
+ "version": "1.0.2",
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",
@@ -61,11 +61,6 @@
61
61
  "peerDependencies": {
62
62
  "typescript": ">=5.0.0"
63
63
  },
64
- "peerDependenciesMeta": {
65
- "typescript": {
66
- "optional": true
67
- }
68
- },
69
64
  "engines": {
70
65
  "node": ">=20.0.0"
71
66
  },