@svadmin/appwrite 0.8.7 → 0.8.9
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 +11 -8
- package/src/appwrite.test.ts +0 -252
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/appwrite",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"description": "Appwrite adapters — DataProvider, AuthProvider, LiveProvider for svadmin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"files": [
|
|
8
|
-
"src
|
|
8
|
+
"src/**/*.ts",
|
|
9
|
+
"!src/**/*.test.*",
|
|
10
|
+
"!src/**/*.spec.*",
|
|
11
|
+
"!src/**/vitest.config.*",
|
|
12
|
+
"!src/**/setupTest.*"
|
|
9
13
|
],
|
|
10
14
|
"main": "src/index.ts",
|
|
11
15
|
"types": "src/index.ts",
|
|
@@ -16,10 +20,9 @@
|
|
|
16
20
|
}
|
|
17
21
|
},
|
|
18
22
|
"peerDependencies": {
|
|
19
|
-
"@svadmin/core": "^0.
|
|
23
|
+
"@svadmin/core": "^0.25.3",
|
|
20
24
|
"appwrite": ">=14.0.0",
|
|
21
|
-
"@refinedev/appwrite": "^8.0.1"
|
|
22
|
-
"@svadmin/refine-adapter": "^0.9.3"
|
|
25
|
+
"@refinedev/appwrite": "^8.0.1"
|
|
23
26
|
},
|
|
24
27
|
"keywords": [
|
|
25
28
|
"svadmin",
|
|
@@ -48,9 +51,9 @@
|
|
|
48
51
|
},
|
|
49
52
|
"@refinedev/appwrite": {
|
|
50
53
|
"optional": true
|
|
51
|
-
},
|
|
52
|
-
"@svadmin/refine-adapter": {
|
|
53
|
-
"optional": true
|
|
54
54
|
}
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@svadmin/refine-adapter": "^0.9.4"
|
|
55
58
|
}
|
|
56
59
|
}
|
package/src/appwrite.test.ts
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
// @svadmin/appwrite — Unit Tests
|
|
2
|
-
import { describe, test, expect, mock } from 'bun:test';
|
|
3
|
-
import { createAppwriteDataProvider } from './data-provider';
|
|
4
|
-
import { createAppwriteAuthProvider } from './auth-provider';
|
|
5
|
-
import { createAppwriteLiveProvider } from './live-provider';
|
|
6
|
-
|
|
7
|
-
// ─── Mock Appwrite Databases ────────────────────────────────
|
|
8
|
-
mock.module('@refinedev/appwrite', () => {
|
|
9
|
-
return {
|
|
10
|
-
dataProvider: (args: any) => {
|
|
11
|
-
const { databases, databaseId } = args;
|
|
12
|
-
const mockDp: any = {
|
|
13
|
-
getList: async (params: any) => {
|
|
14
|
-
if (params.pagination) databases.listDocuments(databaseId, params.resource, [`limit(${params.pagination.pageSize})`, `offset(${params.pagination.pageSize})`]);
|
|
15
|
-
else if (params.sorters) databases.listDocuments(databaseId, params.resource, [`orderDesc`]);
|
|
16
|
-
else if (params.filters) databases.listDocuments(databaseId, params.resource, [`equal`]);
|
|
17
|
-
else databases.listDocuments(databaseId, params.resource);
|
|
18
|
-
return { data: [{ $id: '1', name: 'Test' }, { $id: '2', name: 'Test2' }], total: 2 };
|
|
19
|
-
},
|
|
20
|
-
getOne: async (params: any) => ({ data: { $id: '1', name: 'Test' } }),
|
|
21
|
-
create: async (params: any) => ({ data: { $id: 'new-1', ...params.variables } }),
|
|
22
|
-
update: async (params: any) => ({ data: { $id: params.id, ...params.variables } }),
|
|
23
|
-
deleteOne: async (params: any) => { await databases.deleteDocument(databaseId, params.resource, params.id); return { data: {} }; },
|
|
24
|
-
getApiUrl: () => '',
|
|
25
|
-
getMany: async (params: any) => ({ data: params.ids.map((id: string) => ({ $id: id })) }),
|
|
26
|
-
deleteMany: async () => { for (const id of ['1', '2']) await databases.deleteDocument(databaseId, 'posts', id); },
|
|
27
|
-
};
|
|
28
|
-
return mockDp;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
function createMockDatabases() {
|
|
35
|
-
return {
|
|
36
|
-
listDocuments: mock(async (_db: string, _col: string, _q?: string[]) => ({
|
|
37
|
-
documents: [{ $id: '1', name: 'Test' }, { $id: '2', name: 'Test2' }],
|
|
38
|
-
total: 2,
|
|
39
|
-
})),
|
|
40
|
-
getDocument: mock(async (_db: string, _col: string, _id: string) => ({
|
|
41
|
-
$id: _id, name: 'Test',
|
|
42
|
-
})),
|
|
43
|
-
createDocument: mock(async (_db: string, _col: string, _docId: string, data: Record<string, unknown>) => ({
|
|
44
|
-
$id: 'new-1', ...data,
|
|
45
|
-
})),
|
|
46
|
-
updateDocument: mock(async (_db: string, _col: string, _docId: string, data: Record<string, unknown>) => ({
|
|
47
|
-
$id: _docId, ...data,
|
|
48
|
-
})),
|
|
49
|
-
deleteDocument: mock(async () => {}),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// ─── Mock Appwrite Account ──────────────────────────────────
|
|
54
|
-
|
|
55
|
-
function createMockAccount(overrides: Record<string, unknown> = {}) {
|
|
56
|
-
return {
|
|
57
|
-
createEmailPasswordSession: mock(async () => ({ $id: 'session-1' })),
|
|
58
|
-
deleteSession: mock(async () => {}),
|
|
59
|
-
get: mock(async () => ({ $id: 'user-1', name: 'Admin', email: 'admin@test.com', prefs: {} })),
|
|
60
|
-
create: mock(async () => ({ $id: 'user-2' })),
|
|
61
|
-
createRecovery: mock(async () => ({})),
|
|
62
|
-
updatePassword: mock(async () => ({})),
|
|
63
|
-
...overrides,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ─── DataProvider Tests ─────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
describe('Appwrite DataProvider', () => {
|
|
70
|
-
test('getList returns data with total', async () => {
|
|
71
|
-
const db = createMockDatabases();
|
|
72
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
73
|
-
const result = await dp.getList({ resource: 'posts' });
|
|
74
|
-
expect(result.data).toHaveLength(2);
|
|
75
|
-
expect(result.total).toBe(2);
|
|
76
|
-
expect(db.listDocuments).toHaveBeenCalledTimes(1);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('getList passes pagination as queries', async () => {
|
|
80
|
-
const db = createMockDatabases();
|
|
81
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
82
|
-
await dp.getList({ resource: 'posts', pagination: { current: 2, pageSize: 5 } });
|
|
83
|
-
const queries = db.listDocuments.mock.calls[0][2] as string[];
|
|
84
|
-
expect(queries).toContain('limit(5)');
|
|
85
|
-
expect(queries).toContain('offset(5)');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('getList passes sorters as queries', async () => {
|
|
89
|
-
const db = createMockDatabases();
|
|
90
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
91
|
-
await dp.getList({ resource: 'posts', sorters: [{ field: 'name', order: 'desc' }] });
|
|
92
|
-
const queries = db.listDocuments.mock.calls[0][2] as string[];
|
|
93
|
-
expect(queries.some((q: string) => q.includes('orderDesc'))).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('getList passes filters as queries', async () => {
|
|
97
|
-
const db = createMockDatabases();
|
|
98
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
99
|
-
await dp.getList({ resource: 'posts', filters: [{ field: 'status', operator: 'eq', value: 'active' }] });
|
|
100
|
-
const queries = db.listDocuments.mock.calls[0][2] as string[];
|
|
101
|
-
expect(queries.some((q: string) => q.includes('equal'))).toBe(true);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('getOne returns single record', async () => {
|
|
105
|
-
const db = createMockDatabases();
|
|
106
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
107
|
-
const result = await dp.getOne({ resource: 'posts', id: '1' });
|
|
108
|
-
expect(result.data).toHaveProperty('$id', '1');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test('create returns new record', async () => {
|
|
112
|
-
const db = createMockDatabases();
|
|
113
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
114
|
-
const result = await dp.create({ resource: 'posts', variables: { name: 'New Post' } });
|
|
115
|
-
expect(result.data).toHaveProperty('name', 'New Post');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('update returns updated record', async () => {
|
|
119
|
-
const db = createMockDatabases();
|
|
120
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
121
|
-
const result = await dp.update({ resource: 'posts', id: '1', variables: { name: 'Updated' } });
|
|
122
|
-
expect(result.data).toHaveProperty('name', 'Updated');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test('deleteOne calls deleteDocument', async () => {
|
|
126
|
-
const db = createMockDatabases();
|
|
127
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
128
|
-
await dp.deleteOne({ resource: 'posts', id: '1' });
|
|
129
|
-
expect(db.deleteDocument).toHaveBeenCalledTimes(1);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('getMany fetches by ids', async () => {
|
|
133
|
-
const db = createMockDatabases();
|
|
134
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
135
|
-
const result = await dp.getMany!({ resource: 'posts', ids: ['1', '2'] });
|
|
136
|
-
expect(result.data).toHaveLength(2);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('deleteMany deletes each id', async () => {
|
|
140
|
-
const db = createMockDatabases();
|
|
141
|
-
const dp = await createAppwriteDataProvider({ databases: db, databaseId: 'main' });
|
|
142
|
-
await dp.deleteMany!({ resource: 'posts', ids: ['1', '2'] });
|
|
143
|
-
expect(db.deleteDocument).toHaveBeenCalledTimes(2);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// ─── AuthProvider Tests ─────────────────────────────────────
|
|
148
|
-
|
|
149
|
-
describe('Appwrite AuthProvider', () => {
|
|
150
|
-
test('login success', async () => {
|
|
151
|
-
const account = createMockAccount();
|
|
152
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
153
|
-
const result = await auth.login({ email: 'admin@test.com', password: 'pass' });
|
|
154
|
-
expect(result.success).toBe(true);
|
|
155
|
-
expect(result.redirectTo).toBe('/');
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test('login failure', async () => {
|
|
159
|
-
const account = createMockAccount({
|
|
160
|
-
createEmailPasswordSession: mock(async () => { throw new Error('Invalid credentials'); }),
|
|
161
|
-
});
|
|
162
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
163
|
-
const result = await auth.login({ email: 'bad', password: 'bad' });
|
|
164
|
-
expect(result.success).toBe(false);
|
|
165
|
-
expect(result.error?.message).toBe('Invalid credentials');
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
test('logout success', async () => {
|
|
169
|
-
const account = createMockAccount();
|
|
170
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
171
|
-
const result = await auth.logout();
|
|
172
|
-
expect(result.success).toBe(true);
|
|
173
|
-
expect(result.redirectTo).toBe('/login');
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
test('check returns authenticated', async () => {
|
|
177
|
-
const account = createMockAccount();
|
|
178
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
179
|
-
const result = await auth.check();
|
|
180
|
-
expect(result.authenticated).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('check returns not authenticated on error', async () => {
|
|
184
|
-
const account = createMockAccount({
|
|
185
|
-
get: mock(async () => { throw new Error('Unauthorized'); }),
|
|
186
|
-
});
|
|
187
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
188
|
-
const result = await auth.check();
|
|
189
|
-
expect(result.authenticated).toBe(false);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
test('getIdentity returns user', async () => {
|
|
193
|
-
const account = createMockAccount();
|
|
194
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
195
|
-
const identity = await auth.getIdentity();
|
|
196
|
-
expect(identity).not.toBeNull();
|
|
197
|
-
expect(identity!.name).toBe('Admin');
|
|
198
|
-
expect(identity!.email).toBe('admin@test.com');
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('register success', async () => {
|
|
202
|
-
const account = createMockAccount();
|
|
203
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
204
|
-
const result = await auth.register!({ email: 'new@test.com', password: 'pass123' });
|
|
205
|
-
expect(result.success).toBe(true);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test('onError with 401', async () => {
|
|
209
|
-
const account = createMockAccount();
|
|
210
|
-
const auth = createAppwriteAuthProvider({ account });
|
|
211
|
-
const result = await auth.onError!(new Error('401 Unauthorized'));
|
|
212
|
-
expect(result.logout).toBe(true);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// ─── LiveProvider Tests ─────────────────────────────────────
|
|
217
|
-
|
|
218
|
-
describe('Appwrite LiveProvider', () => {
|
|
219
|
-
test('subscribe calls client.subscribe with correct channel', () => {
|
|
220
|
-
const unsubFn = mock(() => {});
|
|
221
|
-
const mockClient = {
|
|
222
|
-
subscribe: mock((_channels: string, _cb: unknown) => unsubFn),
|
|
223
|
-
};
|
|
224
|
-
const lp = createAppwriteLiveProvider({ client: mockClient, databaseId: 'main' });
|
|
225
|
-
const cb = mock(() => {});
|
|
226
|
-
const unsub = lp.subscribe({ resource: 'posts', callback: cb });
|
|
227
|
-
|
|
228
|
-
expect(mockClient.subscribe).toHaveBeenCalledTimes(1);
|
|
229
|
-
const channel = mockClient.subscribe.mock.calls[0][0];
|
|
230
|
-
expect(channel).toBe('databases.main.collections.posts.documents');
|
|
231
|
-
|
|
232
|
-
unsub();
|
|
233
|
-
expect(unsubFn).toHaveBeenCalledTimes(1);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
test('subscribe maps create event to INSERT', () => {
|
|
237
|
-
let handler: ((payload: unknown) => void) | null = null;
|
|
238
|
-
const mockClient = {
|
|
239
|
-
subscribe: mock((_channels: string, cb: (payload: unknown) => void) => {
|
|
240
|
-
handler = cb;
|
|
241
|
-
return () => {};
|
|
242
|
-
}),
|
|
243
|
-
};
|
|
244
|
-
const lp = createAppwriteLiveProvider({ client: mockClient, databaseId: 'main' });
|
|
245
|
-
const cb = mock(() => {});
|
|
246
|
-
lp.subscribe({ resource: 'posts', callback: cb });
|
|
247
|
-
|
|
248
|
-
handler!({ events: ['databases.main.collections.posts.documents.*.create'], payload: { $id: '1' } });
|
|
249
|
-
expect(cb).toHaveBeenCalledTimes(1);
|
|
250
|
-
expect((cb.mock.calls as any)[0][0].type).toBe('INSERT');
|
|
251
|
-
});
|
|
252
|
-
});
|