Skip to content

Commit 28eca18

Browse files
authored
merge dev to main (v2.2.1) (#1500)
2 parents b9c7572 + 92f187f commit 28eca18

File tree

17 files changed

+232
-17
lines changed

17 files changed

+232
-17
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zenstack-monorepo",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"description": "",
55
"scripts": {
66
"build": "pnpm -r build",

packages/ide/jetbrains/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44
### Added
5+
- Support comparing fields from different models in mutation policy rules ("create", "update", and "delete).
6+
7+
## 2.1.0
8+
### Added
59
- Support using ZModel type names (e.g., `DateTime`) as model field names.
610
- `auth()` is resolved from all reachable schema files.
711

packages/ide/jetbrains/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ plugins {
99
}
1010

1111
group = "dev.zenstack"
12-
version = "2.2.0"
12+
version = "2.2.1"
1313

1414
repositories {
1515
mavenCentral()

packages/ide/jetbrains/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jetbrains",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"displayName": "ZenStack JetBrains IDE Plugin",
55
"description": "ZenStack JetBrains IDE plugin",
66
"homepage": "https://zenstack.dev",

packages/language/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/language",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"displayName": "ZenStack modeling language compiler",
55
"description": "ZenStack modeling language compiler",
66
"homepage": "https://zenstack.dev",

packages/misc/redwood/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/redwood",
33
"displayName": "ZenStack RedwoodJS Integration",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.",
66
"repository": {
77
"type": "git",

packages/plugins/openapi/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/openapi",
33
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "ZenStack plugin and runtime supporting OpenAPI",
66
"main": "index.js",
77
"repository": {

packages/plugins/swr/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/swr",
33
"displayName": "ZenStack plugin for generating SWR hooks",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "ZenStack plugin for generating SWR hooks",
66
"main": "index.js",
77
"repository": {

packages/plugins/tanstack-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/tanstack-query",
33
"displayName": "ZenStack plugin for generating tanstack-query hooks",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "ZenStack plugin for generating tanstack-query hooks",
66
"main": "index.js",
77
"exports": {
Lines changed: 212 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,212 @@
1-
export * from '../runtime/vue';
1+
/* eslint-disable @typescript-eslint/ban-types */
2+
/* eslint-disable @typescript-eslint/no-explicit-any */
3+
import {
4+
useInfiniteQuery,
5+
useMutation,
6+
useQuery,
7+
useQueryClient,
8+
type InfiniteData,
9+
type QueryKey,
10+
type UseInfiniteQueryOptions,
11+
type UseMutationOptions,
12+
type UseQueryOptions,
13+
} from '@tanstack/vue-query';
14+
import type { ModelMeta } from '@zenstackhq/runtime/cross';
15+
import { computed, inject, provide, toValue, type ComputedRef, type MaybeRefOrGetter } from 'vue';
16+
import {
17+
APIContext,
18+
DEFAULT_QUERY_ENDPOINT,
19+
fetcher,
20+
getQueryKey,
21+
makeUrl,
22+
marshal,
23+
setupInvalidation,
24+
setupOptimisticUpdate,
25+
type ExtraMutationOptions,
26+
type ExtraQueryOptions,
27+
type FetchFn,
28+
} from '../runtime/common';
29+
30+
export { APIContext as RequestHandlerContext } from '../runtime/common';
31+
32+
export const VueQueryContextKey = 'zenstack-vue-query-context';
33+
34+
/**
35+
* Provide context for the generated TanStack Query hooks.
36+
*/
37+
export function provideHooksContext(context: APIContext) {
38+
provide<APIContext>(VueQueryContextKey, context);
39+
}
40+
41+
/**
42+
* Hooks context.
43+
*/
44+
export function getHooksContext() {
45+
const { endpoint, ...rest } = inject<APIContext>(VueQueryContextKey, {
46+
endpoint: DEFAULT_QUERY_ENDPOINT,
47+
fetch: undefined,
48+
logging: false,
49+
});
50+
return { endpoint: endpoint ?? DEFAULT_QUERY_ENDPOINT, ...rest };
51+
}
52+
53+
/**
54+
* Creates a vue-query query.
55+
*
56+
* @param model The name of the model under query.
57+
* @param url The request URL.
58+
* @param args The request args object, URL-encoded and appended as "?q=" parameter
59+
* @param options The vue-query options object
60+
* @param fetch The fetch function to use for sending the HTTP request
61+
* @returns useQuery hook
62+
*/
63+
export function useModelQuery<TQueryFnData, TData, TError>(
64+
model: string,
65+
url: string,
66+
args?: MaybeRefOrGetter<unknown> | ComputedRef<unknown>,
67+
options?:
68+
| MaybeRefOrGetter<Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'> & ExtraQueryOptions>
69+
| ComputedRef<Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'> & ExtraQueryOptions>,
70+
fetch?: FetchFn
71+
) {
72+
const queryOptions = computed(() => {
73+
const optionsValue = toValue<
74+
(Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'> & ExtraQueryOptions) | undefined
75+
>(options);
76+
return {
77+
queryKey: getQueryKey(model, url, args, {
78+
infinite: false,
79+
optimisticUpdate: optionsValue?.optimisticUpdate !== false,
80+
}),
81+
queryFn: ({ queryKey }: { queryKey: QueryKey }) => {
82+
const [_prefix, _model, _op, args] = queryKey;
83+
const reqUrl = makeUrl(url, toValue(args));
84+
return fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false);
85+
},
86+
...optionsValue,
87+
};
88+
});
89+
return useQuery<TQueryFnData, TError, TData>(queryOptions);
90+
}
91+
92+
/**
93+
* Creates a vue-query infinite query.
94+
*
95+
* @param model The name of the model under query.
96+
* @param url The request URL.
97+
* @param args The initial request args object, URL-encoded and appended as "?q=" parameter
98+
* @param options The vue-query infinite query options object
99+
* @param fetch The fetch function to use for sending the HTTP request
100+
* @returns useInfiniteQuery hook
101+
*/
102+
export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
103+
model: string,
104+
url: string,
105+
args?: MaybeRefOrGetter<unknown> | ComputedRef<unknown>,
106+
options?:
107+
| MaybeRefOrGetter<
108+
Omit<UseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey' | 'initialPageParam'>
109+
>
110+
| ComputedRef<
111+
Omit<UseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey' | 'initialPageParam'>
112+
>,
113+
fetch?: FetchFn
114+
) {
115+
// CHECKME: vue-query's `useInfiniteQuery`'s input typing seems wrong
116+
const queryOptions: any = computed(() => ({
117+
queryKey: getQueryKey(model, url, args, { infinite: true, optimisticUpdate: false }),
118+
queryFn: ({ queryKey, pageParam }: { queryKey: QueryKey; pageParam?: unknown }) => {
119+
const [_prefix, _model, _op, args] = queryKey;
120+
const reqUrl = makeUrl(url, pageParam ?? toValue(args));
121+
return fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false);
122+
},
123+
initialPageParam: toValue(args),
124+
...toValue(options),
125+
}));
126+
127+
return useInfiniteQuery<TQueryFnData, TError, InfiniteData<TData>>(queryOptions);
128+
}
129+
130+
/**
131+
* Creates a mutation with vue-query.
132+
*
133+
* @param model The name of the model under mutation.
134+
* @param method The HTTP method.
135+
* @param modelMeta The model metadata.
136+
* @param url The request URL.
137+
* @param options The vue-query options.
138+
* @param fetch The fetch function to use for sending the HTTP request
139+
* @param checkReadBack Whether to check for read back errors and return undefined if found.
140+
* @returns useMutation hooks
141+
*/
142+
export function useModelMutation<
143+
TArgs,
144+
TError,
145+
R = any,
146+
C extends boolean = boolean,
147+
Result = C extends true ? R | undefined : R
148+
>(
149+
model: string,
150+
method: 'POST' | 'PUT' | 'DELETE',
151+
url: string,
152+
modelMeta: ModelMeta,
153+
options?:
154+
| MaybeRefOrGetter<
155+
Omit<UseMutationOptions<Result, TError, TArgs, unknown>, 'mutationFn'> & ExtraMutationOptions
156+
>
157+
| ComputedRef<Omit<UseMutationOptions<Result, TError, TArgs, unknown>, 'mutationFn'> & ExtraMutationOptions>,
158+
fetch?: FetchFn,
159+
checkReadBack?: C
160+
) {
161+
const queryClient = useQueryClient();
162+
const mutationFn = (data: any) => {
163+
const reqUrl = method === 'DELETE' ? makeUrl(url, data) : url;
164+
const fetchInit: RequestInit = {
165+
method,
166+
...(method !== 'DELETE' && {
167+
headers: {
168+
'content-type': 'application/json',
169+
},
170+
body: marshal(data),
171+
}),
172+
};
173+
return fetcher<R, C>(reqUrl, fetchInit, fetch, checkReadBack) as Promise<Result>;
174+
};
175+
176+
const optionsValue = toValue<
177+
(Omit<UseMutationOptions<Result, TError, TArgs, unknown>, 'mutationFn'> & ExtraMutationOptions) | undefined
178+
>(options);
179+
// TODO: figure out the typing problem
180+
const finalOptions: any = computed(() => ({ ...optionsValue, mutationFn }));
181+
const operation = url.split('/').pop();
182+
const invalidateQueries = optionsValue?.invalidateQueries !== false;
183+
const optimisticUpdate = !!optionsValue?.optimisticUpdate;
184+
185+
if (operation) {
186+
const { logging } = getHooksContext();
187+
if (invalidateQueries) {
188+
setupInvalidation(
189+
model,
190+
operation,
191+
modelMeta,
192+
toValue(finalOptions),
193+
(predicate) => queryClient.invalidateQueries({ predicate }),
194+
logging
195+
);
196+
}
197+
198+
if (optimisticUpdate) {
199+
setupOptimisticUpdate(
200+
model,
201+
operation,
202+
modelMeta,
203+
toValue(finalOptions),
204+
queryClient.getQueryCache().getAll(),
205+
(queryKey, data) => queryClient.setQueryData<unknown>(queryKey, data),
206+
invalidateQueries ? (predicate) => queryClient.invalidateQueries({ predicate }) : undefined,
207+
logging
208+
);
209+
}
210+
}
211+
return useMutation<Result, TError, TArgs>(finalOptions);
212+
}

packages/plugins/tanstack-query/src/runtime/vue.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* eslint-disable @typescript-eslint/ban-types */
22
/* eslint-disable @typescript-eslint/no-explicit-any */
3-
import type { InfiniteData } from '@tanstack/react-query-v5';
43
import {
54
useInfiniteQuery,
65
useMutation,
76
useQuery,
87
useQueryClient,
8+
type InfiniteData,
99
type QueryKey,
1010
type UseInfiniteQueryOptions,
1111
type UseMutationOptions,
@@ -124,7 +124,7 @@ export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
124124
...toValue(options),
125125
}));
126126

127-
return useInfiniteQuery<TQueryFnData, TError, InfiniteData<TData>>(queryOptions);
127+
return useInfiniteQuery<TQueryFnData, TError, TData>(queryOptions);
128128
}
129129

130130
/**

packages/plugins/trpc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/trpc",
33
"displayName": "ZenStack plugin for tRPC",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "ZenStack plugin for tRPC",
66
"main": "index.js",
77
"repository": {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/runtime",
33
"displayName": "ZenStack Runtime Library",
4-
"version": "2.2.0",
4+
"version": "2.2.1",
55
"description": "Runtime of ZenStack for both client-side and server-side environments.",
66
"repository": {
77
"type": "git",

packages/schema/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"publisher": "zenstack",
44
"displayName": "ZenStack Language Tools",
55
"description": "Build scalable web apps with minimum code by defining authorization and validation rules inside the data schema that closer to the database",
6-
"version": "2.2.0",
6+
"version": "2.2.1",
77
"author": {
88
"name": "ZenStack Team"
99
},

packages/sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/sdk",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"description": "ZenStack plugin development SDK",
55
"main": "index.js",
66
"scripts": {

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/server",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"displayName": "ZenStack Server-side Adapters",
55
"description": "ZenStack server-side adapters",
66
"homepage": "https://zenstack.dev",

packages/testtools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/testtools",
3-
"version": "2.2.0",
3+
"version": "2.2.1",
44
"description": "ZenStack Test Tools",
55
"main": "index.js",
66
"private": true,

0 commit comments

Comments
 (0)