assign-gingerly 0.0.89 → 0.0.90
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/DX/paths.js +13 -1
- package/DX/paths.ts +39 -17
- package/package.json +1 -1
package/DX/paths.js
CHANGED
|
@@ -52,7 +52,12 @@ function appendCommandSuffix(prefix, token) {
|
|
|
52
52
|
function getReservedToken(prop) {
|
|
53
53
|
if (prop === 'Path')
|
|
54
54
|
return prop;
|
|
55
|
-
|
|
55
|
+
// Own-property check only — `prop in COMMAND_TOKEN_SUFFIXES` would also match
|
|
56
|
+
// inherited Object.prototype members (`toString`, `valueOf`, `toLocaleString`,
|
|
57
|
+
// `hasOwnProperty`, `constructor`, …), so a path segment named after one of
|
|
58
|
+
// those (e.g. `$.count.toLocaleString`) would be mistaken for a command token
|
|
59
|
+
// and produce a garbled path.
|
|
60
|
+
if (Object.hasOwn(COMMAND_TOKEN_SUFFIXES, prop))
|
|
56
61
|
return prop;
|
|
57
62
|
return undefined;
|
|
58
63
|
}
|
|
@@ -193,6 +198,13 @@ function createPathProxy(prefix, options) {
|
|
|
193
198
|
* const $ = paths<MyEl>({ aka: { q: 'querySelector' } });
|
|
194
199
|
* $.querySelector('.user').textContent.Path // '?.q?..user?.textContent'
|
|
195
200
|
*
|
|
201
|
+
* // To write alias keys (emoji) directly in the chain, pass their union as the
|
|
202
|
+
* // second type argument — TypeScript cannot infer it while `T` is explicit:
|
|
203
|
+
* import { akaMethods as m } from 'assign-gingerly/DX/emojis.js';
|
|
204
|
+
* const $ = paths<MyEl, keyof typeof m>({ aka: m });
|
|
205
|
+
* $.count['🌐'].Path // '?.count?.🌐'
|
|
206
|
+
* // (or just use the real method name: $.count.toLocaleString — reverse-aliased to 🌐)
|
|
207
|
+
*
|
|
196
208
|
* // Inside sp template literals, .Path is not needed:
|
|
197
209
|
* sp`${$.lastName}, ${$.firstName}` // ['?.lastName', ', ', '?.firstName']
|
|
198
210
|
*/
|
package/DX/paths.ts
CHANGED
|
@@ -60,7 +60,12 @@ function appendCommandSuffix(prefix: string, token: CommandToken): string {
|
|
|
60
60
|
|
|
61
61
|
function getReservedToken(prop: string): CommandToken | 'Path' | undefined {
|
|
62
62
|
if (prop === 'Path') return prop;
|
|
63
|
-
|
|
63
|
+
// Own-property check only — `prop in COMMAND_TOKEN_SUFFIXES` would also match
|
|
64
|
+
// inherited Object.prototype members (`toString`, `valueOf`, `toLocaleString`,
|
|
65
|
+
// `hasOwnProperty`, `constructor`, …), so a path segment named after one of
|
|
66
|
+
// those (e.g. `$.count.toLocaleString`) would be mistaken for a command token
|
|
67
|
+
// and produce a garbled path.
|
|
68
|
+
if (Object.hasOwn(COMMAND_TOKEN_SUFFIXES, prop)) return prop as CommandToken;
|
|
64
69
|
return undefined;
|
|
65
70
|
}
|
|
66
71
|
|
|
@@ -70,26 +75,36 @@ function getReservedToken(prop: string): CommandToken | 'Path' | undefined {
|
|
|
70
75
|
* with a serialized path string accessor — while providing full autocomplete.
|
|
71
76
|
* Enhanced: also callable (for method call syntax) and includes reserved
|
|
72
77
|
* command markers such as `Each`, `EqNot`, and `PlusEq`.
|
|
78
|
+
*
|
|
79
|
+
* `Extra` carries alias keys (`aka`) and method names (`withMethods`) passed to
|
|
80
|
+
* `paths(...)` so they are accepted at every level of the chain — e.g.
|
|
81
|
+
* `$.count['🌐']` when `paths({ aka: { '🌐': 'toLocaleString' } })`.
|
|
73
82
|
*/
|
|
74
|
-
export type PathProxyCore = {
|
|
83
|
+
export type PathProxyCore<Extra extends string = never> = {
|
|
75
84
|
readonly Path: string;
|
|
76
|
-
readonly Each: PathProxy<any>;
|
|
77
|
-
readonly EqNot: PathProxy<any>;
|
|
78
|
-
readonly PlusEq: PathProxy<any>;
|
|
79
|
-
readonly QMEq: PathProxy<any>;
|
|
80
|
-
readonly YEq: PathProxy<any>;
|
|
81
|
-
readonly MinusEq: PathProxy<any>;
|
|
82
|
-
readonly Arrow: PathProxy<any>;
|
|
83
|
-
readonly EqAmp: PathProxy<any>;
|
|
85
|
+
readonly Each: PathProxy<any, Extra>;
|
|
86
|
+
readonly EqNot: PathProxy<any, Extra>;
|
|
87
|
+
readonly PlusEq: PathProxy<any, Extra>;
|
|
88
|
+
readonly QMEq: PathProxy<any, Extra>;
|
|
89
|
+
readonly YEq: PathProxy<any, Extra>;
|
|
90
|
+
readonly MinusEq: PathProxy<any, Extra>;
|
|
91
|
+
readonly Arrow: PathProxy<any, Extra>;
|
|
92
|
+
readonly EqAmp: PathProxy<any, Extra>;
|
|
93
|
+
} & {
|
|
94
|
+
readonly [K in Extra]: PathProxy<any, Extra> & PathProxyCore<Extra>
|
|
95
|
+
& ((...args: any[]) => PathProxy<any, Extra> & PathProxyCore<Extra>);
|
|
84
96
|
};
|
|
85
97
|
|
|
86
|
-
|
|
98
|
+
type PathLeaf<Extra extends string = never> =
|
|
99
|
+
PathProxyCore<Extra> & ((...args: any[]) => PathProxy<any, Extra> & PathProxyCore<Extra>);
|
|
100
|
+
|
|
101
|
+
export type PathProxy<T, Extra extends string = never> = {
|
|
87
102
|
[K in keyof T]-?: T[K] extends ((...args: any[]) => infer R)
|
|
88
|
-
? ((...args: any[]) => PathProxy<NonNullable<R
|
|
103
|
+
? ((...args: any[]) => PathProxy<NonNullable<R>, Extra> & PathProxyCore<Extra>) & PathProxy<NonNullable<R>, Extra> & PathProxyCore<Extra>
|
|
89
104
|
: T[K] extends (object | undefined | null)
|
|
90
|
-
? PathProxy<NonNullable<T[K]
|
|
91
|
-
:
|
|
92
|
-
} &
|
|
105
|
+
? PathProxy<NonNullable<T[K]>, Extra> & PathProxyCore<Extra> & ((...args: any[]) => PathProxy<any, Extra> & PathProxyCore<Extra>)
|
|
106
|
+
: PathLeaf<Extra>;
|
|
107
|
+
} & PathLeaf<Extra>;
|
|
93
108
|
|
|
94
109
|
/**
|
|
95
110
|
* Options for paths proxy creation.
|
|
@@ -239,11 +254,18 @@ function createPathProxy(prefix: string, options?: PathsOptions): any {
|
|
|
239
254
|
* // With aka (reverse alias applied):
|
|
240
255
|
* const $ = paths<MyEl>({ aka: { q: 'querySelector' } });
|
|
241
256
|
* $.querySelector('.user').textContent.Path // '?.q?..user?.textContent'
|
|
242
|
-
*
|
|
257
|
+
*
|
|
258
|
+
* // To write alias keys (emoji) directly in the chain, pass their union as the
|
|
259
|
+
* // second type argument — TypeScript cannot infer it while `T` is explicit:
|
|
260
|
+
* import { akaMethods as m } from 'assign-gingerly/DX/emojis.js';
|
|
261
|
+
* const $ = paths<MyEl, keyof typeof m>({ aka: m });
|
|
262
|
+
* $.count['🌐'].Path // '?.count?.🌐'
|
|
263
|
+
* // (or just use the real method name: $.count.toLocaleString — reverse-aliased to 🌐)
|
|
264
|
+
*
|
|
243
265
|
* // Inside sp template literals, .Path is not needed:
|
|
244
266
|
* sp`${$.lastName}, ${$.firstName}` // ['?.lastName', ', ', '?.firstName']
|
|
245
267
|
*/
|
|
246
|
-
export function paths<T>(options?: PathsOptions): PathProxy<T> {
|
|
268
|
+
export function paths<T, Extra extends string = never>(options?: PathsOptions): PathProxy<T, Extra> {
|
|
247
269
|
return createPathProxy('', options) as any;
|
|
248
270
|
}
|
|
249
271
|
|
package/package.json
CHANGED