@signalium/query 1.0.18 → 1.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/CHANGELOG.md +41 -0
- package/dist/cjs/development/index.js +48 -12
- package/dist/cjs/development/index.js.map +1 -1
- package/dist/cjs/production/index.js +48 -12
- package/dist/cjs/production/index.js.map +1 -1
- package/dist/esm/QueryClient.d.ts +3 -2
- package/dist/esm/QueryClient.d.ts.map +1 -1
- package/dist/esm/development/index.js +48 -12
- package/dist/esm/development/index.js.map +1 -1
- package/dist/esm/mutation.d.ts.map +1 -1
- package/dist/esm/pathInterpolator.d.ts +7 -3
- package/dist/esm/pathInterpolator.d.ts.map +1 -1
- package/dist/esm/production/index.js +48 -12
- package/dist/esm/production/index.js.map +1 -1
- package/dist/esm/query.d.ts +14 -8
- package/dist/esm/query.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @signalium/query
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- af443c5: Add request body support to query() function
|
|
8
|
+
|
|
9
|
+
Queries can now send JSON request bodies for POST requests, enabling read-like operations that require complex data structures (e.g., fetching prices for an array of tokens).
|
|
10
|
+
|
|
11
|
+
**New features:**
|
|
12
|
+
|
|
13
|
+
- Added `body` field to query definitions for specifying request body schema
|
|
14
|
+
- Body parameters are automatically serialized as JSON with `Content-Type: application/json` header
|
|
15
|
+
- Body params work alongside path params and search params
|
|
16
|
+
- All query features (caching, staleTime, deduplication) work with body queries
|
|
17
|
+
|
|
18
|
+
**API changes:**
|
|
19
|
+
|
|
20
|
+
- Query methods are now restricted to `GET` and `POST` only (PUT, PATCH, DELETE should use `mutation()`)
|
|
21
|
+
|
|
22
|
+
**Example:**
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
const getPrices = query(() => ({
|
|
26
|
+
path: '/prices',
|
|
27
|
+
method: 'POST',
|
|
28
|
+
body: {
|
|
29
|
+
tokens: t.array(t.string),
|
|
30
|
+
},
|
|
31
|
+
searchParams: {
|
|
32
|
+
currency: t.string,
|
|
33
|
+
},
|
|
34
|
+
response: {
|
|
35
|
+
prices: t.array(t.object({ token: t.string, price: t.number })),
|
|
36
|
+
},
|
|
37
|
+
cache: { staleTime: 30_000 },
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
// Usage: POST /prices?currency=USD with body: {"tokens":["ETH","BTC"]}
|
|
41
|
+
const result = getPrices({ tokens: ['ETH', 'BTC'], currency: 'USD' });
|
|
42
|
+
```
|
|
43
|
+
|
|
3
44
|
## 1.0.18
|
|
4
45
|
|
|
5
46
|
### Patch Changes
|
|
@@ -2562,7 +2562,7 @@ var QueryType = /* @__PURE__ */ ((QueryType2) => {
|
|
|
2562
2562
|
return QueryType2;
|
|
2563
2563
|
})(QueryType || {});
|
|
2564
2564
|
function isSignal(value) {
|
|
2565
|
-
return typeof value === "object" && value !== null;
|
|
2565
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && "value" in value && "_id" in value;
|
|
2566
2566
|
}
|
|
2567
2567
|
function extractParamsForKey(params) {
|
|
2568
2568
|
if (params === void 0) {
|
|
@@ -2706,7 +2706,7 @@ function createPathInterpolator(pathTemplate) {
|
|
|
2706
2706
|
lastIndex = paramRegex.lastIndex;
|
|
2707
2707
|
}
|
|
2708
2708
|
segments.push(pathTemplate.slice(lastIndex));
|
|
2709
|
-
|
|
2709
|
+
const interpolate = (params) => {
|
|
2710
2710
|
let result = segments[0];
|
|
2711
2711
|
for (let i = 0; i < paramKeys.length; i++) {
|
|
2712
2712
|
result += encodeURIComponent(String(params[paramKeys[i]])) + segments[i + 1];
|
|
@@ -2725,6 +2725,7 @@ function createPathInterpolator(pathTemplate) {
|
|
|
2725
2725
|
}
|
|
2726
2726
|
return result;
|
|
2727
2727
|
};
|
|
2728
|
+
return { interpolate, pathParamNames: paramKeysSet };
|
|
2728
2729
|
}
|
|
2729
2730
|
const QUERY_DEFINITION_MAP = /* @__PURE__ */ new Map();
|
|
2730
2731
|
function buildQueryFn(queryDefinitionBuilder) {
|
|
@@ -2734,6 +2735,8 @@ function buildQueryFn(queryDefinitionBuilder) {
|
|
|
2734
2735
|
const {
|
|
2735
2736
|
path,
|
|
2736
2737
|
method = "GET",
|
|
2738
|
+
searchParams,
|
|
2739
|
+
body,
|
|
2737
2740
|
response,
|
|
2738
2741
|
requestOptions,
|
|
2739
2742
|
cache,
|
|
@@ -2760,14 +2763,53 @@ function buildQueryFn(queryDefinitionBuilder) {
|
|
|
2760
2763
|
shape = response;
|
|
2761
2764
|
shapeKey = utils.hashValue(shape);
|
|
2762
2765
|
}
|
|
2763
|
-
const interpolatePath = createPathInterpolator(path);
|
|
2766
|
+
const { interpolate: interpolatePath, pathParamNames } = createPathInterpolator(path);
|
|
2767
|
+
const bodyParamNames = /* @__PURE__ */ new Set();
|
|
2768
|
+
const hasBody = body !== void 0 && typeof body === "object" && !(body instanceof ValidatorDef) && !(body instanceof Set);
|
|
2769
|
+
if (hasBody) {
|
|
2770
|
+
for (const key of Object.keys(body)) {
|
|
2771
|
+
bodyParamNames.add(key);
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
const searchParamNames = new Set(
|
|
2775
|
+
searchParams && typeof searchParams === "object" && !(searchParams instanceof ValidatorDef) && !(searchParams instanceof Set) ? Object.keys(searchParams) : []
|
|
2776
|
+
);
|
|
2777
|
+
const checkConflicts = (sourceNames, targetNames, sourceLabel, targetLabel) => {
|
|
2778
|
+
const conflicts = [...sourceNames].filter((name) => targetNames.has(name));
|
|
2779
|
+
if (conflicts.length > 0) {
|
|
2780
|
+
throw new Error(
|
|
2781
|
+
`Query definition error: ${sourceLabel} [${conflicts.join(", ")}] conflict with ${targetLabel}. Please rename to avoid this conflict.`
|
|
2782
|
+
);
|
|
2783
|
+
}
|
|
2784
|
+
};
|
|
2785
|
+
checkConflicts(searchParamNames, pathParamNames, "Search param(s)", `path parameter(s) in "${path}"`);
|
|
2786
|
+
checkConflicts(bodyParamNames, pathParamNames, "Body field(s)", `path parameter(s) in "${path}"`);
|
|
2787
|
+
checkConflicts(bodyParamNames, searchParamNames, "Body field(s)", "search param(s)");
|
|
2764
2788
|
const fetchFn = async (context, params) => {
|
|
2765
|
-
|
|
2789
|
+
let bodyData;
|
|
2790
|
+
let urlParams = params;
|
|
2791
|
+
if (hasBody) {
|
|
2792
|
+
bodyData = {};
|
|
2793
|
+
urlParams = params !== void 0 ? {} : void 0;
|
|
2794
|
+
if (params !== void 0) {
|
|
2795
|
+
for (const key in params) {
|
|
2796
|
+
if (bodyParamNames.has(key)) {
|
|
2797
|
+
bodyData[key] = params[key];
|
|
2798
|
+
} else {
|
|
2799
|
+
urlParams[key] = params[key];
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
const interpolatedPath = interpolatePath(urlParams ?? {});
|
|
2766
2805
|
const baseUrl = resolveBaseUrl(requestOptions?.baseUrl) ?? resolveBaseUrl(context.baseUrl);
|
|
2767
2806
|
const fullUrl = baseUrl ? `${baseUrl}${interpolatedPath}` : interpolatedPath;
|
|
2768
|
-
const { baseUrl: _baseUrl, ...fetchOptions } = requestOptions ?? {};
|
|
2807
|
+
const { baseUrl: _baseUrl, headers: userHeaders, ...fetchOptions } = requestOptions ?? {};
|
|
2808
|
+
const headers = bodyData ? { "Content-Type": "application/json", ...userHeaders } : userHeaders;
|
|
2769
2809
|
const response2 = await context.fetch(fullUrl, {
|
|
2770
2810
|
method,
|
|
2811
|
+
headers,
|
|
2812
|
+
body: bodyData ? JSON.stringify(bodyData) : void 0,
|
|
2771
2813
|
...fetchOptions
|
|
2772
2814
|
});
|
|
2773
2815
|
return response2.json();
|
|
@@ -2928,13 +2970,7 @@ function buildMutationFn(mutationDefinitionBuilder) {
|
|
|
2928
2970
|
const id = `mutation:${method}:${path}`;
|
|
2929
2971
|
const { shape: requestShape, shapeKey: requestShapeKey } = processTypeDef(request);
|
|
2930
2972
|
const { shape: responseShape, shapeKey: responseShapeKey } = processTypeDef(response);
|
|
2931
|
-
const interpolatePath = createPathInterpolator(path);
|
|
2932
|
-
const pathParamNames = /* @__PURE__ */ new Set();
|
|
2933
|
-
const paramRegex = /\[([^\]]+)\]/g;
|
|
2934
|
-
let match;
|
|
2935
|
-
while ((match = paramRegex.exec(path)) !== null) {
|
|
2936
|
-
pathParamNames.add(match[1]);
|
|
2937
|
-
}
|
|
2973
|
+
const { interpolate: interpolatePath, pathParamNames } = createPathInterpolator(path);
|
|
2938
2974
|
const mutateFn = async (context, requestData) => {
|
|
2939
2975
|
const pathParams = {};
|
|
2940
2976
|
for (const paramName of pathParamNames) {
|