@tanglemedia/svelte-starter-directus-api 0.0.16 → 0.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.
Files changed (43) hide show
  1. package/dist/adapter/api-adapter.d.ts +22 -0
  2. package/dist/adapter/api-adapter.js +100 -0
  3. package/dist/{auth.js → auth.deprecated.js} +3 -42
  4. package/dist/{client.js → client.deprecated.js} +3 -36
  5. package/dist/index.d.ts +9 -4
  6. package/dist/index.js +8 -4
  7. package/dist/{load-directus-api-povider.d.ts → load-directus-api-povider.deprecated.d.ts} +3 -2
  8. package/dist/{load-directus-api-povider.js → load-directus-api-povider.deprecated.js} +16 -11
  9. package/dist/provider/api-adapter.provider.d.ts +7 -0
  10. package/dist/provider/api-adapter.provider.js +21 -0
  11. package/dist/provider/directus.factory.d.ts +6 -0
  12. package/dist/provider/directus.factory.js +46 -0
  13. package/dist/services/auth.d.ts +13 -0
  14. package/dist/services/auth.js +75 -0
  15. package/dist/services/register.d.ts +16 -0
  16. package/dist/services/register.js +18 -0
  17. package/dist/static.deprecated.d.ts +22 -0
  18. package/dist/static.deprecated.js +58 -0
  19. package/dist/storage/local-storage.d.ts +9 -0
  20. package/dist/storage/local-storage.js +30 -0
  21. package/dist/types/adapter.types.d.ts +23 -0
  22. package/dist/types/adapter.types.js +1 -0
  23. package/dist/types/index.d.ts +1 -0
  24. package/dist/types/index.js +1 -0
  25. package/package.json +2 -2
  26. package/src/adapter/api-adapter.ts +168 -0
  27. package/src/{auth.ts → auth.deprecated.ts} +10 -65
  28. package/src/{static.ts → client.deprecated.ts} +31 -33
  29. package/src/index.ts +12 -4
  30. package/src/{load-directus-api-povider.ts → load-directus-api-povider.deprecated.ts} +21 -14
  31. package/src/provider/api-adapter.provider.ts +35 -0
  32. package/src/provider/directus.factory.ts +70 -0
  33. package/src/services/auth.ts +82 -0
  34. package/src/services/register.ts +28 -0
  35. package/src/static.deprecated.ts +77 -0
  36. package/src/storage/local-storage.ts +33 -0
  37. package/src/types/adapter.types.ts +30 -0
  38. package/src/types/index.ts +1 -0
  39. package/dist/static.d.ts +0 -31
  40. package/dist/static.js +0 -151
  41. package/src/client.ts +0 -254
  42. /package/dist/{auth.d.ts → auth.deprecated.d.ts} +0 -0
  43. /package/dist/{client.d.ts → client.deprecated.d.ts} +0 -0
@@ -0,0 +1,23 @@
1
+ import type { AuthenticationMode, GraphqlConfig } from '@directus/sdk';
2
+ import type { BaseApiAdapterConfig } from '@tanglemedia/svelte-starter-core';
3
+ export type DirectusApiAuthOptions = {
4
+ mode: AuthenticationMode;
5
+ config?: Partial<{
6
+ autoRefresh: boolean;
7
+ msRefreshBeforeExpires: number;
8
+ credentials?: RequestCredentials;
9
+ storage?: 'localStorage' | 'memoryStorage';
10
+ }>;
11
+ };
12
+ export type DirectusApiAdapterOptions = {
13
+ protocol?: 'http' | 'https';
14
+ host?: string | null;
15
+ auth?: DirectusApiAuthOptions;
16
+ staticToken?: string;
17
+ graphql?: GraphqlConfig;
18
+ rest?: {
19
+ credentials?: RequestCredentials;
20
+ };
21
+ };
22
+ export type DirectusConfig = BaseApiAdapterConfig<DirectusApiAdapterOptions>;
23
+ export type SchemaShape = Record<string, object>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './adapter.types';
@@ -0,0 +1 @@
1
+ export * from './adapter.types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanglemedia/svelte-starter-directus-api",
3
- "version": "0.0.16",
3
+ "version": "0.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",
@@ -41,7 +41,7 @@
41
41
  "@types/js-cookie": "^3.0.6",
