@tanglemedia/svelte-starter-directus-api 6.0.2 → 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": "6.0.2",
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,31 +22,28 @@
22
22
  }
23
23
  },
24
24
  "devDependencies": {
25
- "@directus/types": "13.0.0",
26
- "@sveltejs/adapter-auto": "^4.0.0",
27
- "@sveltejs/package": "^2.3.10",
28
- "@sveltejs/vite-plugin-svelte": "^5.0.3",
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.22.6",
35
- "svelte-check": "^4.1.5",
36
- "vite": "^6.2.1",
37
- "vitest": "^3.0.8",
38
- "@internal/eslint-config": "0.0.0",
39
- "@tanglemedia/svelte-starter-core": "2.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": "19.0.1",
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",
49
- "@tanglemedia/svelte-starter-core": ">=2.0.0",
46
+ "@tanglemedia/svelte-starter-core": ">=3.0.0",
50
47
  "svelte": "^4.0.0 || >=5.0.0"
51
48
  },
52
49
  "scripts": {
@@ -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,25 +22,49 @@ 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';
39
+
40
+ type PathKey<Schema extends SchemaShape> = Extract<RegularCollections<Schema>, string>;
41
+
42
+ export type AdapterClient<Schema extends SchemaShape = SchemaShape> = DirectusAdapterClient<Schema>;
43
+
44
+ const allowedQueryKeys = [
45
+ 'fields',
46
+ 'sort',
47
+ 'filter',
48
+ 'limit',
49
+ 'offset',
50
+ 'page',
51
+ 'search',
52
+ 'version',
53
+ 'versionRaw',
54
+ 'export',
55
+ 'group',
56
+ 'aggregate',
57
+ 'deep',
58
+ 'alias'
59
+ ] as const;
60
+
61
+ type Q = Record<string, unknown>;
33
62
 
34
- export type AdapterClient<Schema extends SchemaShape = SchemaShape> = DirectusClient<Schema> &
35
- RestClient<Schema>;
36
-
37
- /**
38
- * TODO: Various types fixes. The current adapter doesn't correctly follow the types defined under the ApiAdapterAbstract.
39
- * See the fetch adapter under the core
40
- */
41
63
  export class DirectusApiAdapter<
42
64
  Schema extends SchemaShape = SchemaShape,
43
- Path extends RegularCollections<Schema> = RegularCollections<Schema>
65
+ Path extends PathKey<Schema> = PathKey<Schema>
44
66
  >
45
- extends ApiAdapterAbstract<DirectusConfig, ApiAdapterRequestConfig, Path, AdapterClient>
67
+ extends ApiAdapterAbstract<DirectusConfig, ApiAdapterRequestConfig, Path, AdapterClient<Schema>>
46
68
  implements ApiAdapterHandle
47
69
  {
48
70
  constructor(
@@ -53,8 +75,7 @@ export class DirectusApiAdapter<
53
75
  }
54
76
 
55
77
  async handle(event: HandleEvent) {
56
- const f = event.fetch;
57
- this.directus.globals.fetch = f;
78
+ this.directus.globals.fetch = event.fetch;
58
79
  }
59
80
 
60
81
  getAdapterClient(): AdapterClient<Schema> | null {
@@ -65,51 +86,60 @@ export class DirectusApiAdapter<
65
86
  const payload = response.data,
66
87
  meta = response.meta as Record<string, unknown>;
67
88
 
68
- if (!meta) {
69
- return {};
70
- }
71
-
72
- if (typeof meta.total === 'undefined') {
89
+ if (!meta || typeof meta.total === 'undefined') {
73
90
  return {};
74
91
  }
75
92
 
76
93
  const displayed = Array.isArray(payload) ? payload.length : 0;
77
-
78
94
  const total = Number(meta.total);
79
95
 
80
- // todo: Transform or attempt to get meta information
81
- // consider pulling count based on existing filters in order to determine pagination
82
96
  return { total, displayed };
83
97
  }
84
98
 
85
- 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> {
86
116
  if (true !== this.config.configuration.includeTotals) {
87
117
  return null;
88
118
  }
89
119
 
90
120
  const { filter, search } = query || {};
91
-
121
+ const override = config?.configuration as Partial<DirectusApiAdapterOptions> | undefined;
92
122
  // default to count. Note that there is a bug in directus where
93
123
  // the wrong counts are being returned if there are nested filters.
94
124
  // A quick fix is to set totalAggregate to countDistinct
95
- const k = this.config.configuration.totalAggregate || 'count';
96
- 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');
97
127
 
98
- const data = await this.directus.request(
99
- aggregate(collection, {
128
+ const data = await this.directus.request<Array<Record<string, unknown>>>(
129
+ aggregate(collection as unknown as AllCollections<Schema>, {
100
130
  aggregate: { [k]: f },
101
131
  query: {
102
132
  ...(filter ? { filter } : {}),
103
133
  ...(search ? { search } : {})
104
134
  }
105
- })
135
+ } as never)
106
136
  );
107
137
 
108
138
  let total = 0;
109
139
 
110
140
  if (data && data.length === 1) {
111
141
  const c = data[0][k];
112
- 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);
113
143
  }
114
144
 
115
145
  return isNaN(total) ? 0 : total;
@@ -118,157 +148,269 @@ export class DirectusApiAdapter<
118
148
  async transformResponse<T, M extends object = AnyObject>(
119
149
  res: { data: T; meta?: AnyObject },
120
150
  status: number = 200
121
- ): Promise<ApiResponse<T, Response, M>> {
151
+ ): Promise<ApiResponse<T, null, M>> {
122
152
  return {
123
- body: await this.envelopeResponse<T, M>(
153
+ body: (await this.envelopeResponse<T, M>(
124
154
  res.data,
125
155
  (res.meta ? this.normalizeMeta(res as AnyObject) : {}) as M
126
- ),
127
- status: status,
156
+ )) as ApiResponse<T, null, M>['body'],
157
+ status,
128
158
  statusText: 'OK',
129
159
  headers: {},
130
160
  adapterResponse: null
131
161
  };
132
162
  }
133
163
 
134
- public getConfig(configuration?: unknown): DirectusConfig {
135
- const client = this.directus;
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
+ (acc, k) => (typeof c[k] !== 'undefined' ? ((acc[k] = c[k]), acc) : acc),
169
+ {}
170
+ );
136
171
 
137
- // Add the 'configuration' property to the returned object
138
- const config: DirectusConfig = {
139
- ...this.config,
140
- configuration: configuration ?? this.config.configuration ?? {} // Use the provided configuration or an empty object if not provided
172
+ return {
173
+ ...q,
174
+ ...r,
175
+ ...(merge || {})
141
176
  };
177
+ }
178
+
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
+ }
142
186
 
143
- return Object.assign(client, config);
187
+ if (q && (typeof q.id === 'string' || typeof q.id === 'number')) {
188
+ return q.id;
189
+ }
190
+
191
+ return null;
144
192
  }
145
193
 
146
- public async request<T>(
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>(
147
210
  method: BaseApiMethods,
148
- url: string,
149
- query?: Record<string, unknown>
150
- ): Promise<T> {
211
+ url: Path,
212
+ query?: ApiAdapterRequestConfig
213
+ ): Promise<ApiResponse<R>> {
151
214
  try {
152
- const response = await this.directus.request<T>(() => {
153
- const params = JSON.stringify(query);
154
- return {
155
- path: `${url}?${params}`,
156
- method: method
157
- };
158
- });
159
- 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);
160
237
  } catch (error) {
161
238
  console.error(`Error request:`, error);
162
239
  throw error;
163
240
  }
164
241
  }
165
242
 
166
- public async find<T, Q = T, R = T>(
243
+ public async find<T, F = T, R = T>(
167
244
  collection: Path,
168
- query: ApiFindQuery<Q>
245
+ query: ApiFindQuery<F>,
246
+ config?: ApiAdapterRequestConfig
169
247
  ): Promise<ApiResponse<R[]>> {
170
- const response = (await this.directus.request<T>(readItems(collection, query))) as R[];
171
- 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
+
172
254
  if (null === total) {
173
- return this.transformResponse({ data: response });
255
+ return this.transformResponse({ data });
174
256
  }
175
- // console.log('find meta', response, total)
176
257
 
177
- return this.transformResponse({ data: response, meta: { total } });
258
+ return this.transformResponse({ data, meta: { total } });
178
259
  }
179
260
 
180
- public async findOne<T>(
261
+ public async findOne<T, R = T>(
181
262
  collection: Path,
182
- key?: ApiId,
183
- query?: Record<string, unknown>
184
- ): Promise<ApiResponse<T>> {
185
- const data = await this.directus.request<T>(readItem(collection, key, query));
263
+ key: ApiId,
264
+ query?: ApiAdapterRequestConfig
265
+ ): Promise<ApiResponse<R>> {
266
+ const q = this.normalizeQuery(query);
267
+ const data = await this.directus.request<R>(
268
+ readItem(collection as unknown as RegularCollections<Schema>, key, q as never)
269
+ );
186
270
  return this.transformResponse({ data });
187
271
  }
188
272
 
189
- public async aggregate<T, Q = T, R = T>(
273
+ public async aggregate<T, F = T, R = T>(
190
274
  collection: Path,
191
- query: ApiAggregateQuery<Q>
275
+ query: ApiAggregateQuery<F>,
276
+ config?: ApiAdapterRequestConfig
192
277
  ): Promise<ApiResponse<R>> {
193
- const { aggregate: aggregate_, ...rest } = query || {};
194
-
195
- const data = await this.directus.request<T>(
196
- aggregate(collection, {
197
- aggregate: aggregate_
198
- ? aggregate_
199
- : {
200
- count: 'id'
201
- },
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' },
202
283
  query: rest
203
- })
284
+ } as never)
204
285
  );
205
286
 
206
287
  return this.transformResponse({ data });
207
288
  }
208
289
 
209
- public async patch<T>(
290
+ public async patch<T extends object, R = T>(
210
291
  collection: Path,
211
292
  key: ApiId,
212
- query?: Record<string, unknown>
213
- ): Promise<ApiResponse<T>> {
214
- const data = await this.directus.request<T>(updateItem(collection, key, query));
215
- return this.transformResponse({ data });
293
+ data: ApiPatchQuery<T>,
294
+ config?: ApiAdapterRequestConfig
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 });
216
301
  }
217
302
 
218
- public async post<T>(
303
+ public async post<T extends object, R = T>(
219
304
  collection: Path,
220
- data: AnyObject,
221
- query?: Record<string, unknown>
222
- ): Promise<ApiResponse<T>> {
223
- const response = await this.directus.request<T>(createItem(collection, data, query));
224
- return this.transformResponse({ data: response }, 201);
305
+ data: ApiPostQuery<T>,
306
+ config?: ApiAdapterRequestConfig
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);
225
313
  }
226
314
 
227
- public async delete<T>(collection: Path, key?: ApiId): Promise<ApiResponse<T>> {
228
- const data = await this.directus.request<T>(deleteItem(collection, key));
315
+ public async delete<T, R = T>(
316
+ collection: Path,
317
+ key: ApiId,
318
+ config?: ApiAdapterRequestConfig
319
+ ): Promise<ApiResponse<R>> {
320
+ void config;
321
+ const data = await this.directus.request<R>(deleteItem(collection as never, key));
229
322
  return this.transformResponse({ data }, 202);
230
323
  }
231
324
 
232
325
  public async put<T extends object, R = T>(
233
326
  collection: Path,
234
- key?: ApiId,
235
- payload?: AnyObject,
236
- query?: Record<string, unknown>
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
237
341
  ): Promise<ApiResponse<R>> {
238
- if (key) {
239
- const data = (await this.directus.request<T>(
240
- updateItem(collection, key, payload, query)
241
- )) as R;
242
- return this.transformResponse({ data }, 201);
243
- } else {
244
- 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) {
245
356
  throw new Error('No key specified');
246
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);
247
364
  }
248
365
 
249
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
250
- public async upload<T>(path: string = '', data: FormData): Promise<ApiResponse<T>> {
251
- const response = await this.directus.request<T>(uploadFiles(data));
252
- return this.transformResponse({ data: response }, 201);
366
+ public async upload<T, R = T>(
367
+ path: Path,
368
+ data: FormData,
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);
253
375
  }
254
376
 
255
- async createMany<T, R = T>(path: Path, body: ApiCreateManyQuery<T>) {
256
- const data = await this.directus.request<T>(createItems(path, body.data, body?.query));
257
- return this.transformResponse<R[]>({ data }, 200);
377
+ async createMany<T, R = T>(
378
+ path: Path,
379
+ body: ApiCreateManyQuery<T>,
380
+ config?: ApiAdapterRequestConfig
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);
258
387
  }
259
388
 
260
- async updateMany<T, R = T>(path: Path, body: ApiUpdateManyQuery<T>) {
389
+ async updateMany<T, R = T>(
390
+ path: Path,
391
+ body: ApiUpdateManyQuery<T>,
392
+ config?: ApiAdapterRequestConfig
393
+ ): Promise<ApiResponse<R[]>> {
261
394
  if (!body.ids) {
262
395
  throw Error('You must provide an array of keys to update');
263
396
  }
264
- const data = await this.directus.request<T>(
265
- 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)
266
402
  );
267
- return this.transformResponse<R[]>({ data }, 200);
403
+ return this.transformResponse({ data }, 200);
268
404
  }
269
405
 
270
- async deleteMany<R = null>(path: Path, body: ApiDeleteManyQuery<ApiId>) {
271
- const data = await this.directus.request(deleteItems(path, body.ids));
272
- return this.transformResponse<R>({ data } as R, 201);
406
+ async deleteMany<R>(
407
+ path: Path,
408
+ body: ApiDeleteManyQuery<ApiId>,
409
+ config?: ApiAdapterRequestConfig
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);
273
415
  }
274
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
  }