@svadmin/sanity 0.9.20 → 0.10.6
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/package.json +3 -3
- package/src/data-provider.ts +64 -41
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/sanity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.6",
|
|
4
4
|
"description": "Sanity DataProvider for svadmin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@svadmin/core": "^0.
|
|
23
|
+
"@svadmin/core": "^0.52.0"
|
|
24
24
|
},
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/vibeunion/svadmin.git",
|
|
28
|
+
"url": "git+https://github.com/vibeunion/svadmin.git",
|
|
29
29
|
"directory": "packages/sanity"
|
|
30
30
|
},
|
|
31
31
|
"peerDependenciesMeta": {
|
package/src/data-provider.ts
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
|
+
import { definedOptions } from '@svadmin/core/options';
|
|
2
|
+
import { decodeBaseRecord, decodeOneResult, decodeManyResult, withValidatedResponses, type DataTransport } from '@svadmin/core/schema';
|
|
1
3
|
import type {
|
|
2
|
-
DataProvider,
|
|
3
|
-
CreateParams, CreateResult, UpdateParams, UpdateResult, DeleteParams, DeleteResult,
|
|
4
|
-
GetManyParams, GetManyResult, CustomParams, CustomResult, CrudOperator, FieldFilter,
|
|
4
|
+
DataProvider, CrudOperator, FieldFilter,
|
|
5
5
|
Filter, Sort, BaseRecord
|
|
6
6
|
} from '@svadmin/core';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
function decodeDocument(value: unknown): BaseRecord {
|
|
9
|
+
const document = decodeBaseRecord(value);
|
|
10
|
+
const id = document['_id'];
|
|
11
|
+
if (typeof id !== 'string' || id.length === 0 || typeof document['_type'] !== 'string') {
|
|
12
|
+
throw new TypeError('Invalid Sanity document identity');
|
|
13
|
+
}
|
|
14
|
+
return { ...document, id };
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
function inputRecord(value: unknown): Record<string, unknown> {
|
|
18
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
19
|
+
throw new TypeError('Sanity variables must be an object');
|
|
20
|
+
}
|
|
21
|
+
return decodeBaseRecord(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function mutationReceipt(value: unknown, expectedId?: string | number): { id: string } {
|
|
25
|
+
return decodeOneResult({ data: value }, raw => {
|
|
26
|
+
const result = decodeBaseRecord(raw);
|
|
27
|
+
const results = result['results'];
|
|
28
|
+
if (!Array.isArray(results) || results.length !== 1) throw new TypeError('Missing Sanity mutation receipt');
|
|
29
|
+
const receipt = decodeBaseRecord(results[0]);
|
|
30
|
+
const id = receipt['id'];
|
|
31
|
+
if (typeof id !== 'string' || id.length === 0 || (expectedId !== undefined && id !== String(expectedId))) {
|
|
32
|
+
throw new TypeError('Invalid Sanity mutation identity');
|
|
33
|
+
}
|
|
34
|
+
return { id };
|
|
35
|
+
}, true).data;
|
|
16
36
|
}
|
|
17
37
|
|
|
18
38
|
const DEFAULT_JSON_HEADERS: Record<string, string> = { 'Content-Type': 'application/json' };
|
|
@@ -201,28 +221,28 @@ function buildCustomUrl(
|
|
|
201
221
|
return parsed.toString();
|
|
202
222
|
}
|
|
203
223
|
|
|
204
|
-
async function parseResponse
|
|
224
|
+
async function parseResponse(response: Response): Promise<unknown> {
|
|
205
225
|
if (response.status === 204 || response.status === 205) {
|
|
206
|
-
return undefined
|
|
226
|
+
return undefined;
|
|
207
227
|
}
|
|
208
228
|
|
|
209
229
|
const contentLength = response.headers?.get('content-length');
|
|
210
230
|
if (contentLength?.trim() === '0') {
|
|
211
|
-
return undefined
|
|
231
|
+
return undefined;
|
|
212
232
|
}
|
|
213
233
|
|
|
214
234
|
const body = await response.text();
|
|
215
235
|
if (!body || body.trim() === '') {
|
|
216
|
-
return undefined
|
|
236
|
+
return undefined;
|
|
217
237
|
}
|
|
218
238
|
|
|
219
|
-
return JSON.parse(body)
|
|
239
|
+
return JSON.parse(body);
|
|
220
240
|
}
|
|
221
241
|
|
|
222
242
|
export function createSanityDataProvider(projectId: string, dataset: string, token?: string, apiVersion = '2023-05-03'): DataProvider {
|
|
223
243
|
const apiUrl = `https://${projectId}.api.sanity.io/v${apiVersion}`;
|
|
224
244
|
const providerHeaders: Record<string, string> = { ...DEFAULT_JSON_HEADERS };
|
|
225
|
-
if (token) providerHeaders
|
|
245
|
+
if (token) providerHeaders['Authorization'] = `Bearer ${token}`;
|
|
226
246
|
|
|
227
247
|
async function query(groq: string, params: Record<string, unknown> = {}): Promise<unknown> {
|
|
228
248
|
const url = new URL(`${apiUrl}/data/query/${dataset}`);
|
|
@@ -230,22 +250,22 @@ export function createSanityDataProvider(projectId: string, dataset: string, tok
|
|
|
230
250
|
for (const [k, v] of Object.entries(params)) url.searchParams.set(`$${k}`, JSON.stringify(v));
|
|
231
251
|
const res = await fetch(url.toString(), { headers: providerHeaders });
|
|
232
252
|
if (!res.ok) throw new Error(`Sanity error: ${res.status}`);
|
|
233
|
-
const data = await res
|
|
234
|
-
return data
|
|
253
|
+
const data = decodeBaseRecord(await parseResponse(res));
|
|
254
|
+
return data['result'];
|
|
235
255
|
}
|
|
236
256
|
|
|
237
|
-
async function mutate(mutations: Record<string, unknown>[]): Promise<
|
|
257
|
+
async function mutate(mutations: Record<string, unknown>[]): Promise<unknown> {
|
|
238
258
|
const res = await fetch(`${apiUrl}/data/mutate/${dataset}`, {
|
|
239
259
|
method: 'POST', headers: providerHeaders, body: JSON.stringify({ mutations }),
|
|
240
260
|
});
|
|
241
261
|
if (!res.ok) throw new Error(`Sanity mutation error: ${res.status}`);
|
|
242
|
-
return res
|
|
262
|
+
return parseResponse(res);
|
|
243
263
|
}
|
|
244
264
|
|
|
245
|
-
|
|
265
|
+
const transport: DataTransport = {
|
|
246
266
|
getApiUrl: () => apiUrl,
|
|
247
267
|
|
|
248
|
-
async getList
|
|
268
|
+
async getList({ resource, pagination, sorters, filters }) {
|
|
249
269
|
const { current = 1, pageSize = 10 } = pagination ?? {};
|
|
250
270
|
const start = (current - 1) * pageSize;
|
|
251
271
|
const end = start + pageSize;
|
|
@@ -259,50 +279,53 @@ export function createSanityDataProvider(projectId: string, dataset: string, tok
|
|
|
259
279
|
query(`*[${where}]${orderStr}[${start}...${end}]`, params),
|
|
260
280
|
query(`count(*[${where}])`, params),
|
|
261
281
|
]);
|
|
262
|
-
return { data: (
|
|
282
|
+
return { data: decodeManyResult({ data }, decodeDocument).data, total };
|
|
263
283
|
},
|
|
264
284
|
|
|
265
|
-
async getOne
|
|
285
|
+
async getOne({ resource, id }) {
|
|
266
286
|
const raw = await query('*[_type == $resource && _id == $id][0]', { resource, id });
|
|
267
|
-
|
|
268
|
-
return { data: { ...data, id: data._id } as unknown as unknown as T };
|
|
287
|
+
return decodeOneResult({ data: raw }, decodeDocument);
|
|
269
288
|
},
|
|
270
289
|
|
|
271
|
-
async create
|
|
272
|
-
const
|
|
290
|
+
async create({ resource, variables }) {
|
|
291
|
+
const input = inputRecord(variables);
|
|
292
|
+
const doc = { ...input, _type: resource };
|
|
273
293
|
const result = await mutate([{ create: doc }]);
|
|
274
|
-
const id = result
|
|
275
|
-
return { data: { ...
|
|
294
|
+
const { id } = mutationReceipt(result);
|
|
295
|
+
return { data: { ...input, id, _id: id } };
|
|
276
296
|
},
|
|
277
297
|
|
|
278
|
-
async update
|
|
279
|
-
|
|
280
|
-
|
|
298
|
+
async update({ id, variables }) {
|
|
299
|
+
const input = inputRecord(variables);
|
|
300
|
+
const result = await mutate([{ patch: { id, set: input } }]);
|
|
301
|
+
const receipt = mutationReceipt(result, id);
|
|
302
|
+
return { data: { ...input, id: receipt.id, _id: receipt.id } };
|
|
281
303
|
},
|
|
282
304
|
|
|
283
|
-
async deleteOne
|
|
284
|
-
await mutate([{ delete: { id } }]);
|
|
285
|
-
return { data:
|
|
305
|
+
async deleteOne({ id }) {
|
|
306
|
+
const result = await mutate([{ delete: { id } }]);
|
|
307
|
+
return { data: mutationReceipt(result, id) };
|
|
286
308
|
},
|
|
287
309
|
|
|
288
|
-
async getMany
|
|
310
|
+
async getMany({ resource, ids }) {
|
|
289
311
|
const data = await query('*[_type == $resource && _id in $ids]', { resource, ids });
|
|
290
|
-
return { data
|
|
312
|
+
return decodeManyResult({ data }, decodeDocument);
|
|
291
313
|
},
|
|
292
314
|
|
|
293
|
-
async custom
|
|
315
|
+
async custom({ url, method, payload, query: customQuery, headers, sorters, filters }) {
|
|
294
316
|
const requestUrl = buildCustomUrl(url, apiUrl, customQuery, sorters, filters);
|
|
295
317
|
const requestHeaders = mergeHeaders(
|
|
296
318
|
isSameOrigin(apiUrl, requestUrl) ? providerHeaders : DEFAULT_JSON_HEADERS,
|
|
297
319
|
headers,
|
|
298
320
|
);
|
|
299
|
-
const res = await fetch(requestUrl, {
|
|
321
|
+
const res = await fetch(requestUrl, definedOptions({
|
|
300
322
|
method: method.toUpperCase(),
|
|
301
323
|
headers: requestHeaders,
|
|
302
324
|
body: payload === undefined ? undefined : JSON.stringify(payload),
|
|
303
|
-
});
|
|
325
|
+
}));
|
|
304
326
|
if (!res.ok) throw new Error(`Custom request failed: ${res.status}`);
|
|
305
|
-
return { data: await parseResponse
|
|
327
|
+
return { data: await parseResponse(res) };
|
|
306
328
|
},
|
|
307
329
|
};
|
|
330
|
+
return withValidatedResponses(transport);
|
|
308
331
|
}
|