42
42
  "esm-env": "^1.0.0",
43
43
  "js-cookie": "^3.0.5",
44
- "@tanglemedia/svelte-starter-core": "0.0.16"
44
+ "@tanglemedia/svelte-starter-core": "0.0.17"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@sveltejs/kit": ">=2 <3",
@@ -0,0 +1,168 @@
1
+ import {
2
+ aggregate,
3
+ createItem,
4
+ deleteItem,
5
+ readItem,
6
+ readItems,
7
+ updateItem,
8
+ uploadFiles,
9
+ type DirectusClient,
10
+ type RestClient
11
+ } from '@directus/sdk';
12
+ import {
13
+ ApiAdapterAbstract,
14
+ type AnyObject,
15
+ type ApiAdapterRequestConfig,
16
+ type ApiId,
17
+ type ApiResponse,
18
+ type BaseApiMethods
19
+ } from '@tanglemedia/svelte-starter-core';
20
+ import type { DirectusConfig, SchemaShape } from '../types/adapter.types';
21
+
22
+ export type AdapterClient<Schema extends SchemaShape = SchemaShape> = DirectusClient<Schema> &
23
+ RestClient<Schema>;
24
+
25
+ export class DirectusApiAdapter<
26
+ Schema extends SchemaShape = SchemaShape,
27
+ Path extends string = keyof SchemaShape
28
+ > extends ApiAdapterAbstract<DirectusConfig, ApiAdapterRequestConfig, Path, AdapterClient> {
29
+ constructor(
30
+ protected config: DirectusConfig,
31
+ private readonly directus: AdapterClient<Schema>
32
+ ) {
33
+ super(config);
34
+ }
35
+
36
+ getAdapterClient(): AdapterClient<Schema> | null {
37
+ return this.directus;
38
+ }
39
+
40
+ normalizeMeta(payload: AnyObject) {
41
+ // todo: Transform or attempt to get meta information
42
+ // consider pulling count based on existing filters in order to determine pagination
43
+ return payload;
44
+ }
45
+
46
+ async transformResponse<T, M extends object = AnyObject>(
47
+ res: T,
48
+ status: number = 200
49
+ ): Promise<ApiResponse<T, Response, M>> {
50
+ // const payload = (await res.json()) as T;
51
+
52
+ return {
53
+ body: await this.envelopeResponse<T, M>(
54
+ res.data || res
55
+ // this.normalizeMeta(payload as AnyObject) as M
56
+ ),
57
+ status: status,
58
+ statusText: 'OK',
59
+ headers: {},
60
+ adapterResponse: null
61
+ };
62
+ }
63
+
64
+ public getConfig(configuration?: unknown): DirectusConfig {
65
+ const client = this.directus;
66
+
67
+ // Add the 'configuration' property to the returned object
68
+ const config: DirectusConfig = {
69
+ ...this.config,
70
+ configuration: configuration ?? {} // Use the provided configuration or an empty object if not provided
71
+ };
72
+
73
+ return Object.assign(client, config);
74
+ }
75
+
76
+ public async request<T>(
77
+ method: BaseApiMethods,
78
+ url: string,
79
+ query?: Record<string, unknown>
80
+ ): Promise<T> {
81
+ try {
82
+ const response = await this.directus.request<T>(() => {
83
+ const params = JSON.stringify(query);
84
+ return {
85
+ path: `${url}?${params}`,
86
+ method: method
87
+ };
88
+ });
89
+ return response;
90
+ } catch (error) {
91
+ console.error(`Error request:`, error);
92
+ throw error;
93
+ }
94
+ }
95
+
96
+ public async find<T>(collection: Path, query?: Record<string, unknown>): Promise<ApiResponse<T>> {
97
+ const response = await this.directus.request<T>(readItems(collection, query));
98
+ return this.transformResponse(response);
99
+ }
100
+
101
+ public async findOne<T>(
102
+ collection: Path,
103
+ key?: ApiId,
104
+ query?: Record<string, unknown>
105
+ ): Promise<ApiResponse<T>> {
106
+ const response = await this.directus.request<T>(readItem(collection, key, query));
107
+ return this.transformResponse(response);
108
+ }
109
+
110
+ public async aggregate<T>(
111
+ collection: Path,
112
+ query?: Record<string, unknown>
113
+ ): Promise<ApiResponse<T>> {
114
+ const response = await this.directus.request<T>(
115
+ aggregate(collection, {
116
+ aggregate: {
117
+ count: 'id'
118
+ },
119
+ query
120
+ })
121
+ );
122
+ return this.transformResponse(response);
123
+ }
124
+
125
+ public async patch<T>(
126
+ collection: Path,
127
+ key: ApiId,
128
+ query?: Record<string, unknown>
129
+ ): Promise<ApiResponse<T>> {
130
+ const response = await this.directus.request<T>(updateItem(collection, key, query));
131
+ return this.transformResponse(response);
132
+ }
133
+
134
+ public async post<T>(
135
+ collection: Path,
136
+ data: AnyObject,
137
+ query?: Record<string, unknown>
138
+ ): Promise<ApiResponse<T>> {
139
+ const response = await this.directus.request<T>(createItem(collection, data, query));
140
+ return this.transformResponse(response, 201);
141
+ }
142
+
143
+ public async delete<T>(collection: Path, key?: ApiId): Promise<ApiResponse<T>> {
144
+ const response = await this.directus.request<T>(deleteItem(collection, key));
145
+ return this.transformResponse(response, 202);
146
+ }
147
+
148
+ public async put<T>(
149
+ collection: Path,
150
+ key?: ApiId,
151
+ payload?: AnyObject,
152
+ config?: ApiAdapterRequestConfig
153
+ ): Promise<ApiResponse<T>> {
154
+ if (key) {
155
+ const response = await this.directus.request<T>(updateItem(collection, key, payload));
156
+ return this.transformResponse(response, 201);
157
+ } else {
158
+ console.error(`Error updating all ${collection}: no key specified`);
159
+ throw new Error('No key specified');
160
+ }
161
+ }
162
+
163
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
164
+ public async upload<T>(path: string = '', data: FormData): Promise<ApiResponse<T>> {
165
+ const response = await this.directus.request<T>(uploadFiles(data));
166
+ return this.transformResponse(response, 201);
167
+ }
168
+ }
@@ -1,70 +1,15 @@
1
- import type { AuthenticationClient, AuthenticationConfig, AuthenticationData } from '@directus/sdk';
2
- import {
3
- authentication,
4
- createDirectus,
5
- readMe,
6
- refresh,
7
- rest,
8
- updateMe,
9
- memoryStorage
10
- } from '@directus/sdk';
11
-
1
+ import type { AuthenticationClient, AuthenticationConfig } from '@directus/sdk';
2
+ import { authentication, createDirectus, readMe, refresh, rest, updateMe } from '@directus/sdk';
12
3
  import type { DirectusClient, RestClient } from '@directus/sdk';
