@tanglemedia/svelte-starter-directus-api 7.0.0 → 8.1.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanglemedia/svelte-starter-directus-api",
3
- "version": "7.0.0",
3
+ "version": "8.1.0",
4
4
  "main": "src/index.ts",
5
5
  "types": "src/index.ts",
6
6
  "description": "directus API wrapper for all the directus sdk functionality",
@@ -22,27 +22,24 @@
22
22
  }
23
23
  },
24
24
  "devDependencies": {
25
- "@directus/types": "13.5.0",
26
- "@sveltejs/adapter-auto": "^7.0.0",
27
- "@sveltejs/package": "^2.5.7",
28
- "@sveltejs/vite-plugin-svelte": "^6.2.1",
29
- "@testing-library/jest-dom": "^6.6.3",
30
- "@testing-library/svelte": "^5.2.7",
31
- "@vitest/coverage-v8": "^3.0.8",
32
- "jsdom": "^26.0.0",
33
- "msw": "^2.7.3",
34
- "svelte": "^5.46.1",
35
- "svelte-check": "^4.3.5",
36
- "vite": "^7.3.0",
37
- "vitest": "^4.0.16",
38
- "@internal/eslint-config": "0.0.0",
39
- "@tanglemedia/svelte-starter-core": "3.0.0"
25
+ "@directus/types": "15.0.3",
26
+ "@sveltejs/adapter-auto": "^7.0.1",
27
+ "@sveltejs/package": "^2.5.8",
28
+ "@sveltejs/vite-plugin-svelte": "^7.3.0",
29
+ "@tanglemedia/svelte-starter-core": "3.1.0",
30
+ "@testing-library/jest-dom": "^6.10.0",
31
+ "@testing-library/svelte": "^5.4.2",
32
+ "@vitest/coverage-v8": "^4.1.10",
33
+ "jsdom": "^26.1.0",
34
+ "msw": "^2.15.0",
35
+ "svelte": "^5.57.3",
36
+ "svelte-check": "^4.7.7",
37
+ "vite": "^8.3.5",
38
+ "vitest": "^4.1.10"
40
39
  },
41
40
  "dependencies": {
42
- "@directus/sdk": "20.3.0",
43
- "@types/js-cookie": "^3.0.6",
44
- "esm-env": "^1.2.2",
45
- "js-cookie": "^3.0.5"
41
+ "@directus/sdk": "21.3.0",
42
+ "esm-env": "^1.2.2"
46
43
  },
