@bg-dev/nuxt-zenstack 0.0.2 → 0.0.4
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/module.d.mts +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +29 -14
- package/dist/runtime/composables/common.d.ts +6 -8
- package/dist/runtime/composables/common.js +7 -0
- package/dist/runtime/composables/index.d.ts +1 -0
- package/dist/runtime/composables/index.js +1 -0
- package/dist/runtime/composables/useZenstackCreate/index.d.ts +3 -3
- package/dist/runtime/composables/useZenstackCreate/index.js +10 -8
- package/dist/runtime/composables/useZenstackDelete/index.d.ts +3 -3
- package/dist/runtime/composables/useZenstackDelete/index.js +9 -4
- package/dist/runtime/composables/useZenstackRead/index.d.ts +7 -7
- package/dist/runtime/composables/useZenstackRead/index.js +38 -29
- package/dist/runtime/composables/useZenstackReadMany/index.d.ts +9 -8
- package/dist/runtime/composables/useZenstackReadMany/index.js +54 -34
- package/dist/runtime/composables/useZenstackReadMany/orderBy.d.ts +5 -0
- package/dist/runtime/composables/useZenstackReadMany/orderBy.js +25 -0
- package/dist/runtime/composables/useZenstackReadMany/where.d.ts +2 -0
- package/dist/runtime/composables/useZenstackReadMany/where.js +235 -0
- package/dist/runtime/composables/useZenstackStore/helpers.js +4 -4
- package/dist/runtime/composables/useZenstackStore/index.d.ts +34 -2
- package/dist/runtime/composables/useZenstackStore/index.js +27 -6
- package/dist/runtime/composables/useZenstackStore/normalization.d.ts +16 -3
- package/dist/runtime/composables/useZenstackStore/normalization.js +16 -3
- package/dist/runtime/composables/useZenstackUpdate/index.d.ts +2 -2
- package/dist/runtime/composables/useZenstackUpdate/index.js +10 -8
- package/dist/runtime/server/api/models/[model]/[id].delete.js +4 -1
- package/dist/runtime/server/api/models/[model]/[id].get.js +4 -1
- package/dist/runtime/server/api/models/[model]/[id].patch.js +10 -5
- package/dist/runtime/server/api/models/[model]/index.get.js +4 -1
- package/dist/runtime/server/api/models/[model]/index.post.js +10 -5
- package/dist/runtime/server/utils/error.d.ts +9 -0
- package/dist/runtime/server/utils/error.js +49 -0
- package/dist/runtime/server/utils/index.d.ts +5 -8
- package/dist/runtime/server/utils/index.js +27 -10
- package/dist/runtime/server/utils/parsers.d.ts +2 -2
- package/dist/runtime/server/utils/parsers.js +2 -2
- package/package.json +3 -1
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
export function matchesWhere(item, where) {
|
|
2
|
+
if (!where) return true;
|
|
3
|
+
if (!item) return false;
|
|
4
|
+
const itemRecord = item;
|
|
5
|
+
const whereRecord = where;
|
|
6
|
+
for (const key of Object.keys(whereRecord)) {
|
|
7
|
+
if (whereRecord[key] === void 0) continue;
|
|
8
|
+
const filter = whereRecord[key];
|
|
9
|
+
if (key === "AND") {
|
|
10
|
+
if (Array.isArray(filter)) {
|
|
11
|
+
if (!filter.every((cond) => matchesWhere(item, cond))) return false;
|
|
12
|
+
} else {
|
|
13
|
+
if (!matchesWhere(item, filter)) return false;
|
|
14
|
+
}
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (key === "OR") {
|
|
18
|
+
if (Array.isArray(filter)) {
|
|
19
|
+
if (!filter.some((cond) => matchesWhere(item, cond))) return false;
|
|
20
|
+
} else {
|
|
21
|
+
if (!matchesWhere(item, filter)) return false;
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (key === "NOT") {
|
|
26
|
+
if (Array.isArray(filter)) {
|
|
27
|
+
if (filter.some((cond) => matchesWhere(item, cond))) return false;
|
|
28
|
+
} else {
|
|
29
|
+
if (matchesWhere(item, filter)) return false;
|
|
30
|
+
}
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const value = itemRecord[key];
|
|
34
|
+
if (!checkCondition(value, filter)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function checkCondition(value, filter) {
|
|
41
|
+
if (filter === null) {
|
|
42
|
+
return value === null;
|
|
43
|
+
}
|
|
44
|
+
if (filter === void 0) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (typeof filter !== "object" && typeof filter !== "function") {
|
|
48
|
+
if (value instanceof Date && typeof filter === "string") {
|
|
49
|
+
return value.toISOString() === filter;
|
|
50
|
+
}
|
|
51
|
+
return value === filter;
|
|
52
|
+
}
|
|
53
|
+
if (value instanceof Date && filter instanceof Date) {
|
|
54
|
+
return value.getTime() === filter.getTime();
|
|
55
|
+
}
|
|
56
|
+
const filterRecord = filter;
|
|
57
|
+
const keys = Object.keys(filterRecord);
|
|
58
|
+
if (keys.length === 0) return true;
|
|
59
|
+
let caseInsensitive = false;
|
|
60
|
+
if (filterRecord.mode === "insensitive") {
|
|
61
|
+
caseInsensitive = true;
|
|
62
|
+
}
|
|
63
|
+
for (const op of keys) {
|
|
64
|
+
if (op === "mode") continue;
|
|
65
|
+
let expected = filterRecord[op];
|
|
66
|
+
let actual = value;
|
|
67
|
+
if (["lt", "lte", "gt", "gte", "equals", "not"].includes(op)) {
|
|
68
|
+
if (actual instanceof Date && typeof expected === "string") {
|
|
69
|
+
const d = new Date(expected);
|
|
70
|
+
if (!Number.isNaN(d.getTime())) expected = d;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (caseInsensitive && typeof actual === "string" && typeof expected === "string") {
|
|
74
|
+
if (["equals", "not", "contains", "startsWith", "endsWith"].includes(op)) {
|
|
75
|
+
actual = actual.toLowerCase();
|
|
76
|
+
expected = expected.toLowerCase();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
switch (op) {
|
|
80
|
+
case "equals":
|
|
81
|
+
if (actual instanceof Date && expected instanceof Date) {
|
|
82
|
+
if (actual.getTime() !== expected.getTime()) return false;
|
|
83
|
+
} else if (actual !== expected) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case "not":
|
|
88
|
+
if (typeof expected === "object" && expected !== null && !Array.isArray(expected) && !(expected instanceof Date)) {
|
|
89
|
+
if (checkCondition(value, expected)) return false;
|
|
90
|
+
} else {
|
|
91
|
+
if (actual instanceof Date && expected instanceof Date) {
|
|
92
|
+
if (actual.getTime() === expected.getTime()) return false;
|
|
93
|
+
} else if (actual === expected) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case "in":
|
|
99
|
+
if (!Array.isArray(expected)) return false;
|
|
100
|
+
if (caseInsensitive && typeof actual === "string") {
|
|
101
|
+
const lowerVal = actual.toLowerCase();
|
|
102
|
+
const lowerList = expected.map((e) => typeof e === "string" ? e.toLowerCase() : e);
|
|
103
|
+
if (!lowerList.includes(lowerVal)) return false;
|
|
104
|
+
} else {
|
|
105
|
+
if (actual instanceof Date) {
|
|
106
|
+
const time = actual.getTime();
|
|
107
|
+
if (!expected.some((e) => e instanceof Date && e.getTime() === time || e === actual)) return false;
|
|
108
|
+
} else {
|
|
109
|
+
if (!expected.includes(actual)) return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
case "notIn":
|
|
114
|
+
if (!Array.isArray(expected)) return false;
|
|
115
|
+
if (caseInsensitive && typeof actual === "string") {
|
|
116
|
+
const lowerVal = actual.toLowerCase();
|
|
117
|
+
const lowerList = expected.map((e) => typeof e === "string" ? e.toLowerCase() : e);
|
|
118
|
+
if (lowerList.includes(lowerVal)) return false;
|
|
119
|
+
} else {
|
|
120
|
+
if (actual instanceof Date) {
|
|
121
|
+
const time = actual.getTime();
|
|
122
|
+
if (expected.some((e) => e instanceof Date && e.getTime() === time || e === actual)) return false;
|
|
123
|
+
} else {
|
|
124
|
+
if (expected.includes(actual)) return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case "lt":
|
|
129
|
+
if (typeof actual === "number" && typeof expected === "number") {
|
|
130
|
+
if (!(actual < expected)) return false;
|
|
131
|
+
} else if (actual instanceof Date && expected instanceof Date) {
|
|
132
|
+
if (!(actual < expected)) return false;
|
|
133
|
+
} else if (typeof actual === "string" && typeof expected === "string") {
|
|
134
|
+
if (!(actual < expected)) return false;
|
|
135
|
+
} else {
|
|
136
|
+
if (!(actual < expected)) return false;
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case "lte":
|
|
140
|
+
if (!(actual <= expected)) return false;
|
|
141
|
+
break;
|
|
142
|
+
case "gt":
|
|
143
|
+
if (!(actual > expected)) return false;
|
|
144
|
+
break;
|
|
145
|
+
case "gte":
|
|
146
|
+
if (!(actual >= expected)) return false;
|
|
147
|
+
break;
|
|
148
|
+
case "contains":
|
|
149
|
+
if (typeof actual !== "string" || typeof expected !== "string" || !actual.includes(expected)) return false;
|
|
150
|
+
break;
|
|
151
|
+
case "startsWith":
|
|
152
|
+
if (typeof actual !== "string" || typeof expected !== "string" || !actual.startsWith(expected)) return false;
|
|
153
|
+
break;
|
|
154
|
+
case "endsWith":
|
|
155
|
+
if (typeof actual !== "string" || typeof expected !== "string" || !actual.endsWith(expected)) return false;
|
|
156
|
+
break;
|
|
157
|
+
// Relations
|
|
158
|
+
case "some":
|
|
159
|
+
if (!Array.isArray(value)) return false;
|
|
160
|
+
if (!value.some((v) => checkInternal(v, expected))) return false;
|
|
161
|
+
break;
|
|
162
|
+
case "every":
|
|
163
|
+
if (!Array.isArray(value)) return false;
|
|
164
|
+
if (!value.every((v) => checkInternal(v, expected))) return false;
|
|
165
|
+
break;
|
|
166
|
+
case "none":
|
|
167
|
+
if (!Array.isArray(value)) return false;
|
|
168
|
+
if (value.some((v) => checkInternal(v, expected))) return false;
|
|
169
|
+
break;
|
|
170
|
+
case "is":
|
|
171
|
+
if (expected === null) {
|
|
172
|
+
if (value != null) return false;
|
|
173
|
+
} else {
|
|
174
|
+
if (value == null) return false;
|
|
175
|
+
if (!checkInternal(value, expected)) return false;
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
case "isNot":
|
|
179
|
+
if (expected === null) {
|
|
180
|
+
if (value == null) return false;
|
|
181
|
+
} else {
|
|
182
|
+
if (value == null) break;
|
|
183
|
+
if (checkInternal(value, expected)) return false;
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
default:
|
|
187
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
188
|
+
if (!checkCondition(value[op], expected)) return false;
|
|
189
|
+
} else {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
function checkInternal(item, where) {
|
|
197
|
+
return matchesWhereInternal(item, where);
|
|
198
|
+
}
|
|
199
|
+
function matchesWhereInternal(item, where) {
|
|
200
|
+
if (!where) return true;
|
|
201
|
+
if (!item) return false;
|
|
202
|
+
for (const key of Object.keys(where)) {
|
|
203
|
+
if (where[key] === void 0) continue;
|
|
204
|
+
const filter = where[key];
|
|
205
|
+
if (key === "AND") {
|
|
206
|
+
if (Array.isArray(filter)) {
|
|
207
|
+
if (!filter.every((cond) => matchesWhereInternal(item, cond))) return false;
|
|
208
|
+
} else {
|
|
209
|
+
if (!matchesWhereInternal(item, filter)) return false;
|
|
210
|
+
}
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (key === "OR") {
|
|
214
|
+
if (Array.isArray(filter)) {
|
|
215
|
+
if (!filter.some((cond) => matchesWhereInternal(item, cond))) return false;
|
|
216
|
+
} else {
|
|
217
|
+
if (!matchesWhereInternal(item, filter)) return false;
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (key === "NOT") {
|
|
222
|
+
if (Array.isArray(filter)) {
|
|
223
|
+
if (filter.some((cond) => matchesWhereInternal(item, cond))) return false;
|
|
224
|
+
} else {
|
|
225
|
+
if (matchesWhereInternal(item, filter)) return false;
|
|
226
|
+
}
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const value = item[key];
|
|
230
|
+
if (!checkCondition(value, filter)) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
@@ -3,10 +3,10 @@ export function getModelDef(model) {
|
|
|
3
3
|
return zenstackSchema.models[model];
|
|
4
4
|
}
|
|
5
5
|
export function isIdString(model) {
|
|
6
|
-
const
|
|
7
|
-
if (!
|
|
8
|
-
throw new Error(`
|
|
9
|
-
return
|
|
6
|
+
const modelDef = getModelDef(model);
|
|
7
|
+
if (!modelDef.uniqueFields.id)
|
|
8
|
+
throw new Error(`Model ${model.toString()} does not have an id as a unique field`);
|
|
9
|
+
return modelDef.uniqueFields.id.type === "String";
|
|
10
10
|
}
|
|
11
11
|
export function getModels() {
|
|
12
12
|
return Object.keys(zenstackSchema.models);
|
|
@@ -1,18 +1,50 @@
|
|
|
1
1
|
import type { $Zmodel, $Zid } from '#build/types/nuxt-zenstack';
|
|
2
|
+
type FetchEntry = {
|
|
3
|
+
model: string;
|
|
4
|
+
method: 'GET' | 'PATCH' | 'POST' | 'DELETE';
|
|
5
|
+
ssr: boolean;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
id?: string | number;
|
|
8
|
+
query?: string;
|
|
9
|
+
body?: string;
|
|
10
|
+
};
|
|
2
11
|
export declare function useZenstackStore(): {
|
|
3
12
|
state: Readonly<import("vue").Ref<{
|
|
4
13
|
readonly [x: string]: {
|
|
5
|
-
readonly [x: string]:
|
|
14
|
+
readonly [x: string]: {
|
|
15
|
+
readonly [x: string]: string | number | boolean | readonly string[] | null;
|
|
16
|
+
};
|
|
6
17
|
};
|
|
7
18
|
}, {
|
|
8
19
|
readonly [x: string]: {
|
|
9
|
-
readonly [x: string]:
|
|
20
|
+
readonly [x: string]: {
|
|
21
|
+
readonly [x: string]: string | number | boolean | readonly string[] | null;
|
|
22
|
+
};
|
|
10
23
|
};
|
|
11
24
|
}>>;
|
|
25
|
+
fetchHistory: Readonly<import("vue").Ref<readonly {
|
|
26
|
+
readonly model: string;
|
|
27
|
+
readonly method: "GET" | "PATCH" | "POST" | "DELETE";
|
|
28
|
+
readonly ssr: boolean;
|
|
29
|
+
readonly timestamp: number;
|
|
30
|
+
readonly id?: string | number | undefined;
|
|
31
|
+
readonly query?: string | undefined;
|
|
32
|
+
readonly body?: string | undefined;
|
|
33
|
+
}[], readonly {
|
|
34
|
+
readonly model: string;
|
|
35
|
+
readonly method: "GET" | "PATCH" | "POST" | "DELETE";
|
|
36
|
+
readonly ssr: boolean;
|
|
37
|
+
readonly timestamp: number;
|
|
38
|
+
readonly id?: string | number | undefined;
|
|
39
|
+
readonly query?: string | undefined;
|
|
40
|
+
readonly body?: string | undefined;
|
|
41
|
+
}[]>>;
|
|
12
42
|
setOne: (model: $Zmodel, input: object) => void;
|
|
13
43
|
setMany: (model: $Zmodel, input: object[]) => void;
|
|
14
44
|
getOne: <Zmodel extends $Zmodel>(model: Zmodel, input: $Zid<Zmodel>) => any;
|
|
15
45
|
getMany: (model: $Zmodel) => any;
|
|
16
46
|
deleteOne: <Model extends $Zmodel>(model: Model, id: $Zid<Model>) => void;
|
|
17
47
|
deleteMany: (model: $Zmodel) => void;
|
|
48
|
+
addToFetchHistory: (entry: Omit<FetchEntry, "ssr" | "timestamp">) => void;
|
|
18
49
|
};
|
|
50
|
+
export {};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { generateNormalizrSchema, getNormalizrSchema } from "./normalization.js";
|
|
1
|
+
import { generateNormalizrSchema, getNormalizrSchema, mergeNormalizedData } from "./normalization.js";
|
|
2
2
|
import { normalize, denormalize } from "normalizr";
|
|
3
|
-
import { defu } from "defu";
|
|
4
3
|
import { readonly, useState } from "#imports";
|
|
5
4
|
generateNormalizrSchema();
|
|
6
5
|
export function useZenstackStore() {
|
|
7
|
-
const state = useState("zenstack-
|
|
6
|
+
const state = useState("zenstack-state", () => ({}));
|
|
7
|
+
const fetchHistory = useState("zenstack-fetch-history", () => []);
|
|
8
8
|
function setOne(model, input) {
|
|
9
9
|
const schema = getNormalizrSchema(model);
|
|
10
10
|
const res = normalize(input, schema);
|
|
11
|
-
state.value =
|
|
11
|
+
state.value = mergeNormalizedData(res.entities, state.value);
|
|
12
12
|
}
|
|
13
13
|
function setMany(model, input) {
|
|
14
14
|
const schema = [getNormalizrSchema(model)];
|
|
15
15
|
const res = normalize(input, schema);
|
|
16
|
-
state.value =
|
|
16
|
+
state.value = mergeNormalizedData(res.entities, state.value);
|
|
17
17
|
}
|
|
18
18
|
function getOne(model, input) {
|
|
19
19
|
const schema = getNormalizrSchema(model);
|
|
@@ -45,5 +45,26 @@ export function useZenstackStore() {
|
|
|
45
45
|
}
|
|
46
46
|
state.value = newState;
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
function addToFetchHistory(entry) {
|
|
49
|
+
fetchHistory.value.push({
|
|
50
|
+
method: entry.method,
|
|
51
|
+
model: entry.model,
|
|
52
|
+
body: entry.body,
|
|
53
|
+
id: entry.id,
|
|
54
|
+
query: entry.query,
|
|
55
|
+
ssr: typeof window === "undefined",
|
|
56
|
+
timestamp: (/* @__PURE__ */ new Date()).getTime()
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
state: readonly(state),
|
|
61
|
+
fetchHistory: readonly(fetchHistory),
|
|
62
|
+
setOne,
|
|
63
|
+
setMany,
|
|
64
|
+
getOne,
|
|
65
|
+
getMany,
|
|
66
|
+
deleteOne,
|
|
67
|
+
deleteMany,
|
|
68
|
+
addToFetchHistory
|
|
69
|
+
};
|
|
49
70
|
}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { schema as normalizrSchema } from 'normalizr';
|
|
2
2
|
import type { $Zmodel } from '#build/types/nuxt-zenstack';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
type NormalizedDataField = number | string | boolean | null | string[];
|
|
4
|
+
/**
|
|
5
|
+
* Normalized data structure
|
|
6
|
+
* {
|
|
7
|
+
* model: {
|
|
8
|
+
* id: {
|
|
9
|
+
* field: NormalizedDataField
|
|
10
|
+
* }
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
*/
|
|
14
|
+
export type NormalizedData = Record<string, Record<string, Record<string, NormalizedDataField>>>;
|
|
15
|
+
export declare function getNormalizrSchema(model: $Zmodel): normalizrSchema.Entity<any>;
|
|
16
|
+
export declare function generateNormalizrSchema(): void;
|
|
17
|
+
export declare function mergeNormalizedData(newData: NormalizedData, currentData: NormalizedData): NormalizedData;
|
|
18
|
+
export {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { schema as normalizrSchema } from "normalizr";
|
|
2
2
|
import { getModelDef, getModels, isValidModel } from "./helpers.js";
|
|
3
|
+
import { defu } from "defu";
|
|
3
4
|
const NORMALIZR_SCHEMA = /* @__PURE__ */ new Map();
|
|
4
|
-
function getNormalizrSchema(model) {
|
|
5
|
+
export function getNormalizrSchema(model) {
|
|
5
6
|
const schema = NORMALIZR_SCHEMA.get(model);
|
|
6
7
|
if (!schema)
|
|
7
8
|
throw new Error(`Model ${model.toString()} not defined`);
|
|
8
9
|
return schema;
|
|
9
10
|
}
|
|
10
|
-
function generateNormalizrSchema() {
|
|
11
|
+
export function generateNormalizrSchema() {
|
|
11
12
|
const models = getModels();
|
|
12
13
|
for (const model of models) {
|
|
13
14
|
NORMALIZR_SCHEMA.set(model, new normalizrSchema.Entity(model.toString()));
|
|
@@ -28,4 +29,16 @@ function generateNormalizrSchema() {
|
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
|
-
export
|
|
32
|
+
export function mergeNormalizedData(newData, currentData) {
|
|
33
|
+
const merged = defu(newData, currentData);
|
|
34
|
+
for (const model in merged) {
|
|
35
|
+
for (const id in merged[model]) {
|
|
36
|
+
for (const field in merged[model][id]) {
|
|
37
|
+
if (Array.isArray(merged[model][id][field])) {
|
|
38
|
+
merged[model][id][field] = Array.from(new Set(merged[model][id][field]));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return merged;
|
|
44
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { $Zmodel, $Zitem, $ZupdateData, $Zid } from '#build/types/nuxt-zenstack';
|
|
1
|
+
import type { $Zmodel, $Zitem, $ZupdateData, $Zid, $Zerror } from '#build/types/nuxt-zenstack';
|
|
2
2
|
import type { Status } from '../common.js';
|
|
3
3
|
import type { Ref } from '#imports';
|
|
4
4
|
export declare function useZenstackUpdate<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
5
|
data: Ref<Zitem | null>;
|
|
6
|
-
error: Ref
|
|
6
|
+
error: Ref<$Zerror | null>;
|
|
7
7
|
status: Ref<Status>;
|
|
8
8
|
mutate: (id: $Zid<Zmodel>, input: $ZupdateData<Zmodel>) => Promise<void>;
|
|
9
9
|
reset: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ref } from "#imports";
|
|
2
2
|
import { joinURL } from "ufo";
|
|
3
3
|
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
-
import { getConfig } from "../common.js";
|
|
4
|
+
import { getConfig, getFetch } from "../common.js";
|
|
5
5
|
export function useZenstackUpdate(model) {
|
|
6
6
|
const data = ref(null);
|
|
7
7
|
const error = ref(null);
|
|
@@ -14,17 +14,19 @@ export function useZenstackUpdate(model) {
|
|
|
14
14
|
status.value = "idle";
|
|
15
15
|
}
|
|
16
16
|
async function mutate(id, input) {
|
|
17
|
+
const _fetch = getFetch();
|
|
17
18
|
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
19
|
+
const body = { data: input };
|
|
20
|
+
const method = "PATCH";
|
|
21
|
+
store.addToFetchHistory({
|
|
22
|
+
model: model.toString(),
|
|
23
|
+
method,
|
|
24
|
+
body: JSON.stringify(body)
|
|
25
|
+
});
|
|
18
26
|
reset();
|
|
19
27
|
status.value = "pending";
|
|
20
28
|
try {
|
|
21
|
-
const res = await
|
|
22
|
-
method: "PATCH",
|
|
23
|
-
body: {
|
|
24
|
-
data: input
|
|
25
|
-
// TODO: maybe include relations
|
|
26
|
-
}
|
|
27
|
-
});
|
|
29
|
+
const res = await _fetch(url, { method, body });
|
|
28
30
|
if (res.data)
|
|
29
31
|
store.setOne(model, res.data);
|
|
30
32
|
data.value = res.data;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { defineEventHandler } from "h3";
|
|
2
2
|
import { parseModel, parseId } from "../../../utils/parsers.js";
|
|
3
3
|
import { getModelOperations } from "../../../utils/index.js";
|
|
4
|
+
import { createError } from "../../../utils/error.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
6
|
const model = parseModel(event);
|
|
6
7
|
const id = parseId(event, model);
|
|
7
|
-
const operations = getModelOperations(model);
|
|
8
|
+
const operations = getModelOperations(event, model);
|
|
8
9
|
const data = await operations.delete({
|
|
9
10
|
where: {
|
|
10
11
|
id
|
|
11
12
|
}
|
|
13
|
+
}).catch((err) => {
|
|
14
|
+
throw createError(err);
|
|
12
15
|
});
|
|
13
16
|
return { data };
|
|
14
17
|
});
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { parseModel, parseId, parseReadArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
3
|
import { getModelOperations } from "../../../utils/index.js";
|
|
4
|
+
import { createError } from "../../../utils/error.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
6
|
const model = parseModel(event);
|
|
6
7
|
const id = parseId(event, model);
|
|
7
8
|
const readArgs = parseReadArgs(event, model);
|
|
8
|
-
const operations = getModelOperations(model);
|
|
9
|
+
const operations = getModelOperations(event, model);
|
|
9
10
|
const data = await operations.findUnique({
|
|
10
11
|
include: readArgs.include,
|
|
11
12
|
where: {
|
|
12
13
|
id
|
|
13
14
|
}
|
|
15
|
+
}).catch((err) => {
|
|
16
|
+
throw createError(err);
|
|
14
17
|
});
|
|
15
18
|
return { data };
|
|
16
19
|
});
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import { parseModel, parseId,
|
|
1
|
+
import { parseModel, parseId, parseUpdateArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "../../../utils/index.js";
|
|
3
|
+
import { getModelOperations, includeAll } from "../../../utils/index.js";
|
|
4
|
+
import { createError } from "../../../utils/error.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
6
|
const model = parseModel(event);
|
|
6
7
|
const id = parseId(event, model);
|
|
7
|
-
const
|
|
8
|
-
const operations = getModelOperations(model);
|
|
8
|
+
const updateArgs = await parseUpdateArgs(event, model);
|
|
9
|
+
const operations = getModelOperations(event, model);
|
|
10
|
+
const include = includeAll(model);
|
|
9
11
|
const data = await operations.update({
|
|
10
|
-
data:
|
|
12
|
+
data: updateArgs.data,
|
|
13
|
+
include,
|
|
11
14
|
where: {
|
|
12
15
|
id
|
|
13
16
|
}
|
|
17
|
+
}).catch((err) => {
|
|
18
|
+
throw createError(err);
|
|
14
19
|
});
|
|
15
20
|
return { data };
|
|
16
21
|
});
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { parseModel, parseReadArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
3
|
import { getModelOperations } from "../../../utils/index.js";
|
|
4
|
+
import { createError } from "../../../utils/error.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
6
|
const model = parseModel(event);
|
|
6
7
|
const readArgs = parseReadArgs(event, model);
|
|
7
|
-
const operations = getModelOperations(model);
|
|
8
|
+
const operations = getModelOperations(event, model);
|
|
8
9
|
const data = await operations.findMany({
|
|
9
10
|
orderBy: readArgs.orderBy,
|
|
10
11
|
include: readArgs.include,
|
|
11
12
|
skip: readArgs.skip,
|
|
12
13
|
take: readArgs.take,
|
|
13
14
|
where: readArgs.where
|
|
15
|
+
}).catch((err) => {
|
|
16
|
+
throw createError(err);
|
|
14
17
|
});
|
|
15
18
|
return { data };
|
|
16
19
|
});
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { parseModel,
|
|
1
|
+
import { parseModel, parseCreateArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "../../../utils/index.js";
|
|
3
|
+
import { getModelOperations, includeAll } from "../../../utils/index.js";
|
|
4
|
+
import { createError } from "../../../utils/error.js";
|
|
4
5
|
export default defineEventHandler(async (event) => {
|
|
5
6
|
const model = parseModel(event);
|
|
6
|
-
const
|
|
7
|
-
const operations = getModelOperations(model);
|
|
7
|
+
const createArgs = await parseCreateArgs(event, model);
|
|
8
|
+
const operations = getModelOperations(event, model);
|
|
9
|
+
const include = includeAll(model);
|
|
8
10
|
const data = await operations.create({
|
|
9
|
-
data:
|
|
11
|
+
data: createArgs.data,
|
|
12
|
+
include
|
|
13
|
+
}).catch((err) => {
|
|
14
|
+
throw createError(err);
|
|
10
15
|
});
|
|
11
16
|
return { data };
|
|
12
17
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { $ZormError } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import { ORMErrorReason } from '@zenstackhq/orm';
|
|
3
|
+
export declare function createError(ormError: $ZormError): import("h3").H3Error<{
|
|
4
|
+
ormErrorReason: ORMErrorReason;
|
|
5
|
+
dbErrorCode?: unknown;
|
|
6
|
+
dbErrorMessage?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
rejectedByPolicyReason?: import("@zenstackhq/orm").RejectedByPolicyReason;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ORMErrorReason } from "@zenstackhq/orm";
|
|
2
|
+
import { createError as createH3Error } from "h3";
|
|
3
|
+
export function createError(ormError) {
|
|
4
|
+
let statusCode = 500;
|
|
5
|
+
switch (ormError.reason) {
|
|
6
|
+
case ORMErrorReason.CONFIG_ERROR:
|
|
7
|
+
statusCode = 500;
|
|
8
|
+
break;
|
|
9
|
+
case ORMErrorReason.DB_QUERY_ERROR:
|
|
10
|
+
statusCode = 409;
|
|
11
|
+
break;
|
|
12
|
+
case ORMErrorReason.INTERNAL_ERROR:
|
|
13
|
+
statusCode = 500;
|
|
14
|
+
break;
|
|
15
|
+
case ORMErrorReason.NOT_FOUND:
|
|
16
|
+
statusCode = 404;
|
|
17
|
+
break;
|
|
18
|
+
case ORMErrorReason.INVALID_INPUT:
|
|
19
|
+
statusCode = 400;
|
|
20
|
+
break;
|
|
21
|
+
case ORMErrorReason.NOT_SUPPORTED:
|
|
22
|
+
statusCode = 501;
|
|
23
|
+
break;
|
|
24
|
+
case ORMErrorReason.REJECTED_BY_POLICY:
|
|
25
|
+
statusCode = 401;
|
|
26
|
+
break;
|
|
27
|
+
default:
|
|
28
|
+
statusCode = 500;
|
|
29
|
+
}
|
|
30
|
+
const error = {
|
|
31
|
+
name: "Zenstack Error",
|
|
32
|
+
cause: ormError.cause,
|
|
33
|
+
message: ormError.message,
|
|
34
|
+
statusCode,
|
|
35
|
+
statusMessage: ormError.reason,
|
|
36
|
+
stack: ormError.stack,
|
|
37
|
+
fatal: false,
|
|
38
|
+
unhandled: false,
|
|
39
|
+
toJSON: () => error,
|
|
40
|
+
data: {
|
|
41
|
+
ormErrorReason: ormError.reason,
|
|
42
|
+
dbErrorCode: ormError.dbErrorCode,
|
|
43
|
+
dbErrorMessage: ormError.dbErrorMessage,
|
|
44
|
+
model: ormError.model,
|
|
45
|
+
rejectedByPolicyReason: ormError.rejectedByPolicyReason
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return createH3Error(error);
|
|
49
|
+
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
declare
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function getClient(): ClientContract<SchemaType>;
|
|
6
|
-
export declare function getModelOperations<Zmodel extends $Zmodel>(model: Zmodel): $Zoperations<Zmodel>;
|
|
7
|
-
export declare function getModelDef(model: $Zmodel): any;
|
|
1
|
+
import type { $Zmodel, $Zoperations, $Zdef } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { H3Event } from 'h3';
|
|
3
|
+
export declare function getModelOperations<Zmodel extends $Zmodel>(event: H3Event, model: Zmodel): $Zoperations<Zmodel>;
|
|
4
|
+
export declare function getModelDef(model: $Zmodel): $Zdef;
|
|
8
5
|
export declare function isIdString(model: $Zmodel): boolean;
|
|
9
6
|
export declare function getModels(): $Zmodel[];
|
|
10
7
|
export declare function isValidModel(model: $Zmodel): boolean;
|
|
11
|
-
export
|
|
8
|
+
export declare function includeAll<Zmodel extends $Zmodel>(model: Zmodel): boolean | import("@zenstackhq/orm").SelectIncludeOmit<SchemaType, any, boolean, true>;
|