13
-
14
- import { BROWSER } from 'esm-env';
15
-
16
- import cookie from 'js-cookie';
17
-
18
- const localDirectusStorage = (storageKey: string = 'access_token_directus') => {
19
- if (!BROWSER || !window.localStorage) {
20
- console.warn('Defaulting to memory storage');
21
- return memoryStorage();
22
- }
23
-
24
- const storage = window.localStorage;
25
-
26
- return {
27
- get: async (): Promise<AuthenticationData | null> => {
28
- const data = storage.getItem(storageKey);
29
- return data ? (JSON.parse(data) as AuthenticationData) : null;
30
- },
31
- set: async (value: AuthenticationData | null): Promise<void> => {
32
- if (value === null) {
33
- storage.removeItem(storageKey);
34
- } else {
35
- storage.setItem(storageKey, JSON.stringify(value));
36
- }
37
- }
38
- };
39
- };
40
-
41
- // const cookieDirectusStorage = (cookieKey: string = 'access_token_directus') => {
42
- // return {
43
- // get: async (): Promise<AuthenticationData | null> => {
44
- // const data = JSON.parse(cookie.get(cookieKey)) || '{}';
45
- // return data ? (data as AuthenticationData) : null;
46
-
47
- // },
48
- // set: async (value: AuthenticationData | null): Promise<void> => {
49
- // cookie.set(cookieKey, JSON.stringify(value))
50
- // }
51
- // };
52
- // }
4
+ import { AuthLocalStorage } from './storage/local-storage';
53
5
 
