@svadmin/simple-rest 0.9.3 → 0.9.5
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 +15 -2
- package/src/auth-provider.ts +9 -4
- package/src/data-provider.ts +19 -135
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/simple-rest",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "Simple REST adapters — fetch-based DataProvider and JWT/Cookie AuthProvider",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"@svadmin/core": "^0.
|
|
19
|
+
"@svadmin/core": "^0.23.3",
|
|
20
|
+
"@refinedev/simple-rest": "^5.0.0",
|
|
21
|
+
"@svadmin/refine-adapter": "^0.9.3"
|
|
20
22
|
},
|
|
21
23
|
"license": "MIT",
|
|
22
24
|
"author": "zuohuadong",
|
|
@@ -28,5 +30,16 @@
|
|
|
28
30
|
"homepage": "https://github.com/zuohuadong/svadmin#readme",
|
|
29
31
|
"bugs": {
|
|
30
32
|
"url": "https://github.com/zuohuadong/svadmin/issues"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@svadmin/core": {
|
|
36
|
+
"optional": true
|
|
37
|
+
},
|
|
38
|
+
"@refinedev/simple-rest": {
|
|
39
|
+
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"@svadmin/refine-adapter": {
|
|
42
|
+
"optional": true
|
|
43
|
+
}
|
|
31
44
|
}
|
|
32
45
|
}
|
package/src/auth-provider.ts
CHANGED
|
@@ -14,7 +14,7 @@ export function createSimpleRestAuthProvider(opts: SimpleRestAuthOptions): AuthP
|
|
|
14
14
|
const { tokenKey = 'auth_token' } = opts;
|
|
15
15
|
|
|
16
16
|
function getAuthHeader(): Record<string, string> {
|
|
17
|
-
if (!tokenKey) return {};
|
|
17
|
+
if (!tokenKey || typeof window === 'undefined') return {};
|
|
18
18
|
const token = localStorage.getItem(tokenKey);
|
|
19
19
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
20
20
|
}
|
|
@@ -33,7 +33,7 @@ export function createSimpleRestAuthProvider(opts: SimpleRestAuthOptions): AuthP
|
|
|
33
33
|
return { success: false, error: { message: error.message ?? 'Login failed' } };
|
|
34
34
|
}
|
|
35
35
|
const data = await response.json();
|
|
36
|
-
if (tokenKey && data.token) {
|
|
36
|
+
if (tokenKey && data.token && typeof window !== 'undefined') {
|
|
37
37
|
localStorage.setItem(tokenKey, data.token);
|
|
38
38
|
}
|
|
39
39
|
return { success: true, redirectTo: '/' };
|
|
@@ -50,12 +50,12 @@ export function createSimpleRestAuthProvider(opts: SimpleRestAuthOptions): AuthP
|
|
|
50
50
|
credentials: 'include',
|
|
51
51
|
}).catch((e) => console.warn('[auth] logout request failed:', e));
|
|
52
52
|
}
|
|
53
|
-
if (tokenKey) localStorage.removeItem(tokenKey);
|
|
53
|
+
if (tokenKey && typeof window !== 'undefined') localStorage.removeItem(tokenKey);
|
|
54
54
|
return { success: true, redirectTo: '/login' };
|
|
55
55
|
},
|
|
56
56
|
|
|
57
57
|
async check(): Promise<CheckResult> {
|
|
58
|
-
if (tokenKey) {
|
|
58
|
+
if (tokenKey && typeof window !== 'undefined') {
|
|
59
59
|
const token = localStorage.getItem(tokenKey);
|
|
60
60
|
if (!token) return { authenticated: false, redirectTo: '/login', logout: true };
|
|
61
61
|
}
|
|
@@ -71,6 +71,11 @@ export function createSimpleRestAuthProvider(opts: SimpleRestAuthOptions): AuthP
|
|
|
71
71
|
return { authenticated: false, redirectTo: '/login', logout: true };
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
if (!tokenKey) {
|
|
75
|
+
console.warn('[svadmin] Cookie-based auth without identityUrl: cannot verify session. Provide identityUrl for secure auth checking.');
|
|
76
|
+
return { authenticated: false, redirectTo: '/login', logout: true };
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
return { authenticated: true };
|
|
75
80
|
},
|
|
76
81
|
|
package/src/data-provider.ts
CHANGED
|
@@ -1,137 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const extra = typeof opts.headers === 'function' ? opts.headers() : (opts.headers ?? {});
|
|
20
|
-
return { ...base, ...extra };
|
|
1
|
+
import type { DataProvider } from '@svadmin/core';
|
|
2
|
+
import { createRefineAdapter } from '@svadmin/refine-adapter';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a simple-rest data provider using the official @refinedev/simple-rest package.
|
|
7
|
+
* Requires `@refinedev/simple-rest` to be installed.
|
|
8
|
+
*
|
|
9
|
+
* @param args Arguments required by @refinedev/simple-rest
|
|
10
|
+
* @returns A fully compatible svadmin DataProvider
|
|
11
|
+
*/
|
|
12
|
+
export async function createSimpleRestDataProvider(...args: any[]): Promise<DataProvider> {
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
const pkg = await import('@refinedev/simple-rest');
|
|
15
|
+
const init = (pkg as any).default || (pkg as any).dataProvider || (pkg as any).DataProvider;
|
|
16
|
+
if (typeof init !== 'function') throw new Error('[svadmin] Failed to resolve @refinedev/simple-rest data provider. Ensure the package is installed correctly.');
|
|
17
|
+
const refineProvider = init(...args);
|
|
18
|
+
return createRefineAdapter(refineProvider);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
export
|
|
24
|
-
const { apiUrl } = opts;
|
|
25
|
-
|
|
26
|
-
async function request<T>(url: string, init?: RequestInit): Promise<T> {
|
|
27
|
-
const response = await fetch(url, { ...init, headers: { ...getHeaders(opts), ...init?.headers } });
|
|
28
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
29
|
-
return response.json();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
getApiUrl: () => apiUrl,
|
|
34
|
-
|
|
35
|
-
async getList<T extends BaseRecord = BaseRecord>({ resource, pagination, sorters, filters }: GetListParams): Promise<GetListResult<T>> {
|
|
36
|
-
const params = new URLSearchParams();
|
|
37
|
-
const { current = 1, pageSize = 10 } = pagination ?? {};
|
|
38
|
-
params.set('_page', String(current));
|
|
39
|
-
params.set('_limit', String(pageSize));
|
|
40
|
-
|
|
41
|
-
if (sorters?.length) {
|
|
42
|
-
params.set('_sort', sorters.map(s => s.field).join(','));
|
|
43
|
-
params.set('_order', sorters.map(s => s.order).join(','));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (filters?.length) {
|
|
47
|
-
for (const f of filters) {
|
|
48
|
-
if (f.operator === 'eq') params.set(f.field, String(f.value));
|
|
49
|
-
else if (f.operator === 'contains') params.set(`${f.field}_like`, String(f.value));
|
|
50
|
-
else params.set(`${f.field}_${f.operator}`, String(f.value));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const url = `${apiUrl}/${resource}?${params.toString()}`;
|
|
55
|
-
const response = await fetch(url, { headers: getHeaders(opts) });
|
|
56
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
57
|
-
|
|
58
|
-
const data = await response.json() as unknown as unknown as T[];
|
|
59
|
-
const total = parseInt(response.headers.get('X-Total-Count') ?? String(data.length), 10);
|
|
60
|
-
return { data, total };
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
async getOne<T extends BaseRecord = BaseRecord>({ resource, id }: GetOneParams): Promise<GetOneResult<T>> {
|
|
64
|
-
const data = await request<unknown>(`${apiUrl}/${resource}/${id}`);
|
|
65
|
-
return { data: data as unknown as unknown as T };
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
async create<T extends BaseRecord = BaseRecord>({ resource, variables }: CreateParams): Promise<CreateResult<T>> {
|
|
69
|
-
const data = await request<unknown>(`${apiUrl}/${resource}`, {
|
|
70
|
-
method: 'POST',
|
|
71
|
-
body: JSON.stringify(variables),
|
|
72
|
-
});
|
|
73
|
-
return { data: data as unknown as unknown as T };
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
async update<T extends BaseRecord = BaseRecord>({ resource, id, variables }: UpdateParams): Promise<UpdateResult<T>> {
|
|
77
|
-
const data = await request<unknown>(`${apiUrl}/${resource}/${id}`, {
|
|
78
|
-
method: 'PATCH',
|
|
79
|
-
body: JSON.stringify(variables),
|
|
80
|
-
});
|
|
81
|
-
return { data: data as unknown as unknown as T };
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
async deleteOne<T extends BaseRecord = BaseRecord>({ resource, id }: DeleteParams): Promise<DeleteResult<T>> {
|
|
85
|
-
const data = await request<unknown>(`${apiUrl}/${resource}/${id}`, { method: 'DELETE' });
|
|
86
|
-
return { data: data as unknown as unknown as T };
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
async getMany<T extends BaseRecord = BaseRecord>({ resource, ids }: GetManyParams): Promise<GetManyResult<T>> {
|
|
90
|
-
const params = ids.map(id => `id=${id}`).join('&');
|
|
91
|
-
const data = await request<unknown[]>(`${apiUrl}/${resource}?${params}`);
|
|
92
|
-
return { data: data as unknown as unknown as T[] };
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
async createMany<T extends BaseRecord = BaseRecord>({ resource, variables }: CreateManyParams): Promise<CreateManyResult<T>> {
|
|
96
|
-
const results: T[] = [];
|
|
97
|
-
for (const vars of variables) {
|
|
98
|
-
const data = await request<unknown>(`${apiUrl}/${resource}`, {
|
|
99
|
-
method: 'POST',
|
|
100
|
-
body: JSON.stringify(vars),
|
|
101
|
-
});
|
|
102
|
-
results.push(data as unknown as T);
|
|
103
|
-
}
|
|
104
|
-
return { data: results };
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
async updateMany<T extends BaseRecord = BaseRecord>({ resource, ids, variables }: UpdateManyParams): Promise<UpdateManyResult<T>> {
|
|
108
|
-
const results: T[] = [];
|
|
109
|
-
for (const id of ids) {
|
|
110
|
-
const data = await request<unknown>(`${apiUrl}/${resource}/${id}`, {
|
|
111
|
-
method: 'PATCH',
|
|
112
|
-
body: JSON.stringify(variables),
|
|
113
|
-
});
|
|
114
|
-
results.push(data as unknown as T);
|
|
115
|
-
}
|
|
116
|
-
return { data: results };
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
async deleteMany<T extends BaseRecord = BaseRecord>({ resource, ids }: DeleteManyParams): Promise<DeleteManyResult<T>> {
|
|
120
|
-
const results: T[] = [];
|
|
121
|
-
for (const id of ids) {
|
|
122
|
-
const data = await request<unknown>(`${apiUrl}/${resource}/${id}`, { method: 'DELETE' });
|
|
123
|
-
results.push(data as unknown as T);
|
|
124
|
-
}
|
|
125
|
-
return { data: results };
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
async custom<T = unknown>({ url, method, payload, headers }: CustomParams): Promise<CustomResult<T>> {
|
|
129
|
-
const data = await request<unknown>(url, {
|
|
130
|
-
method: method.toUpperCase(),
|
|
131
|
-
headers,
|
|
132
|
-
body: payload ? JSON.stringify(payload) : undefined,
|
|
133
|
-
});
|
|
134
|
-
return { data: data as unknown as unknown as T };
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
}
|
|
21
|
+
export type SimpleRestOptions = any;
|