@soda-gql/core 0.3.0 → 0.4.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/README.md +29 -9
- package/dist/adapter.d.cts +2 -2
- package/dist/adapter.d.ts +2 -2
- package/dist/{index-DH3lMepk.d.cts → index-C-evbm4T.d.ts} +47 -21
- package/dist/index-C-evbm4T.d.ts.map +1 -0
- package/dist/{index-WU6aMZjg.d.ts → index-IYiti5xq.d.cts} +47 -21
- package/dist/index-IYiti5xq.d.cts.map +1 -0
- package/dist/index.cjs +154 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +154 -22
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/{schema-C7q047S0.d.ts → schema-D88zIxYO.d.cts} +79 -16
- package/dist/schema-D88zIxYO.d.cts.map +1 -0
- package/dist/{schema-BElqa12z.d.cts → schema-DgHZfIVa.d.ts} +79 -16
- package/dist/schema-DgHZfIVa.d.ts.map +1 -0
- package/dist/{schema-builder-DDfulXP3.d.cts → schema-builder-DWYlI1oI.d.cts} +2 -2
- package/dist/{schema-builder-DDfulXP3.d.cts.map → schema-builder-DWYlI1oI.d.cts.map} +1 -1
- package/dist/{schema-builder-DfyTaFMt.d.ts → schema-builder-XjFwbmSc.d.ts} +2 -2
- package/dist/{schema-builder-DfyTaFMt.d.ts.map → schema-builder-XjFwbmSc.d.ts.map} +1 -1
- package/package.json +1 -1
- package/dist/index-DH3lMepk.d.cts.map +0 -1
- package/dist/index-WU6aMZjg.d.ts.map +0 -1
- package/dist/schema-BElqa12z.d.cts.map +0 -1
- package/dist/schema-C7q047S0.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -13,15 +13,25 @@ var VarRef = class {
|
|
|
13
13
|
const isVarRef = (value) => {
|
|
14
14
|
return typeof value === "object" && value !== null && value instanceof VarRef;
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Recursively checks if a NestedValue contains any VarRef.
|
|
18
|
+
* Used by getVarRefValue to determine if it's safe to return as ConstValue.
|
|
19
|
+
*/
|
|
20
|
+
const hasVarRefInside = (value) => {
|
|
21
|
+
if (isVarRef(value)) return true;
|
|
22
|
+
if (Array.isArray(value)) return value.some(hasVarRefInside);
|
|
23
|
+
if (typeof value === "object" && value !== null) return Object.values(value).some(hasVarRefInside);
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
16
26
|
const createVarRefFromVariable = (name) => {
|
|
17
27
|
return new VarRef({
|
|
18
28
|
type: "variable",
|
|
19
29
|
name
|
|
20
30
|
});
|
|
21
31
|
};
|
|
22
|
-
const
|
|
32
|
+
const createVarRefFromNestedValue = (value) => {
|
|
23
33
|
return new VarRef({
|
|
24
|
-
type: "
|
|
34
|
+
type: "nested-value",
|
|
25
35
|
value
|
|
26
36
|
});
|
|
27
37
|
};
|
|
@@ -30,22 +40,117 @@ const getVarRefInner = (varRef) => {
|
|
|
30
40
|
};
|
|
31
41
|
/**
|
|
32
42
|
* Get the variable name from a VarRef.
|
|
33
|
-
* Throws if the VarRef contains a
|
|
43
|
+
* Throws if the VarRef contains a nested-value instead of a variable reference.
|
|
34
44
|
*/
|
|
35
45
|
const getVarRefName = (varRef) => {
|
|
36
46
|
const inner = VarRef.getInner(varRef);
|
|
37
|
-
if (inner.type !== "variable") throw new Error("Expected variable reference, got
|
|
47
|
+
if (inner.type !== "variable") throw new Error("Expected variable reference, got nested-value");
|
|
38
48
|
return inner.name;
|
|
39
49
|
};
|
|
40
50
|
/**
|
|
41
51
|
* Get the const value from a VarRef.
|
|
42
|
-
* Throws if the VarRef contains a variable reference instead of a
|
|
52
|
+
* Throws if the VarRef contains a variable reference instead of a nested-value,
|
|
53
|
+
* or if the nested-value contains any VarRef inside.
|
|
43
54
|
*/
|
|
44
55
|
const getVarRefValue = (varRef) => {
|
|
45
56
|
const inner = VarRef.getInner(varRef);
|
|
46
|
-
if (inner.type !== "
|
|
57
|
+
if (inner.type !== "nested-value") throw new Error("Expected nested-value, got variable reference");
|
|
58
|
+
if (hasVarRefInside(inner.value)) throw new Error("Cannot get const value: nested-value contains VarRef");
|
|
47
59
|
return inner.value;
|
|
48
60
|
};
|
|
61
|
+
const SelectableProxyInnerRegistry = /* @__PURE__ */ new WeakMap();
|
|
62
|
+
const getSelectableProxyInner = (proxy) => {
|
|
63
|
+
const inner = SelectableProxyInnerRegistry.get(proxy);
|
|
64
|
+
if (!inner) throw new Error(`Proxy inner not found`);
|
|
65
|
+
return inner;
|
|
66
|
+
};
|
|
67
|
+
const createSelectableProxy = (current) => {
|
|
68
|
+
const proxy = new Proxy(Object.create(null), { get(_, property) {
|
|
69
|
+
if (typeof property === "symbol") throw new Error(`Prohibited property access: ${String(property)}`);
|
|
70
|
+
const nextSegments = [...current.segments, property];
|
|
71
|
+
if (current.varInner.type === "virtual") return createSelectableProxy({
|
|
72
|
+
varInner: current.varInner,
|
|
73
|
+
segments: nextSegments
|
|
74
|
+
});
|
|
75
|
+
if (current.varInner.type === "variable") return createSelectableProxy({
|
|
76
|
+
varInner: {
|
|
77
|
+
type: "virtual",
|
|
78
|
+
varName: current.varInner.name,
|
|
79
|
+
varSegments: nextSegments
|
|
80
|
+
},
|
|
81
|
+
segments: nextSegments
|
|
82
|
+
});
|
|
83
|
+
if (typeof current.varInner.value === "object" && current.varInner.value !== null) {
|
|
84
|
+
const value = current.varInner.value[property];
|
|
85
|
+
return createSelectableProxy({
|
|
86
|
+
varInner: isVarRef(value) ? getVarRefInner(value) : {
|
|
87
|
+
type: "nested-value",
|
|
88
|
+
value
|
|
89
|
+
},
|
|
90
|
+
segments: nextSegments
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
throw new Error(`Cannot access children of primitive value at path [${current.segments.join(".")}]`);
|
|
94
|
+
} });
|
|
95
|
+
SelectableProxyInnerRegistry.set(proxy, current);
|
|
96
|
+
return proxy;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Get the variable name from a VarRef at a specific path.
|
|
100
|
+
*
|
|
101
|
+
* @param varRef - The VarRef containing a nested-value
|
|
102
|
+
* @param selector - Path builder function, e.g., p => p.user.age
|
|
103
|
+
* @returns The variable name at the specified path
|
|
104
|
+
* @throws If path doesn't lead to a VarRef with type "variable"
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const ref = createVarRefFromNestedValue({
|
|
108
|
+
* user: { age: someVariableRef }
|
|
109
|
+
* });
|
|
110
|
+
* getNameAt(ref, p => p.user.age); // returns the variable name
|
|
111
|
+
*/
|
|
112
|
+
const getNameAt = (varRef, selector) => {
|
|
113
|
+
const inner = getSelectableProxyInner(selector(createSelectableProxy({
|
|
114
|
+
varInner: VarRef.getInner(varRef),
|
|
115
|
+
segments: []
|
|
116
|
+
})));
|
|
117
|
+
if (inner.varInner.type === "virtual") throw new Error(`Value at path [${inner.segments.join(".")}] is inside a variable`);
|
|
118
|
+
if (inner.varInner.type !== "variable") throw new Error(`Value at path [${inner.segments.join(".")}] is not a variable`);
|
|
119
|
+
return inner.varInner.name;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Get the const value from a nested-value VarRef at a specific path.
|
|
123
|
+
*
|
|
124
|
+
* @param varRef - The VarRef containing a nested-value
|
|
125
|
+
* @param pathFn - Path builder function, e.g., p => p.user.name
|
|
126
|
+
* @returns The const value at the specified path
|
|
127
|
+
* @throws If path leads to a VarRef or if value contains VarRef inside
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* const ref = createVarRefFromNestedValue({
|
|
131
|
+
* user: { name: "Alice", age: someVariableRef }
|
|
132
|
+
* });
|
|
133
|
+
* getValueAt(ref, p => p.user.name); // returns "Alice"
|
|
134
|
+
*/
|
|
135
|
+
const getValueAt = (varRef, selector) => {
|
|
136
|
+
const inner = getSelectableProxyInner(selector(createSelectableProxy({
|
|
137
|
+
varInner: VarRef.getInner(varRef),
|
|
138
|
+
segments: []
|
|
139
|
+
})));
|
|
140
|
+
if (inner.varInner.type === "virtual") throw new Error(`Value at path [${inner.segments.join(".")}] is inside a variable`);
|
|
141
|
+
if (inner.varInner.type !== "nested-value") throw new Error(`Value at path [${inner.segments.join(".")}] is not a nested-value`);
|
|
142
|
+
if (hasVarRefInside(inner.varInner.value)) throw new Error(`Value at path [${inner.segments.join(".")}] contains nested VarRef`);
|
|
143
|
+
return inner.varInner.value;
|
|
144
|
+
};
|
|
145
|
+
const getVariablePath = (varRef, selector) => {
|
|
146
|
+
const inner = getSelectableProxyInner(selector(createSelectableProxy({
|
|
147
|
+
varInner: VarRef.getInner(varRef),
|
|
148
|
+
segments: []
|
|
149
|
+
})));
|
|
150
|
+
if (inner.varInner.type === "virtual") return [`$${inner.varInner.varName}`, ...inner.segments.slice(inner.varInner.varSegments.length)];
|
|
151
|
+
if (inner.varInner.type === "variable") return [`$${inner.varInner.name}`];
|
|
152
|
+
throw new Error(`Value at path [${inner.segments.join(".")}] is not a variable or inside a variable`);
|
|
153
|
+
};
|
|
49
154
|
|
|
50
155
|
//#endregion
|
|
51
156
|
//#region packages/core/src/composer/build-document.ts
|
|
@@ -61,7 +166,7 @@ const buildArgumentValue = (value) => {
|
|
|
61
166
|
value: inner.name
|
|
62
167
|
}
|
|
63
168
|
};
|
|
64
|
-
if (inner.type === "
|
|
169
|
+
if (inner.type === "nested-value") return buildArgumentValue(inner.value);
|
|
65
170
|
throw new Error(`Unknown var ref type: ${inner}`);
|
|
66
171
|
}
|
|
67
172
|
if (Array.isArray(value)) return {
|
|
@@ -297,8 +402,8 @@ const buildDocument = (options) => {
|
|
|
297
402
|
* query.operation({
|
|
298
403
|
* name: "GetData",
|
|
299
404
|
* fields: ({ $ }) => $colocate({
|
|
300
|
-
* userCard: userCardFragment.
|
|
301
|
-
* posts: postsFragment.
|
|
405
|
+
* userCard: userCardFragment.spread({ userId: $.userId }),
|
|
406
|
+
* posts: postsFragment.spread({ userId: $.userId }),
|
|
302
407
|
* }),
|
|
303
408
|
* });
|
|
304
409
|
*
|
|
@@ -335,7 +440,7 @@ const fieldPathContext = { current: null };
|
|
|
335
440
|
* ```typescript
|
|
336
441
|
* import { getCurrentFieldPath } from '@soda-gql/core';
|
|
337
442
|
*
|
|
338
|
-
* // Inside a field builder or model
|
|
443
|
+
* // Inside a field builder or model spread:
|
|
339
444
|
* const path = getCurrentFieldPath();
|
|
340
445
|
* console.log(path?.full); // "$.user.posts[].author"
|
|
341
446
|
* ```
|
|
@@ -569,8 +674,8 @@ var Fragment = class Fragment extends GqlElement {
|
|
|
569
674
|
get typename() {
|
|
570
675
|
return GqlElement.get(this).typename;
|
|
571
676
|
}
|
|
572
|
-
get
|
|
573
|
-
return GqlElement.get(this).
|
|
677
|
+
get spread() {
|
|
678
|
+
return GqlElement.get(this).spread;
|
|
574
679
|
}
|
|
575
680
|
static create(define$1) {
|
|
576
681
|
return new Fragment(define$1);
|
|
@@ -633,7 +738,7 @@ const withFragmentUsageCollection = (fn) => {
|
|
|
633
738
|
}
|
|
634
739
|
};
|
|
635
740
|
/**
|
|
636
|
-
* Record a fragment usage. Called when fragment.
|
|
741
|
+
* Record a fragment usage. Called when fragment.spread() is invoked.
|
|
637
742
|
* No-op if not in a collection context.
|
|
638
743
|
*
|
|
639
744
|
* @internal
|
|
@@ -647,10 +752,10 @@ const recordFragmentUsage = (record) => {
|
|
|
647
752
|
const createVarAssignments = (definitions, providedValues) => {
|
|
648
753
|
return mapValues(definitions, (_definition, key) => {
|
|
649
754
|
const varName = key;
|
|
650
|
-
if (!providedValues || providedValues[varName] === void 0) return
|
|
755
|
+
if (!providedValues || providedValues[varName] === void 0) return createVarRefFromNestedValue(void 0);
|
|
651
756
|
const provided = providedValues[varName];
|
|
652
757
|
if (isVarRef(provided)) return provided;
|
|
653
|
-
return
|
|
758
|
+
return createVarRefFromNestedValue(provided);
|
|
654
759
|
});
|
|
655
760
|
};
|
|
656
761
|
const createVarRefs = (definitions) => mapValues(definitions, (_ref, name) => createVarRefFromVariable(name));
|
|
@@ -664,7 +769,7 @@ const createGqlFragmentComposers = (schema, _adapter) => {
|
|
|
664
769
|
const { metadata, fields } = options;
|
|
665
770
|
return Fragment.create(() => ({
|
|
666
771
|
typename,
|
|
667
|
-
|
|
772
|
+
spread: (variables) => {
|
|
668
773
|
const f = createFieldFactories(schema, typename);
|
|
669
774
|
const $ = createVarAssignments(varDefinitions, variables);
|
|
670
775
|
recordFragmentUsage({
|
|
@@ -758,6 +863,8 @@ const createOperationComposerFactory = (schema, adapter) => {
|
|
|
758
863
|
/**
|
|
759
864
|
* Creates a variable method for a specific input type.
|
|
760
865
|
* This is used by codegen to generate type-specific variable methods.
|
|
866
|
+
*
|
|
867
|
+
* @deprecated Use createVarMethodFactory instead for proper type inference with nested input objects.
|
|
761
868
|
*/
|
|
762
869
|
const createVarMethod = (kind, typeName) => {
|
|
763
870
|
return (modifier, extras) => ({
|
|
@@ -769,6 +876,30 @@ const createVarMethod = (kind, typeName) => {
|
|
|
769
876
|
});
|
|
770
877
|
};
|
|
771
878
|
/**
|
|
879
|
+
* Creates a factory function for generating schema-scoped variable methods.
|
|
880
|
+
* This ensures proper type inference for nested input objects by binding the schema type upfront.
|
|
881
|
+
*
|
|
882
|
+
* @example
|
|
883
|
+
* ```typescript
|
|
884
|
+
* const createMethod = createVarMethodFactory<typeof schema>();
|
|
885
|
+
* const inputTypeMethods = {
|
|
886
|
+
* Boolean: createMethod("scalar", "Boolean"),
|
|
887
|
+
* user_bool_exp: createMethod("input", "user_bool_exp"),
|
|
888
|
+
* } satisfies InputTypeMethods<typeof schema>;
|
|
889
|
+
* ```
|
|
890
|
+
*/
|
|
891
|
+
const createVarMethodFactory = () => {
|
|
892
|
+
return (kind, typeName) => {
|
|
893
|
+
return ((modifier, extras) => ({
|
|
894
|
+
kind,
|
|
895
|
+
name: typeName,
|
|
896
|
+
modifier,
|
|
897
|
+
defaultValue: extras?.default ? { default: extras.default() } : null,
|
|
898
|
+
directives: extras?.directives ?? {}
|
|
899
|
+
}));
|
|
900
|
+
};
|
|
901
|
+
};
|
|
902
|
+
/**
|
|
772
903
|
* Creates a variable builder that uses injected input type methods.
|
|
773
904
|
*/
|
|
774
905
|
const createVarBuilder = (inputTypeMethods) => {
|
|
@@ -784,6 +915,9 @@ const createVarBuilder = (inputTypeMethods) => {
|
|
|
784
915
|
varBuilder.getName = getVarRefName;
|
|
785
916
|
varBuilder.getValue = getVarRefValue;
|
|
786
917
|
varBuilder.getInner = getVarRefInner;
|
|
918
|
+
varBuilder.getNameAt = getNameAt;
|
|
919
|
+
varBuilder.getValueAt = getValueAt;
|
|
920
|
+
varBuilder.getVariablePath = getVariablePath;
|
|
787
921
|
return varBuilder;
|
|
788
922
|
};
|
|
789
923
|
|
|
@@ -795,21 +929,19 @@ const createGqlElementComposer = (schema, options) => {
|
|
|
795
929
|
const metadataAdapter = adapter?.metadata;
|
|
796
930
|
const fragment = createGqlFragmentComposers(schema, metadataAdapter);
|
|
797
931
|
const createOperationComposer = createOperationComposerFactory(schema, metadataAdapter);
|
|
798
|
-
const
|
|
932
|
+
const context = {
|
|
799
933
|
fragment,
|
|
800
934
|
query: { operation: createOperationComposer("query") },
|
|
801
935
|
mutation: { operation: createOperationComposer("mutation") },
|
|
802
|
-
subscription: { operation: createOperationComposer("subscription") }
|
|
803
|
-
};
|
|
804
|
-
const helper = {
|
|
936
|
+
subscription: { operation: createOperationComposer("subscription") },
|
|
805
937
|
$var: createVarBuilder(inputTypeMethods),
|
|
806
938
|
$colocate: createColocateHelper(),
|
|
807
939
|
...helpers ?? {}
|
|
808
940
|
};
|
|
809
|
-
const elementComposer = (composeElement) => composeElement(
|
|
941
|
+
const elementComposer = (composeElement) => composeElement(context);
|
|
810
942
|
return elementComposer;
|
|
811
943
|
};
|
|
812
944
|
|
|
813
945
|
//#endregion
|
|
814
|
-
export { Fragment, GqlElement, Operation, appendToPath, buildArgumentValue, buildConstValueNode, buildDocument, buildOperationTypeNode, buildWithTypeModifier, createColocateHelper, createDefaultAdapter, createFieldFactories, createGqlElementComposer, createGqlFragmentComposers, createOperationComposerFactory, createVarAssignments, createVarBuilder, createVarMethod, createVarRefs, defaultMetadataAdapter, define, defineOperationRoots, defineScalar, getCurrentFieldPath, getVarRefInner, getVarRefName, getVarRefValue, isListType, recordFragmentUsage, unsafeInputType, unsafeOutputType, withFieldPath, withFragmentUsageCollection };
|
|
946
|
+
export { Fragment, GqlElement, Operation, appendToPath, buildArgumentValue, buildConstValueNode, buildDocument, buildOperationTypeNode, buildWithTypeModifier, createColocateHelper, createDefaultAdapter, createFieldFactories, createGqlElementComposer, createGqlFragmentComposers, createOperationComposerFactory, createVarAssignments, createVarBuilder, createVarMethod, createVarMethodFactory, createVarRefs, defaultMetadataAdapter, define, defineOperationRoots, defineScalar, getCurrentFieldPath, getVarRefInner, getVarRefName, getVarRefValue, isListType, recordFragmentUsage, unsafeInputType, unsafeOutputType, withFieldPath, withFragmentUsageCollection };
|
|
815
947
|
//# sourceMappingURL=index.js.map
|