54
6
  const authenticationConfig: AuthenticationConfig = {
55
- storage: localDirectusStorage(),
7
+ storage: new AuthLocalStorage(),
56
8
  autoRefresh: true,
57
9
  msRefreshBeforeExpires: 30000,
58
10
  credentials: 'include'
59
11
  };
60
12
 
61
- // const authenticationCookieConfig: AuthenticationConfig = {
62
- // storage: cookieDirectusStorage(),
63
- // autoRefresh: true,
64
- // msRefreshBeforeExpires: 30000,
65
- // credentials: 'include'
66
- // };
67
-
68
13
  class ApiAuthDirectus {
69
14
  private baseURL: string;
70
15
  private storageMode: 'json' | 'cookie';
@@ -78,14 +23,14 @@ class ApiAuthDirectus {
78
23
 
79
24
  private init<T extends object>(): void {
80
25
  try {
81
- if(this.storageMode === 'json'){
26
+ if (this.storageMode === 'json') {
82
27
  this.directus = createDirectus<T>(this.baseURL)
83
- .with(rest({ credentials: 'include' }))
84
- .with(authentication('json', authenticationConfig));
85
- }else {
28
+ .with(rest({ credentials: 'include' }))
29
+ .with(authentication('json', authenticationConfig));
30
+ } else {
86
31
  this.directus = createDirectus<T>(this.baseURL)
87
- .with(authentication('cookie', { credentials: 'include' }))
88
- .with(rest({ credentials: 'include' }));
32
+ .with(authentication('cookie', { credentials: 'include' }))
33
+ .with(rest({ credentials: 'include' }));
89
34
  }
90
35
  } catch (error) {
91
36
  console.error(`Error initializing Directus:`, error);
@@ -1,47 +1,59 @@
1
+ import type { AuthenticationConfig, DirectusClient, RestClient } from '@directus/sdk';
1
2
  import {
2
3
  aggregate,
4
+ authentication,
3
5
  createDirectus,
4
6
  createItem,
5
- createUser,
6
7
  deleteItem,
7
8
  readItem,
8
9
  readItems,
9
10
  rest,
10
- staticToken,
11
11
  updateItem,
12
- updateItems,
13
12
  uploadFiles
14
13
  } from '@directus/sdk';
15
- import type { DirectusClient, RestClient, StaticTokenClient } from '@directus/sdk';
16
14
  import type {
17
15
  AnyObject,
18
16
  ApiAdapterInterface,
19
17
  ApiAdapterRequestConfig,
20
18
  BaseApiAdapterConfig
21
19
  } from '@tanglemedia/svelte-starter-core';
20
+ import { AuthLocalStorage } from './storage/local-storage';
21
+
22
+ const authenticationConfig: AuthenticationConfig = {
23
+ storage: new AuthLocalStorage(),
24
+ autoRefresh: true,
25
+ msRefreshBeforeExpires: 30000,
26
+ credentials: 'include'
27
+ };
22
28
 
23
29
  type BaseApiMethods = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
24
30
 
25
31
  type ApiId = string | number;
26
32
 
27
- class ApiStaticDirectus implements ApiAdapterInterface {
33
+ class ApiClientDirectus implements ApiAdapterInterface {
28
34
  private baseURL: string;
29
- private directusAccessToken: string;
30
- private directus: DirectusClient<AnyObject> & RestClient<object> & StaticTokenClient<object>;
35
+ private storageMode: 'json' | 'cookie';
36
+ private directus: DirectusClient<object> & RestClient<object>;
31
37
 
32
- constructor(baseURL: string, directusAccessToken: string) {
38
+ constructor(baseURL: string, storageMode: 'json' | 'cookie' = 'json') {
33
39
  this.baseURL = baseURL;
34
- this.directusAccessToken = directusAccessToken;
40
+ this.storageMode = storageMode;
35
41
  this.init();
36
42
  }
37
43
 
38
44
  private init<T extends object>(): void {
39
45
  try {
40
- this.directus = createDirectus<T>(this.baseURL)
41
- .with(rest())
42
- .with(staticToken(this.directusAccessToken));
46
+ if (this.storageMode === 'json') {
47
+ this.directus = createDirectus<T>(this.baseURL)
48
+ .with(rest({ credentials: 'include' }))
49
+ .with(authentication('json', authenticationConfig));
50
+ } else {
51
+ this.directus = createDirectus<T>(this.baseURL)
52
+ .with(authentication('cookie', { credentials: 'include' }))
53
+ .with(rest({ credentials: 'include' }));
54
+ }
43
55
  } catch (error) {
44
- console.error(`Error initializing Directus admin:`, error);
56
+ console.error(`Error initializing Directus:`, error);
45
57
  throw error;
46
58
  }
47
59
  }
@@ -78,23 +90,10 @@ class ApiStaticDirectus implements ApiAdapterInterface {
78
90
  }
79
91
  }
80
92
 
81
- public async createUser(
82
- data:
83
- | { email: string; password: string; first_name: string; last_name: string; role: string }
84
- | object
85
- ): Promise<{ message: string; type: string }> {
86
- try {
87
- await this.directus.request(createUser(data));
88
-
89
- return { message: 'You have successfully registered your account', type: 'success' };
90
- } catch (error) {
91
- console.error(`Error creating a user:`, error);
92
- throw error;
93
- }
94
- }
95
-
96
93
  public async find<T>(collection: string, query?: Record<string, unknown>): Promise<T> {
94
+ // console.log('in find');
97
95
  try {
96
+ // console.log(`Find ${collection}`)
98
97
  const response = await this.directus.request<T>(readItems(collection, query));
99
98
  return response;
100
99
  } catch (error) {
@@ -105,7 +104,7 @@ class ApiStaticDirectus implements ApiAdapterInterface {
105
104
 
106
105
  public async findOne<T>(
107
106
  collection: string,
108
- key: ApiId,
107
+ key?: ApiId,
109
108
  query?: Record<string, unknown>
110
109
  ): Promise<T> {
111
110
  try {
@@ -140,7 +139,7 @@ class ApiStaticDirectus implements ApiAdapterInterface {
140
139
  query?: Record<string, unknown>
141
140
  ): Promise<T> {
142
141
  try {
143
- const response = await this.directus.request<T>(updateItems(collection, key, query));
142
+ const response = await this.directus.request<T>(updateItem(collection, key, query));
144
143
  return response;
145
144
  } catch (error) {
146
145
  console.error(`Error updating all ${collection}:`, error);
@@ -162,8 +161,7 @@ class ApiStaticDirectus implements ApiAdapterInterface {
162
161
  }
163
162
  }
164
163
 
165
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
166
- public async delete<T>(collection: string, keys: ApiId): Promise<T> {
164
+ public async delete<T>(collection: string, key?: ApiId): Promise<T> {
167
165
  try {
168
166
  const response = await this.directus.request<T>(deleteItem(collection, key));
169
167
  return response;
@@ -205,4 +203,4 @@ class ApiStaticDirectus implements ApiAdapterInterface {
205
203
  }
206
204
  }
207
205
 
208
- export { ApiStaticDirectus };
206
+ export { ApiClientDirectus };
package/src/index.ts CHANGED
@@ -1,4 +1,12 @@
1
- export * from './static';
2
- export * from './client';
3
- export * from './auth';
4
- export * from './load-directus-api-povider';
1
+ export * from './static.deprecated';
2
+ export * from './client.deprecated';
3
+ export * from './auth.deprecated';
4
+ export * from './load-directus-api-povider.deprecated';
5
+
6
+ export * from './provider/api-adapter.provider';
7
+ export * from './provider/directus.factory';
8
+
9
+ export * from './services/auth';
10
+ export * from './services/register';
11
+
12
+ export type * from './types';
@@ -1,5 +1,6 @@
1
- import { ApiClientDirectus } from './client';
2
- import { ApiStaticDirectus } from './static';
1
+ import { ApiClientDirectus } from './client.deprecated';
2
+ import { ApiStaticDirectus } from './static.deprecated';
3
+ import { ApiAuthDirectus } from './auth.deprecated';
3
4
  import {
4
5
  type ApiAdapterProviderInterface,
5
6
  type ApiAdapterInterface,
@@ -10,43 +11,49 @@ import {
10
11
  } from '@tanglemedia/svelte-starter-core';
11
12
 
12
13
  class LoadDirectusApiProvider implements ApiAdapterProviderInterface {
13
- constructor(private readonly configLoader: () => Promise<Config<{ api?: ApiConfigSchema }>>, private storageMode: 'json' | 'cookie' = 'json') {}
14
+ constructor(
15
+ private readonly configLoader: () => Promise<Config<{ api?: ApiConfigSchema }>>,
16
+ private storageMode: 'json' | 'cookie' = 'json',
17
+ private key?: string | undefined
18
+ ) {}
14
19
 
15
- async loadAdapter(
16
- key?: string | undefined
17
- ): Promise<ApiAdapterInterface<BaseApiAdapterConfig, ApiAdapterRequestConfig, string>> {
20
+ async loadAdapter(): Promise<
21
+ ApiAdapterInterface<BaseApiAdapterConfig, ApiAdapterRequestConfig, string>
22
+ > {
18
23
  const conf = await this.configLoader();
19
24
  const config = (p: string) => conf.config(p);
20
25
 
21
- const apiAdapterKey = key || (config('api.default') as string);
22
- const directusType = (config(`api.adapters.${apiAdapterKey}.type`) as string) || 'client';
26
+ const apiAdapterKey =
27
+ this.key === 'auth' ? 'auth' : this.key || (config('api.default') as string);
28
+ const directusType =
29
+ apiAdapterKey === 'auth'
30
+ ? this.key
31
+ : (config(`api.adapters.${apiAdapterKey}.type`) as string) || 'client';
23
32
  console.log(`api.apaters.${apiAdapterKey}.type`);
24
33
 
25
34
  if (!apiAdapterKey) {
26
35
  throw new Error(`No adapter key specified`);
27
36
  }
28
- console.log(apiAdapterKey);
29
- console.log(directusType);
30
37
  if (directusType) {
31
38
  if (directusType === 'client') {
32
39
  const protocol: string = config(`api.adapters.${apiAdapterKey}.protocol`) || '';
33
40
  const host: string = config(`api.adapters.${apiAdapterKey}.host`) || '';
34
41
  return new ApiClientDirectus(`${protocol}://${host}`.trim(), this.storageMode);
42
+ } else if (directusType === 'auth') {
43
+ const protocol: string = config(`api.adapters.${apiAdapterKey}.protocol`) || '';
44
+ const host: string = config(`api.adapters.${apiAdapterKey}.host`) || '';
45
+ return new ApiAuthDirectus(`${protocol}://${host}`.trim(), this.storageMode);
35
46
  } else {
36
- console.log('static');
37
47
  const protocol: string = config(`api.adapters.${apiAdapterKey}.protocol`) || '';
38
48
  const host: string = config(`api.adapters.${apiAdapterKey}.host`) || '';
39
49
  const accessToken: string = config(`api.adapters.${apiAdapterKey}.access_token`) || '';
40
50
  return new ApiStaticDirectus(`${protocol}://${host}`.trim(), accessToken);
41
51
  }
42
52
  } else {
43
- console.log('client');
44
53
  const protocol: string = config(`api.adapters.${apiAdapterKey}.protocol`) || '';
45
54
  const host: string = config(`api.adapters.${apiAdapterKey}.host`) || '';
46
55
  return new ApiClientDirectus(`${protocol}://${host}`.trim(), this.storageMode);
47
56
  }
48
-
49
- console.log('This should be unreachable');
50
57
  }
51
58
  }
52
59
 
@@ -0,0 +1,35 @@
1
+ import type {
2
+ AdapterProviderRegister,
3
+ ApiAdapterInterface,
4
+ ApiAdapterProviderInterface
5
+ } from '@tanglemedia/svelte-starter-core';
6
+ import { DirectusApiAdapter } from '../adapter/api-adapter';
7
+ import type { DirectusConfig, SchemaShape } from '../types/adapter.types';
8
+ import { createDirectusClientFactory } from './directus.factory';
9
+
10
+ export class DirectusApiProvider implements ApiAdapterProviderInterface<DirectusConfig> {
11
+ async loadAdapter(
12
+ key?: string,
13
+ config?: DirectusConfig
14
+ ): Promise<ApiAdapterInterface<DirectusConfig>> {
15
+ if (!config) {
16
+ throw new Error('Missing adapter configuration');
17
+ }
18
+
19
+ const client = this.createDirectusClient<SchemaShape>(config);
20
+
21
+ return new DirectusApiAdapter(config, client);
22
+ }
23
+
24
+ createDirectusClient<T extends object>(config: DirectusConfig) {
25
+ // todo: Determine if we can overwrite the fetch globals during runtime
26
+ return createDirectusClientFactory<T>(config);
27
+ }
28
+ }
29
+
30
+ export const registerDirectusProvider = (): AdapterProviderRegister => {
31
+ return {
32
+ name: 'directus',
33
+ provider: new DirectusApiProvider()
34
+ };
35
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ authentication,
3
+ createDirectus,
4
+ graphql,
5
+ rest,
6
+ staticToken,
7
+ type AuthenticationConfig,
8
+ type ClientOptions
9
+ } from '@directus/sdk';
10
+ import { AuthLocalStorage } from '../storage/local-storage';
11
+ import type { DirectusConfig } from '../types/adapter.types';
12
+
13
+ const authConfigDefaults = {
14
+ autoRefresh: false,
15
+ msRefreshBeforeExpires: 0,
16
+ credentials: 'include' as const
17
+ };
18
+
19
+ /**
20
+ * Creates a directus client based on the application configuration
21
+ */
22
+ export const createDirectusClientFactory = <T extends object>(
23
+ {
24
+ baseUrl,
25
+ configuration: { protocol = 'https', host, auth, staticToken: token, graphql: gql, rest: rs }
26
+ }: DirectusConfig,
27
+ options?: ClientOptions
28
+ ) => {
29
+ let url = baseUrl;
30
+
31
+ if (host) {
32
+ url = `${protocol}://${host}`;
33
+ }
34
+
35
+ if (!url) {
36
+ throw new Error('Unable to resolve base url for directus client');
37
+ }
38
+
39
+ // if there is going to be authentication and no rest config has been specified.
40
+ // set the correct defaults
41
+ if (!rs && auth) {
42
+ rs = { credentials: 'include' };
43
+ }
44
+
45
+ let client = createDirectus<T>(url, options).with(rest(rs));
46
+
47
+ if (auth) {
48
+ if (auth.config?.storage === 'localStorage') {
49
+ const authenticationConfig: AuthenticationConfig = {
50
+ storage: new AuthLocalStorage(),
51
+ autoRefresh: auth.config.autoRefresh || false,
52
+ msRefreshBeforeExpires: auth.config.msRefreshBeforeExpires || 0,
53
+ credentials: auth.config.credentials || 'include'
54
+ };
55
+ client = client.with(authentication(auth.mode, authenticationConfig));
56
+ } else {
57
+ client = client.with(authentication(auth.mode));
58
+ }
59
+ }
60
+
61
+ if (token) {
62
+ client = client.with(staticToken(token));
63
+ }
64
+
65
+ if (gql) {
66
+ client = client.with(graphql(gql));
67
+ }
68
+
69
+ return client;
70
+ };