47
44
  "peerDependencies": {
48
45
  "@sveltejs/kit": ">=2 <3",
@@ -10,9 +10,7 @@ import {
10
10
  updateItems,
11
11
  uploadFiles,
12
12
  type AllCollections,
13
- type DirectusClient,
14
- type RegularCollections,
15
- type RestClient
13
+ type RegularCollections
16
14
  } from '@directus/sdk';
17
15
  import {
18
16
  ApiAdapterAbstract,
@@ -24,15 +22,24 @@ import {
24
22
  type ApiDeleteManyQuery,
25
23
  type ApiFindQuery,
26
24
  type ApiId,
25
+ type ApiPatchQuery,
26
+ type ApiPostQuery,
27
+ type ApiPutQuery,
27
28
  type ApiResponse,
28
29
  type ApiUpdateManyQuery,
29
30
  type BaseApiMethods,
30
31
  type HandleEvent
31
32
  } from '@tanglemedia/svelte-starter-core';
32
- import type { DirectusConfig, SchemaShape } from '../types/adapter.types';
33
+ import type {
34
+ DirectusAdapterClient,
35
+ DirectusApiAdapterOptions,
36
+ DirectusConfig,
37
+ SchemaShape
38
+ } from '../types/adapter.types';
33
39
 
34
- export type AdapterClient<Schema extends SchemaShape = SchemaShape> = DirectusClient<Schema> &
35
- RestClient<Schema>;
40
+ type PathKey<Schema extends SchemaShape> = Extract<RegularCollections<Schema>, string>;
41
+
42
+ export type AdapterClient<Schema extends SchemaShape = SchemaShape> = DirectusAdapterClient<Schema>;
36
43
 
37
44
  const allowedQueryKeys = [
38
45
  'fields',
@@ -49,17 +56,15 @@ const allowedQueryKeys = [
49
56
  'aggregate',
50
57
  'deep',
51
58
  'alias'
52
- ];
59
+ ] as const;
60
+
61
+ type Q = Record<string, unknown>;
53
62
 
54
- /**
55
- * TODO: Various types fixes. The current adapter doesn't correctly follow the types defined under the ApiAdapterAbstract.
56
- * See the fetch adapter under the core
57
- */
58
63
  export class DirectusApiAdapter<
59
64
  Schema extends SchemaShape = SchemaShape,
60
- Path extends RegularCollections<Schema> = RegularCollections<Schema>
65
+ Path extends PathKey<Schema> = PathKey<Schema>
61
66
  >
62
- extends ApiAdapterAbstract<DirectusConfig, ApiAdapterRequestConfig, Path, AdapterClient>
67
+ extends ApiAdapterAbstract<DirectusConfig, ApiAdapterRequestConfig, Path, AdapterClient<Schema>>
63
68
  implements ApiAdapterHandle
64
69
  {
65
70
  constructor(
@@ -70,8 +75,7 @@ export class DirectusApiAdapter<
70
75
  }
71
76
 
72
77
  async handle(event: HandleEvent) {
73
- const f = event.fetch;
74
- this.directus.globals.fetch = f;
78
+ this.directus.globals.fetch = event.fetch;
75
79
  }
76
80
 
77
81
  getAdapterClient(): AdapterClient<Schema> | null {
@@ -82,51 +86,60 @@ export class DirectusApiAdapter<
82
86
  const payload = response.data,
83
87
  meta = response.meta as Record<string, unknown>;
84
88
 
85
- if (!meta) {
86
- return {};
87
- }
88
-
89
- if (typeof meta.total === 'undefined') {
89
+ if (!meta || typeof meta.total === 'undefined') {
90
90
  return {};
91
91
  }
92
92
 
93
93
  const displayed = Array.isArray(payload) ? payload.length : 0;
94
-
95
94
  const total = Number(meta.total);
96
95
 
97
- // todo: Transform or attempt to get meta information
98
- // consider pulling count based on existing filters in order to determine pagination
99
96
  return { total, displayed };
100
97
  }
101
98
 
102
- async includeTotals(collection: AllCollections<Schema>, query?: ApiFindQuery<any>) {
99
+ /**
100
+ * Counts the items matching the query's `filter` and `search`, or returns `null` when
101
+ * `includeTotals` is not enabled on the adapter. Side effect: sends an aggregate request
102
+ * to Directus.
103
+ *
104
+ * A per-request `config.configuration` can override `totalAggregate` and `totalField`,
105
+ * for example to count a collection whose primary key is not `id`.
106
+ *
107
+ * @example
108
+ * await adapter.includeTotals('clinics', { filter }, { configuration: { totalField: 'ID' } });
109
+ * // requests aggregate={"countDistinct":"ID"} when the adapter uses countDistinct
110
+ */
111
+ async includeTotals(
112
+ collection: Path,
113
+ query?: ApiFindQuery<any>,
114
+ config?: ApiAdapterRequestConfig
115
+ ): Promise<number | null> {
103
116
  if (true !== this.config.configuration.includeTotals) {
104
117
  return null;
105
118
  }
106
119
 
107
120
  const { filter, search } = query || {};
108
-
121
+ const override = config?.configuration as Partial<DirectusApiAdapterOptions> | undefined;
109
122
  // default to count. Note that there is a bug in directus where
110
123
  // the wrong counts are being returned if there are nested filters.
111
124
  // A quick fix is to set totalAggregate to countDistinct
112
- const k = this.config.configuration.totalAggregate || 'count';
113
- const f = this.config.configuration.totalField || 'id';
125
+ const k = override?.totalAggregate ?? (this.config.configuration.totalAggregate || 'count');
126
+ const f = override?.totalField ?? (this.config.configuration.totalField || 'id');
114
127
 
115
- const data = await this.directus.request(
116
- aggregate(collection, {
128
+ const data = await this.directus.request<Array<Record<string, unknown>>>(
129
+ aggregate(collection as unknown as AllCollections<Schema>, {
117
130
  aggregate: { [k]: f },
118
131
  query: {
119
132
  ...(filter ? { filter } : {}),
120
133
  ...(search ? { search } : {})
121
134
  }
122
- })
135
+ } as never)
123
136
  );
124
137
 
125
138
  let total = 0;
126
139
 
127
140
  if (data && data.length === 1) {
128
141
  const c = data[0][k];
129
- total = c && typeof c === 'object' ? Number(c[f]) : Number(c);
142
+ total = c && typeof c === 'object' ? Number((c as Record<string, unknown>)[f]) : Number(c);
130
143
  }
131
144
 
132
145
  return isNaN(total) ? 0 : total;
@@ -135,39 +148,27 @@ export class DirectusApiAdapter<
135
148
  async transformResponse<T, M extends object = AnyObject>(
136
149
  res: { data: T; meta?: AnyObject },
137
150
  status: number = 200
138
- ): Promise<ApiResponse<T, Response, M>> {
151
+ ): Promise<ApiResponse<T, null, M>> {
139
152
  return {
140
- body: await this.envelopeResponse<T, M>(
153
+ body: (await this.envelopeResponse<T, M>(
141
154
  res.data,
142
155
  (res.meta ? this.normalizeMeta(res as AnyObject) : {}) as M
143
- ),
144
- status: status,
156
+ )) as ApiResponse<T, null, M>['body'],
157
+ status,
145
158
  statusText: 'OK',
146
159
  headers: {},
147
160
  adapterResponse: null
148
161
  };
149
162
  }
150
163
 
151
- public getConfig(configuration?: unknown): DirectusConfig {
152
- const client = this.directus;
153
-
154
- // Add the 'configuration' property to the returned object
155
- const config: DirectusConfig = {
156
- ...this.config,
157
- configuration: configuration ?? this.config.configuration ?? {} // Use the provided configuration or an empty object if not provided
158
- };
159
-
160
- return Object.assign(client, config);
161
- }
162
-
163
- normalizeQuery(config: ApiAdapterRequestConfig = {}, merge?: Record<string, unknown>) {
164
- const q = { ...(config?.params || {}) };
165
- const c = { ...config } as Record<string, unknown>;
166
- // legacy support, this pulls the directus specific keys from the config
167
- const r = allowedQueryKeys.reduce<Record<string, unknown>>(
164
+ normalizeQuery(config: ApiAdapterRequestConfig = {}, merge?: Q) {
165
+ const q = { ...((config?.params as Q | undefined) || {}) };
166
+ const c = { ...config } as Q;
167
+ const r = allowedQueryKeys.reduce<Q>(
168
168
  (acc, k) => (typeof c[k] !== 'undefined' ? ((acc[k] = c[k]), acc) : acc),
169
169
  {}
170
170
  );
171
+
171
172
  return {
172
173
  ...q,
173
174
  ...r,
@@ -175,158 +176,241 @@ export class DirectusApiAdapter<
175
176
  };
176
177
  }
177
178
 
178
- public async request<T>(
179
+ getId(data: object, config?: ApiAdapterRequestConfig): ApiId | null {
180
+ const d = data as Record<string, unknown>;
181
+ const q = config?.params as Q | undefined;
182
+
183
+ if (typeof d.id === 'string' || typeof d.id === 'number') {
184
+ return d.id;
185
+ }
186
+
187
+ if (q && (typeof q.id === 'string' || typeof q.id === 'number')) {
188
+ return q.id;
189
+ }
190
+
191
+ return null;
192
+ }
193
+
194
+ stripId(config?: ApiAdapterRequestConfig) {
195
+ const q = config?.params as Q | undefined;
196
+
197
+ if (!q || typeof q.id === 'undefined') {
198
+ return config;
199
+ }
200
+
201
+ const { id: _id, ...params } = q;
202
+
203
+ return {
204
+ ...config,
205
+ params
206
+ };
207
+ }
208
+
209
+ public async request<T, R = T>(
179
210
  method: BaseApiMethods,
180
- url: string,
211
+ url: Path,
181
212
  query?: ApiAdapterRequestConfig
182
- ): Promise<T> {
213
+ ): Promise<ApiResponse<R>> {
183
214
  try {
184
- const response = await this.directus.request<T>(() => {
185
- const params = JSON.stringify(query);
186
- return {
187
- path: `${url}?${params}`,
188
- method: method
189
- };
190
- });
191
- return response;
215
+ const { body, headers } = query || {};
216
+ const params = this.normalizeQuery(query);
217
+
218
+ const data = await this.directus.request<R>(
219
+ (() =>
220
+ ({
221
+ path: url,
222
+ method,
223
+ headers,
224
+ params,
225
+ ...(typeof body === 'undefined'
226
+ ? {}
227
+ : {
228
+ body:
229
+ body instanceof FormData || typeof body === 'string'
230
+ ? body
231
+ : JSON.stringify(body)
232
+ })
233
+ })) as never
234
+ );
235
+
236
+ return this.transformResponse({ data }, method === 'POST' ? 201 : method === 'DELETE' ? 202 : 200);
192
237
  } catch (error) {
193
238
  console.error(`Error request:`, error);
194
239
  throw error;
195
240
  }
196
241
  }
197
242
 
198
- public async find<T, Q = T, R = T>(
243
+ public async find<T, F = T, R = T>(
199
244
  collection: Path,
200
- query: ApiFindQuery<Q>,
245
+ query: ApiFindQuery<F>,
201
246
  config?: ApiAdapterRequestConfig
202
247
  ): Promise<ApiResponse<R[]>> {
203
- query = this.normalizeQuery(config, query);
204
- const response = (await this.directus.request<T>(readItems(collection, query))) as R[];
205
- const total = await this.includeTotals(collection, query);
248
+ const q = this.normalizeQuery(config, query as Q);
249
+ const data = await this.directus.request<R[]>(
250
+ readItems(collection as unknown as RegularCollections<Schema>, q as never)
251
+ );
252
+ const total = await this.includeTotals(collection, query, config);
253
+
206
254
  if (null === total) {
207
- return this.transformResponse({ data: response });
255
+ return this.transformResponse({ data });
208
256
  }
209
- // console.log('find meta', response, total)
210
257
 
211
- return this.transformResponse({ data: response, meta: { total } });
258
+ return this.transformResponse({ data, meta: { total } });
212
259
  }
213
260
 
214
- public async findOne<T>(
261
+ public async findOne<T, R = T>(
215
262
  collection: Path,
216
- key?: ApiId,
263
+ key: ApiId,
217
264
  query?: ApiAdapterRequestConfig
218
- ): Promise<ApiResponse<T>> {
265
+ ): Promise<ApiResponse<R>> {
219
266
  const q = this.normalizeQuery(query);
220
- const data = await this.directus.request<T>(readItem(collection, key, query));
267
+ const data = await this.directus.request<R>(
268
+ readItem(collection as unknown as RegularCollections<Schema>, key, q as never)
269
+ );
221
270
  return this.transformResponse({ data });
222
271
  }
223
272
 
224
- public async aggregate<T, Q = T, R = T>(
273
+ public async aggregate<T, F = T, R = T>(
225
274
  collection: Path,
226
- query: ApiAggregateQuery<Q>,
275
+ query: ApiAggregateQuery<F>,
227
276
  config?: ApiAdapterRequestConfig
228
277
  ): Promise<ApiResponse<R>> {
229
- const { aggregate: aggregate_, ...rest } = this.normalizeQuery(config, query);
230
-
231
- const data = await this.directus.request<T>(
232
- aggregate(collection, {
233
- aggregate: aggregate_
234
- ? aggregate_
235
- : {
236
- count: 'id'
237
- },
278
+ const { aggregate: a, ...rest } = this.normalizeQuery(config, query as Q);
279
+
280
+ const data = await this.directus.request<R>(
281
+ aggregate(collection as unknown as AllCollections<Schema>, {
282
+ aggregate: a ? a : { count: 'id' },
238
283
  query: rest
239
- })
284
+ } as never)
240
285
  );
241
286
 
242
287
  return this.transformResponse({ data });
243
288
  }
244
289
 
245
- public async patch<T>(
290
+ public async patch<T extends object, R = T>(
246
291
  collection: Path,
247
292
  key: ApiId,
248
- query?: Record<string, unknown>,
293
+ data: ApiPatchQuery<T>,
249
294
  config?: ApiAdapterRequestConfig
250
- ): Promise<ApiResponse<T>> {
251
- const data = await this.directus.request<T>(updateItem(collection, key, query));
252
- return this.transformResponse({ data });
295
+ ): Promise<ApiResponse<R>> {
296
+ const q = this.normalizeQuery(config);
297
+ const res = await this.directus.request<R>(
298
+ updateItem(collection as never, key, data as never, q as never)
299
+ );
300
+ return this.transformResponse({ data: res });
253
301
  }
254
302
 
255
- public async post<T>(
303
+ public async post<T extends object, R = T>(
256
304
  collection: Path,
257
- data: AnyObject,
258
- query?: Record<string, unknown>,
305
+ data: ApiPostQuery<T>,
259
306
  config?: ApiAdapterRequestConfig
260
- ): Promise<ApiResponse<T>> {
261
- const response = await this.directus.request<T>(createItem(collection, data, query));
262
- return this.transformResponse({ data: response }, 201);
307
+ ): Promise<ApiResponse<R>> {
308
+ const q = this.normalizeQuery(config);
309
+ const res = await this.directus.request<R>(
310
+ createItem(collection as never, data as never, q as never)
311
+ );
312
+ return this.transformResponse({ data: res }, 201);
263
313
  }
264
314
 
265
- public async delete<T>(
315
+ public async delete<T, R = T>(
266
316
  collection: Path,
267
- key?: ApiId,
317
+ key: ApiId,
268
318
  config?: ApiAdapterRequestConfig
269
- ): Promise<ApiResponse<T>> {
270
- const data = await this.directus.request<T>(deleteItem(collection, key));
319
+ ): Promise<ApiResponse<R>> {
320
+ void config;
321
+ const data = await this.directus.request<R>(deleteItem(collection as never, key));
271
322
  return this.transformResponse({ data }, 202);
272
323
  }
273
324
 
274
325
  public async put<T extends object, R = T>(
275
326
  collection: Path,
276
- key?: ApiId,
277
- payload?: AnyObject,
278
- query?: ApiAdapterRequestConfig
327
+ data: ApiPutQuery<T>,
328
+ config?: ApiAdapterRequestConfig
329
+ ): Promise<ApiResponse<R>>;
330
+ public async put<T extends object, R = T>(
331
+ collection: Path,
332
+ key: ApiId,
333
+ data?: AnyObject,
334
+ config?: ApiAdapterRequestConfig
335
+ ): Promise<ApiResponse<R>>;
336
+ public async put<T extends object, R = T>(
337
+ collection: Path,
338
+ keyOrData: ApiId | ApiPutQuery<T>,
339
+ dataOrConfig?: AnyObject | ApiAdapterRequestConfig,
340
+ config?: ApiAdapterRequestConfig
279
341
  ): Promise<ApiResponse<R>> {
280
- if (key) {
281
- const data = (await this.directus.request<T>(
282
- updateItem(collection, key, payload, query)
283
- )) as R;
284
- return this.transformResponse({ data }, 201);
285
- } else {
286
- console.error(`Error updating all ${collection}: no key specified`);
342
+ const key =
343
+ typeof keyOrData === 'string' || typeof keyOrData === 'number'
344
+ ? keyOrData
345
+ : this.getId(keyOrData, dataOrConfig as ApiAdapterRequestConfig | undefined);
346
+ const data =
347
+ typeof keyOrData === 'string' || typeof keyOrData === 'number'
348
+ ? (dataOrConfig as AnyObject | undefined)
349
+ : keyOrData;
350
+ const q =
351
+ typeof keyOrData === 'string' || typeof keyOrData === 'number'
352
+ ? config
353
+ : (dataOrConfig as ApiAdapterRequestConfig | undefined);
354
+
355
+ if (!key) {
287
356
  throw new Error('No key specified');
288
357
  }
358
+
359
+ const res = await this.directus.request<R>(
360
+ updateItem(collection as never, key, data as never, this.normalizeQuery(this.stripId(q)) as never)
361
+ );
362
+
363
+ return this.transformResponse({ data: res }, 201);
289
364
  }
290
365
 
291
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
292
- public async upload<T>(
293
- path: string = '',
366
+ public async upload<T, R = T>(
367
+ path: Path,
294
368
  data: FormData,
295
- config?: ApiAdapterRequestConfig
296
- ): Promise<ApiResponse<T>> {
297
- const response = await this.directus.request<T>(uploadFiles(data));
298
- return this.transformResponse({ data: response }, 201);
369
+ config?: ApiAdapterRequestConfig & { method?: BaseApiMethods }
370
+ ): Promise<ApiResponse<R>> {
371
+ void path;
372
+ void config;
373
+ const res = await this.directus.request<R>(uploadFiles(data));
374
+ return this.transformResponse({ data: res }, 201);
299
375
  }
300
376
 
301
377
  async createMany<T, R = T>(
302
378
  path: Path,
303
379
  body: ApiCreateManyQuery<T>,
304
380
  config?: ApiAdapterRequestConfig
305
- ) {
306
- const data = await this.directus.request<T>(createItems(path, body.data, body?.query));
307
- return this.transformResponse<R[]>({ data }, 200);
381
+ ): Promise<ApiResponse<R[]>> {
382
+ const q = this.normalizeQuery(config, ((body as Q).query as Q | undefined) || {});
383
+ const data = await this.directus.request<R[]>(
384
+ createItems(path as never, body.data as never, q as never)
385
+ );
386
+ return this.transformResponse({ data }, 200);
308
387
  }
309
388
 
310
389
  async updateMany<T, R = T>(
311
390
  path: Path,
312
391
  body: ApiUpdateManyQuery<T>,
313
392
  config?: ApiAdapterRequestConfig
314
- ) {
393
+ ): Promise<ApiResponse<R[]>> {
315
394
  if (!body.ids) {
316
395
  throw Error('You must provide an array of keys to update');
317
396
  }
318
- const data = await this.directus.request<T>(
319
- updateItems(path, body.ids || [], body.data, body?.query)
397
+
398
+ const q = this.normalizeQuery(config, ((body as Q).query as Q | undefined) || {});
399
+ const ids = body.ids as string[] | number[];
400
+ const data = await this.directus.request<R[]>(
401
+ updateItems(path as never, ids, body.data as never, q as never)
320
402
  );
321
- return this.transformResponse<R[]>({ data }, 200);
403
+ return this.transformResponse({ data }, 200);
322
404
  }
323
405
 
324
- async deleteMany<R = null>(
406
+ async deleteMany<R>(
325
407
  path: Path,
326
408
  body: ApiDeleteManyQuery<ApiId>,
327
409
  config?: ApiAdapterRequestConfig
328
- ) {
329
- const data = await this.directus.request(deleteItems(path, body.ids));
330
- return this.transformResponse<R>({ data } as R, 201);
410
+ ): Promise<ApiResponse<R[]>> {
411
+ void config;
412
+ const ids = body.ids as string[] | number[];
413
+ const data = await this.directus.request<R[]>(deleteItems(path as never, ids));
414
+ return this.transformResponse({ data }, 201);
331
415
  }
332
416
  }
package/src/index.ts CHANGED
@@ -7,3 +7,4 @@ export * from './services/register';
7
7
  export type * from './types';
8
8
 
9
9
  export * from './provider/api-references-functions.provider';
10
+ export * from './utils/directus-error';
@@ -1,17 +1,25 @@
1
1
  import type {
2
2
  AdapterProviderRegister,
3
+ ApiAdapterRequestConfig,
3
4
  ApiAdapterInterface,
4
5
  ApiAdapterProviderInterface
5
6
  } from '@tanglemedia/svelte-starter-core';
6
7
  import { DirectusApiAdapter } from '../adapter/api-adapter';
7
- import type { DirectusConfig, SchemaShape } from '../types/adapter.types';
8
+ import type { DirectusAdapterClient, DirectusConfig, SchemaShape } from '../types/adapter.types';
8
9
  import { createDirectusClientFactory } from './directus.factory';
9
10
 
10
11
  export class DirectusApiProvider implements ApiAdapterProviderInterface<DirectusConfig> {
11
12
  async loadAdapter(
12
13
  key?: string,
13
14
  config?: DirectusConfig
14
- ): Promise<ApiAdapterInterface<DirectusConfig>> {
15
+ ): Promise<
16
+ ApiAdapterInterface<
17
+ DirectusConfig,
18
+ ApiAdapterRequestConfig,
19
+ string,
20
+ DirectusAdapterClient<SchemaShape>
21
+ >
22
+ > {
15
23
  if (!config) {
16
24
  throw new Error('Missing adapter configuration');
17
25
  }
@@ -21,7 +29,7 @@ export class DirectusApiProvider implements ApiAdapterProviderInterface<Directus
21
29
  return new DirectusApiAdapter(config, client);
22
30
  }
23
31
 
24
- createDirectusClient<T extends object>(config: DirectusConfig) {
32
+ createDirectusClient<T extends SchemaShape>(config: DirectusConfig): DirectusAdapterClient<T> {
25
33
  // todo: Determine if we can overwrite the fetch globals during runtime
26
34
  return createDirectusClientFactory<T>(config);
27
35
  }