@a2ui-sdk/utils 0.2.1 → 0.3.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/README.md +47 -0
- package/dist/0.8/dataBinding.d.ts +12 -7
- package/dist/0.8/dataBinding.js +17 -10
- package/dist/0.8/pathUtils.d.ts +60 -0
- package/dist/0.8/pathUtils.js +95 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,12 +43,17 @@ import {
|
|
|
43
43
|
import {
|
|
44
44
|
// Data binding utilities
|
|
45
45
|
resolveValue,
|
|
46
|
+
resolveActionContext,
|
|
46
47
|
resolveStringValue,
|
|
47
48
|
resolveNumberValue,
|
|
48
49
|
resolveBooleanValue,
|
|
49
50
|
isPathBinding,
|
|
50
51
|
|
|
51
52
|
// Path utilities
|
|
53
|
+
normalizePath,
|
|
54
|
+
isAbsolutePath,
|
|
55
|
+
joinPaths,
|
|
56
|
+
resolvePath,
|
|
52
57
|
parsePath,
|
|
53
58
|
joinPath,
|
|
54
59
|
getValueAtPath,
|
|
@@ -67,6 +72,36 @@ const { interpolate, hasInterpolation } = v0_9
|
|
|
67
72
|
|
|
68
73
|
## API
|
|
69
74
|
|
|
75
|
+
### Scope and Path Resolution (v0.8+)
|
|
76
|
+
|
|
77
|
+
Work with scoped data paths:
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import {
|
|
81
|
+
normalizePath,
|
|
82
|
+
isAbsolutePath,
|
|
83
|
+
joinPaths,
|
|
84
|
+
resolvePath,
|
|
85
|
+
} from '@a2ui-sdk/utils/0.8'
|
|
86
|
+
|
|
87
|
+
// Normalize path format
|
|
88
|
+
normalizePath('user/name') // '/user/name'
|
|
89
|
+
normalizePath('/items/') // '/items'
|
|
90
|
+
|
|
91
|
+
// Check if path is absolute
|
|
92
|
+
isAbsolutePath('/user/name') // true
|
|
93
|
+
isAbsolutePath('name') // false
|
|
94
|
+
|
|
95
|
+
// Join base path with relative path
|
|
96
|
+
joinPaths('/items/0', 'name') // '/items/0/name'
|
|
97
|
+
joinPaths('/items', '../users') // '/users'
|
|
98
|
+
|
|
99
|
+
// Resolve path with scope
|
|
100
|
+
resolvePath('/user/name', '/items/0') // '/user/name' (absolute, ignores basePath)
|
|
101
|
+
resolvePath('name', '/items/0') // '/items/0/name' (relative, uses basePath)
|
|
102
|
+
resolvePath('name', null) // '/name' (treats relative as absolute when no basePath)
|
|
103
|
+
```
|
|
104
|
+
|
|
70
105
|
### String Interpolation (v0.9)
|
|
71
106
|
|
|
72
107
|
Process strings with embedded expressions:
|
|
@@ -102,6 +137,18 @@ resolveValue({ path: '/user/name' }, dataModel) // 'Alice'
|
|
|
102
137
|
resolveValue('static value', dataModel) // 'static value'
|
|
103
138
|
```
|
|
104
139
|
|
|
140
|
+
`resolveValue` also supports scoped path resolution:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { resolveValue } from '@a2ui-sdk/utils/0.9'
|
|
144
|
+
|
|
145
|
+
const dataModel = { items: [{ name: 'Item 1' }, { name: 'Item 2' }] }
|
|
146
|
+
|
|
147
|
+
// Resolve with basePath for scoped data access
|
|
148
|
+
resolveValue({ path: 'name' }, dataModel, '/items/0') // 'Item 1'
|
|
149
|
+
resolveValue({ path: '/items/1/name' }, dataModel, '/items/0') // 'Item 2' (absolute path ignores basePath)
|
|
150
|
+
```
|
|
151
|
+
|
|
105
152
|
### Path Utilities
|
|
106
153
|
|
|
107
154
|
Work with JSON Pointer paths (RFC 6901):
|
|
@@ -8,20 +8,24 @@ import type { ValueSource, DataModel, DataEntry, DataModelValue } from '@a2ui-sd
|
|
|
8
8
|
*
|
|
9
9
|
* @param source - The value source (literal or path reference)
|
|
10
10
|
* @param dataModel - The data model for path lookups
|
|
11
|
+
* @param basePath - Optional base path for resolving relative paths (null for root scope)
|
|
11
12
|
* @param defaultValue - Default value if source is undefined or path not found
|
|
12
13
|
* @returns The resolved value
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* // Literal values
|
|
16
|
-
* resolveValue({ literalString: "Hello" }, {}); // "Hello"
|
|
17
|
-
* resolveValue({ literalNumber: 42 }, {}); // 42
|
|
17
|
+
* resolveValue({ literalString: "Hello" }, {}, null); // "Hello"
|
|
18
|
+
* resolveValue({ literalNumber: 42 }, {}, null); // 42
|
|
18
19
|
*
|
|
19
|
-
* // Path references
|
|
20
|
+
* // Path references (absolute paths)
|
|
20
21
|
* const model = { user: { name: "John" } };
|
|
21
|
-
* resolveValue({ path: "/user/name" }, model); // "John"
|
|
22
|
-
* resolveValue({ path: "/user/age" }, model, 0); // 0 (default)
|
|
22
|
+
* resolveValue({ path: "/user/name" }, model, null); // "John"
|
|
23
|
+
* resolveValue({ path: "/user/age" }, model, null, 0); // 0 (default)
|
|
24
|
+
*
|
|
25
|
+
* // Path references (relative paths with scope)
|
|
26
|
+
* resolveValue({ path: "name" }, model, "/user"); // "John" (resolves to "/user/name")
|
|
23
27
|
*/
|
|
24
|
-
export declare function resolveValue<T = unknown>(source: ValueSource | undefined, dataModel: DataModel, defaultValue?: T): T;
|
|
28
|
+
export declare function resolveValue<T = unknown>(source: ValueSource | undefined, dataModel: DataModel, basePath?: string | null, defaultValue?: T): T;
|
|
25
29
|
/**
|
|
26
30
|
* Converts a DataEntry array to a plain object.
|
|
27
31
|
* This is used for processing dataModelUpdate message contents.
|
|
@@ -47,9 +51,10 @@ export declare function contentsToObject(contents: DataEntry[]): Record<string,
|
|
|
47
51
|
*
|
|
48
52
|
* @param context - Array of action context items
|
|
49
53
|
* @param dataModel - The data model for path lookups
|
|
54
|
+
* @param basePath - Optional base path for resolving relative paths (null for root scope)
|
|
50
55
|
* @returns A plain object with resolved context values
|
|
51
56
|
*/
|
|
52
57
|
export declare function resolveActionContext(context: Array<{
|
|
53
58
|
key: string;
|
|
54
59
|
value: ValueSource;
|
|
55
|
-
}> | undefined, dataModel: DataModel): Record<string, unknown>;
|
|
60
|
+
}> | undefined, dataModel: DataModel, basePath?: string | null): Record<string, unknown>;
|
package/dist/0.8/dataBinding.js
CHANGED
|
@@ -2,26 +2,30 @@
|
|
|
2
2
|
* Data binding utility functions for A2UI.
|
|
3
3
|
* Handles resolving value sources and converting data entries.
|
|
4
4
|
*/
|
|
5
|
-
import { getValueByPath } from './pathUtils.js';
|
|
5
|
+
import { getValueByPath, resolvePath } from './pathUtils.js';
|
|
6
6
|
/**
|
|
7
7
|
* Resolves a ValueSource to its actual value.
|
|
8
8
|
*
|
|
9
9
|
* @param source - The value source (literal or path reference)
|
|
10
10
|
* @param dataModel - The data model for path lookups
|
|
11
|
+
* @param basePath - Optional base path for resolving relative paths (null for root scope)
|
|
11
12
|
* @param defaultValue - Default value if source is undefined or path not found
|
|
12
13
|
* @returns The resolved value
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* // Literal values
|
|
16
|
-
* resolveValue({ literalString: "Hello" }, {}); // "Hello"
|
|
17
|
-
* resolveValue({ literalNumber: 42 }, {}); // 42
|
|
17
|
+
* resolveValue({ literalString: "Hello" }, {}, null); // "Hello"
|
|
18
|
+
* resolveValue({ literalNumber: 42 }, {}, null); // 42
|
|
18
19
|
*
|
|
19
|
-
* // Path references
|
|
20
|
+
* // Path references (absolute paths)
|
|
20
21
|
* const model = { user: { name: "John" } };
|
|
21
|
-
* resolveValue({ path: "/user/name" }, model); // "John"
|
|
22
|
-
* resolveValue({ path: "/user/age" }, model, 0); // 0 (default)
|
|
22
|
+
* resolveValue({ path: "/user/name" }, model, null); // "John"
|
|
23
|
+
* resolveValue({ path: "/user/age" }, model, null, 0); // 0 (default)
|
|
24
|
+
*
|
|
25
|
+
* // Path references (relative paths with scope)
|
|
26
|
+
* resolveValue({ path: "name" }, model, "/user"); // "John" (resolves to "/user/name")
|
|
23
27
|
*/
|
|
24
|
-
export function resolveValue(source, dataModel, defaultValue) {
|
|
28
|
+
export function resolveValue(source, dataModel, basePath = null, defaultValue) {
|
|
25
29
|
if (source === undefined || source === null) {
|
|
26
30
|
return defaultValue;
|
|
27
31
|
}
|
|
@@ -38,7 +42,9 @@ export function resolveValue(source, dataModel, defaultValue) {
|
|
|
38
42
|
return source.literalArray;
|
|
39
43
|
}
|
|
40
44
|
if ('path' in source) {
|
|
41
|
-
|
|
45
|
+
// Resolve path against base path (scope)
|
|
46
|
+
const resolvedPath = resolvePath(source.path, basePath);
|
|
47
|
+
const value = getValueByPath(dataModel, resolvedPath);
|
|
42
48
|
if (value === undefined) {
|
|
43
49
|
return defaultValue;
|
|
44
50
|
}
|
|
@@ -104,15 +110,16 @@ function normalizeKey(key) {
|
|
|
104
110
|
*
|
|
105
111
|
* @param context - Array of action context items
|
|
106
112
|
* @param dataModel - The data model for path lookups
|
|
113
|
+
* @param basePath - Optional base path for resolving relative paths (null for root scope)
|
|
107
114
|
* @returns A plain object with resolved context values
|
|
108
115
|
*/
|
|
109
|
-
export function resolveActionContext(context, dataModel) {
|
|
116
|
+
export function resolveActionContext(context, dataModel, basePath = null) {
|
|
110
117
|
if (!context) {
|
|
111
118
|
return {};
|
|
112
119
|
}
|
|
113
120
|
const result = {};
|
|
114
121
|
for (const item of context) {
|
|
115
|
-
result[item.key] = resolveValue(item.value, dataModel);
|
|
122
|
+
result[item.key] = resolveValue(item.value, dataModel, basePath);
|
|
116
123
|
}
|
|
117
124
|
return result;
|
|
118
125
|
}
|
package/dist/0.8/pathUtils.d.ts
CHANGED
|
@@ -40,3 +40,63 @@ export declare function setValueByPath(dataModel: DataModel, path: string, value
|
|
|
40
40
|
* @returns A new data model with the data merged
|
|
41
41
|
*/
|
|
42
42
|
export declare function mergeAtPath(dataModel: DataModel, path: string, data: Record<string, unknown>): DataModel;
|
|
43
|
+
/**
|
|
44
|
+
* Normalizes a path to ensure it starts with "/" and has no trailing "/".
|
|
45
|
+
*
|
|
46
|
+
* @param path - The path to normalize
|
|
47
|
+
* @returns The normalized path
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* normalizePath("user/name"); // "/user/name"
|
|
51
|
+
* normalizePath("/items/"); // "/items"
|
|
52
|
+
* normalizePath("/data"); // "/data"
|
|
53
|
+
* normalizePath(""); // "/"
|
|
54
|
+
*/
|
|
55
|
+
export declare function normalizePath(path: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Checks if a path is absolute (starts with "/").
|
|
58
|
+
*
|
|
59
|
+
* @param path - The path to check
|
|
60
|
+
* @returns True if the path is absolute, false otherwise
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* isAbsolutePath("/user/name"); // true
|
|
64
|
+
* isAbsolutePath("name"); // false
|
|
65
|
+
* isAbsolutePath(""); // false
|
|
66
|
+
*/
|
|
67
|
+
export declare function isAbsolutePath(path: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Joins two paths together.
|
|
70
|
+
*
|
|
71
|
+
* @param basePath - The base path (should be absolute)
|
|
72
|
+
* @param relativePath - The relative path to append
|
|
73
|
+
* @returns The combined path
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* joinPaths("/items/0", "name"); // "/items/0/name"
|
|
77
|
+
* joinPaths("/user", "profile/age"); // "/user/profile/age"
|
|
78
|
+
* joinPaths("/data", ""); // "/data"
|
|
79
|
+
*/
|
|
80
|
+
export declare function joinPaths(basePath: string, relativePath: string): string;
|
|
81
|
+
/**
|
|
82
|
+
* Resolves a path against a base path (scope).
|
|
83
|
+
* - Absolute paths (starting with "/") are returned normalized, ignoring the base path
|
|
84
|
+
* - Relative paths are resolved against the base path if provided
|
|
85
|
+
* - If base path is null, relative paths are treated as absolute
|
|
86
|
+
*
|
|
87
|
+
* @param path - The path to resolve (absolute or relative)
|
|
88
|
+
* @param basePath - The base path for resolving relative paths (null for root scope)
|
|
89
|
+
* @returns The resolved absolute path
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Absolute paths ignore base path
|
|
93
|
+
* resolvePath("/user/name", "/items/0"); // "/user/name"
|
|
94
|
+
*
|
|
95
|
+
* // Relative paths resolve against base path
|
|
96
|
+
* resolvePath("name", "/items/0"); // "/items/0/name"
|
|
97
|
+
* resolvePath("profile/age", "/user"); // "/user/profile/age"
|
|
98
|
+
*
|
|
99
|
+
* // Relative paths with null base path (root scope)
|
|
100
|
+
* resolvePath("name", null); // "/name"
|
|
101
|
+
*/
|
|
102
|
+
export declare function resolvePath(path: string, basePath: string | null): string;
|
package/dist/0.8/pathUtils.js
CHANGED
|
@@ -109,3 +109,98 @@ export function mergeAtPath(dataModel, path, data) {
|
|
|
109
109
|
const merged = { ...currentObj, ...data };
|
|
110
110
|
return setValueByPath(dataModel, path, merged);
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Normalizes a path to ensure it starts with "/" and has no trailing "/".
|
|
114
|
+
*
|
|
115
|
+
* @param path - The path to normalize
|
|
116
|
+
* @returns The normalized path
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* normalizePath("user/name"); // "/user/name"
|
|
120
|
+
* normalizePath("/items/"); // "/items"
|
|
121
|
+
* normalizePath("/data"); // "/data"
|
|
122
|
+
* normalizePath(""); // "/"
|
|
123
|
+
*/
|
|
124
|
+
export function normalizePath(path) {
|
|
125
|
+
if (!path) {
|
|
126
|
+
return '/';
|
|
127
|
+
}
|
|
128
|
+
// Ensure leading slash
|
|
129
|
+
let normalized = path.startsWith('/') ? path : `/${path}`;
|
|
130
|
+
// Remove trailing slash (unless it's the root path)
|
|
131
|
+
if (normalized.length > 1 && normalized.endsWith('/')) {
|
|
132
|
+
normalized = normalized.slice(0, -1);
|
|
133
|
+
}
|
|
134
|
+
return normalized;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Checks if a path is absolute (starts with "/").
|
|
138
|
+
*
|
|
139
|
+
* @param path - The path to check
|
|
140
|
+
* @returns True if the path is absolute, false otherwise
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* isAbsolutePath("/user/name"); // true
|
|
144
|
+
* isAbsolutePath("name"); // false
|
|
145
|
+
* isAbsolutePath(""); // false
|
|
146
|
+
*/
|
|
147
|
+
export function isAbsolutePath(path) {
|
|
148
|
+
return path.startsWith('/');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Joins two paths together.
|
|
152
|
+
*
|
|
153
|
+
* @param basePath - The base path (should be absolute)
|
|
154
|
+
* @param relativePath - The relative path to append
|
|
155
|
+
* @returns The combined path
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* joinPaths("/items/0", "name"); // "/items/0/name"
|
|
159
|
+
* joinPaths("/user", "profile/age"); // "/user/profile/age"
|
|
160
|
+
* joinPaths("/data", ""); // "/data"
|
|
161
|
+
*/
|
|
162
|
+
export function joinPaths(basePath, relativePath) {
|
|
163
|
+
if (!relativePath) {
|
|
164
|
+
return normalizePath(basePath);
|
|
165
|
+
}
|
|
166
|
+
// Remove leading slash from relative path if present
|
|
167
|
+
const cleanRelative = relativePath.startsWith('/')
|
|
168
|
+
? relativePath.slice(1)
|
|
169
|
+
: relativePath;
|
|
170
|
+
// Combine paths
|
|
171
|
+
const combined = `${normalizePath(basePath)}/${cleanRelative}`;
|
|
172
|
+
return normalizePath(combined);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Resolves a path against a base path (scope).
|
|
176
|
+
* - Absolute paths (starting with "/") are returned normalized, ignoring the base path
|
|
177
|
+
* - Relative paths are resolved against the base path if provided
|
|
178
|
+
* - If base path is null, relative paths are treated as absolute
|
|
179
|
+
*
|
|
180
|
+
* @param path - The path to resolve (absolute or relative)
|
|
181
|
+
* @param basePath - The base path for resolving relative paths (null for root scope)
|
|
182
|
+
* @returns The resolved absolute path
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* // Absolute paths ignore base path
|
|
186
|
+
* resolvePath("/user/name", "/items/0"); // "/user/name"
|
|
187
|
+
*
|
|
188
|
+
* // Relative paths resolve against base path
|
|
189
|
+
* resolvePath("name", "/items/0"); // "/items/0/name"
|
|
190
|
+
* resolvePath("profile/age", "/user"); // "/user/profile/age"
|
|
191
|
+
*
|
|
192
|
+
* // Relative paths with null base path (root scope)
|
|
193
|
+
* resolvePath("name", null); // "/name"
|
|
194
|
+
*/
|
|
195
|
+
export function resolvePath(path, basePath) {
|
|
196
|
+
// Absolute paths are used as-is (ignore base path)
|
|
197
|
+
if (isAbsolutePath(path)) {
|
|
198
|
+
return normalizePath(path);
|
|
199
|
+
}
|
|
200
|
+
// Root scope (null or "/" base path) - treat relative path as absolute
|
|
201
|
+
if (basePath === null || basePath === '/') {
|
|
202
|
+
return normalizePath(path);
|
|
203
|
+
}
|
|
204
|
+
// Relative path with scope - join with base path
|
|
205
|
+
return joinPaths(basePath, path);
|
|
206
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a2ui-sdk/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A2UI utilities",
|
|
5
5
|
"homepage": "https://a2ui-sdk.js.org/",
|
|
6
6
|
"repository": {
|
|
@@ -43,6 +43,6 @@
|
|
|
43
43
|
"vitest": "^4.0.16"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@a2ui-sdk/types": "0.
|
|
46
|
+
"@a2ui-sdk/types": "0.3.0"
|
|
47
47
|
}
|
|
48
48
|
}
|