@sylphx/lens-server 2.0.1 → 2.1.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/dist/index.d.ts +18 -2
- package/dist/index.js +20 -2
- package/package.json +1 -1
- package/src/server/selection.ts +82 -3
- package/src/server/types.ts +19 -2
package/dist/index.d.ts
CHANGED
|
@@ -436,11 +436,27 @@ declare class PluginManager {
|
|
|
436
436
|
*/
|
|
437
437
|
declare function createPluginManager(): PluginManager;
|
|
438
438
|
import { FieldType } from "@sylphx/lens-core";
|
|
439
|
-
/**
|
|
439
|
+
/**
|
|
440
|
+
* Nested selection object with optional input.
|
|
441
|
+
* Used for relations that need their own params.
|
|
442
|
+
*/
|
|
443
|
+
interface NestedSelection {
|
|
444
|
+
/** Input/params for this nested query */
|
|
445
|
+
input?: Record<string, unknown>;
|
|
446
|
+
/** Field selection for this nested query */
|
|
447
|
+
select?: SelectionObject;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Selection object for field selection.
|
|
451
|
+
* Supports:
|
|
452
|
+
* - `true` - Select this field
|
|
453
|
+
* - `{ select: {...} }` - Nested selection only
|
|
454
|
+
* - `{ input: {...}, select?: {...} }` - Nested with input params
|
|
455
|
+
*/
|
|
440
456
|
interface SelectionObject {
|
|
441
457
|
[key: string]: boolean | SelectionObject | {
|
|
442
458
|
select: SelectionObject;
|
|
443
|
-
};
|
|
459
|
+
} | NestedSelection;
|
|
444
460
|
}
|
|
445
461
|
/** Entity map type */
|
|
446
462
|
type EntitiesMap = Record<string, EntityDef<string, any>>;
|
package/dist/index.js
CHANGED
|
@@ -215,6 +215,20 @@ class DataLoader {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
// src/server/selection.ts
|
|
218
|
+
function extractSelect(value) {
|
|
219
|
+
if (value === true)
|
|
220
|
+
return null;
|
|
221
|
+
if (typeof value !== "object" || value === null)
|
|
222
|
+
return null;
|
|
223
|
+
const obj = value;
|
|
224
|
+
if ("input" in obj || "select" in obj && typeof obj.select === "object") {
|
|
225
|
+
return obj.select ?? null;
|
|
226
|
+
}
|
|
227
|
+
if ("select" in obj && typeof obj.select === "object") {
|
|
228
|
+
return obj.select;
|
|
229
|
+
}
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
218
232
|
function applySelection(data, select) {
|
|
219
233
|
if (!data)
|
|
220
234
|
return data;
|
|
@@ -233,8 +247,12 @@ function applySelection(data, select) {
|
|
|
233
247
|
if (value === true) {
|
|
234
248
|
result[key] = obj[key];
|
|
235
249
|
} else if (typeof value === "object" && value !== null) {
|
|
236
|
-
const nestedSelect =
|
|
237
|
-
|
|
250
|
+
const nestedSelect = extractSelect(value);
|
|
251
|
+
if (nestedSelect) {
|
|
252
|
+
result[key] = applySelection(obj[key], nestedSelect);
|
|
253
|
+
} else {
|
|
254
|
+
result[key] = obj[key];
|
|
255
|
+
}
|
|
238
256
|
}
|
|
239
257
|
}
|
|
240
258
|
return result;
|
package/package.json
CHANGED
package/src/server/selection.ts
CHANGED
|
@@ -4,12 +4,53 @@
|
|
|
4
4
|
* Field selection logic for query results.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { SelectionObject } from "./types.js";
|
|
7
|
+
import type { NestedSelection, SelectionObject } from "./types.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if a value is a NestedSelection with input.
|
|
11
|
+
*/
|
|
12
|
+
function isNestedSelection(value: unknown): value is NestedSelection {
|
|
13
|
+
return (
|
|
14
|
+
typeof value === "object" &&
|
|
15
|
+
value !== null &&
|
|
16
|
+
("input" in value || "select" in value) &&
|
|
17
|
+
!Array.isArray(value)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract the select object from a selection value.
|
|
23
|
+
* Handles: true, SelectionObject, { select: ... }, { input: ..., select: ... }
|
|
24
|
+
*/
|
|
25
|
+
function extractSelect(value: unknown): SelectionObject | null {
|
|
26
|
+
if (value === true) return null;
|
|
27
|
+
if (typeof value !== "object" || value === null) return null;
|
|
28
|
+
|
|
29
|
+
const obj = value as Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
// { input?: ..., select?: ... } pattern
|
|
32
|
+
if ("input" in obj || ("select" in obj && typeof obj.select === "object")) {
|
|
33
|
+
return (obj.select as SelectionObject) ?? null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// { select: ... } pattern (without input)
|
|
37
|
+
if ("select" in obj && typeof obj.select === "object") {
|
|
38
|
+
return obj.select as SelectionObject;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Direct SelectionObject
|
|
42
|
+
return value as SelectionObject;
|
|
43
|
+
}
|
|
8
44
|
|
|
9
45
|
/**
|
|
10
46
|
* Apply field selection to data.
|
|
11
47
|
* Recursively filters data to only include selected fields.
|
|
12
48
|
*
|
|
49
|
+
* Supports:
|
|
50
|
+
* - `field: true` - Include field as-is
|
|
51
|
+
* - `field: { select: {...} }` - Nested selection
|
|
52
|
+
* - `field: { input: {...}, select: {...} }` - Nested with input (input passed to resolvers)
|
|
53
|
+
*
|
|
13
54
|
* @param data - The data to filter
|
|
14
55
|
* @param select - Selection object specifying which fields to include
|
|
15
56
|
* @returns Filtered data with only selected fields
|
|
@@ -35,10 +76,48 @@ export function applySelection(data: unknown, select: SelectionObject): unknown
|
|
|
35
76
|
if (value === true) {
|
|
36
77
|
result[key] = obj[key];
|
|
37
78
|
} else if (typeof value === "object" && value !== null) {
|
|
38
|
-
const nestedSelect =
|
|
39
|
-
|
|
79
|
+
const nestedSelect = extractSelect(value);
|
|
80
|
+
if (nestedSelect) {
|
|
81
|
+
result[key] = applySelection(obj[key], nestedSelect);
|
|
82
|
+
} else {
|
|
83
|
+
// No nested select means include the whole field
|
|
84
|
+
result[key] = obj[key];
|
|
85
|
+
}
|
|
40
86
|
}
|
|
41
87
|
}
|
|
42
88
|
|
|
43
89
|
return result;
|
|
44
90
|
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Extract nested inputs from a selection object.
|
|
94
|
+
* Returns a map of field paths to their input params.
|
|
95
|
+
* Used by resolvers to fetch nested data with the right params.
|
|
96
|
+
*/
|
|
97
|
+
export function extractNestedInputs(
|
|
98
|
+
select: SelectionObject,
|
|
99
|
+
prefix = "",
|
|
100
|
+
): Map<string, Record<string, unknown>> {
|
|
101
|
+
const inputs = new Map<string, Record<string, unknown>>();
|
|
102
|
+
|
|
103
|
+
for (const [key, value] of Object.entries(select)) {
|
|
104
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
105
|
+
|
|
106
|
+
if (isNestedSelection(value) && value.input) {
|
|
107
|
+
inputs.set(path, value.input);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Recurse into nested selections
|
|
111
|
+
if (typeof value === "object" && value !== null) {
|
|
112
|
+
const nestedSelect = extractSelect(value);
|
|
113
|
+
if (nestedSelect) {
|
|
114
|
+
const nestedInputs = extractNestedInputs(nestedSelect, path);
|
|
115
|
+
for (const [nestedPath, nestedInput] of nestedInputs) {
|
|
116
|
+
inputs.set(nestedPath, nestedInput);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return inputs;
|
|
123
|
+
}
|
package/src/server/types.ts
CHANGED
|
@@ -20,9 +20,26 @@ import type { PluginManager, ServerPlugin } from "../plugin/types.js";
|
|
|
20
20
|
// Selection Types
|
|
21
21
|
// =============================================================================
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Nested selection object with optional input.
|
|
25
|
+
* Used for relations that need their own params.
|
|
26
|
+
*/
|
|
27
|
+
export interface NestedSelection {
|
|
28
|
+
/** Input/params for this nested query */
|
|
29
|
+
input?: Record<string, unknown>;
|
|
30
|
+
/** Field selection for this nested query */
|
|
31
|
+
select?: SelectionObject;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Selection object for field selection.
|
|
36
|
+
* Supports:
|
|
37
|
+
* - `true` - Select this field
|
|
38
|
+
* - `{ select: {...} }` - Nested selection only
|
|
39
|
+
* - `{ input: {...}, select?: {...} }` - Nested with input params
|
|
40
|
+
*/
|
|
24
41
|
export interface SelectionObject {
|
|
25
|
-
[key: string]: boolean | SelectionObject | { select: SelectionObject };
|
|
42
|
+
[key: string]: boolean | SelectionObject | { select: SelectionObject } | NestedSelection;
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
// =============================================================================
|