@meeovi/directus-client 1.0.1 → 1.0.2
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/dist/client/createClient.d.ts +3 -2
- package/dist/client/createClient.js +1 -1
- package/dist/generators/form-engine.d.ts +11 -13
- package/dist/generators/form-engine.js +20 -61
- package/dist/generators/widget-registry.d.ts +9 -17
- package/dist/generators/widget-registry.js +50 -3
- package/package.json +1 -1
- package/src/client/createClient.ts +5 -4
- package/src/generators/form-engine.ts +4 -14
- package/tsconfig.json +3 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readItem, readItems, createItem, updateItem, deleteItem, uploadFiles, readSingleton, readFieldsByCollection, type DirectusClient } from '@directus/sdk';
|
|
2
2
|
export interface MeeoviDirectusClient<Schema> {
|
|
3
|
-
client:
|
|
3
|
+
client: DirectusClient<Schema>;
|
|
4
|
+
request: any;
|
|
4
5
|
readItem: typeof readItem;
|
|
5
6
|
readItems: typeof readItems;
|
|
6
7
|
createItem: typeof createItem;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/client/createClient.ts
|
|
2
1
|
import { createDirectus, rest, authentication, readItem, readItems, createItem, updateItem, deleteItem, uploadFiles, readSingleton, readFieldsByCollection } from '@directus/sdk';
|
|
3
2
|
export function createMeeoviDirectusClient(url) {
|
|
4
3
|
const client = createDirectus(url)
|
|
@@ -6,6 +5,7 @@ export function createMeeoviDirectusClient(url) {
|
|
|
6
5
|
.with(authentication());
|
|
7
6
|
return {
|
|
8
7
|
client,
|
|
8
|
+
request: client.request,
|
|
9
9
|
readItem,
|
|
10
10
|
readItems,
|
|
11
11
|
createItem,
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import type { DirectusField } from '../schema/types';
|
|
2
|
-
export interface
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export interface GeneratedFormField {
|
|
3
|
+
key: string;
|
|
4
|
+
widget: string;
|
|
5
|
+
type: string;
|
|
6
|
+
options?: Record<string, any>;
|
|
7
|
+
fields?: GeneratedFormField[];
|
|
8
|
+
isRepeatable?: boolean;
|
|
9
|
+
isFile?: boolean;
|
|
10
|
+
isRelational?: boolean;
|
|
6
11
|
}
|
|
7
|
-
export declare function
|
|
8
|
-
|
|
9
|
-
submit: () => Promise<{
|
|
10
|
-
error: string | null;
|
|
11
|
-
success: string | null;
|
|
12
|
-
}>;
|
|
13
|
-
readonly error: string | null;
|
|
14
|
-
readonly success: string | null;
|
|
15
|
-
};
|
|
12
|
+
export declare function generateFormField(field: DirectusField): GeneratedFormField;
|
|
13
|
+
export declare function generateFormSchema(fields: DirectusField[]): GeneratedFormField[];
|
|
@@ -1,63 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const validation = meta.validation;
|
|
13
|
-
if (validation._and) {
|
|
14
|
-
for (const rule of validation._and) {
|
|
15
|
-
const fieldName = Object.keys(rule)[0];
|
|
16
|
-
if (!fieldName)
|
|
17
|
-
continue;
|
|
18
|
-
const ruleDef = rule[fieldName];
|
|
19
|
-
if (ruleDef?._regex) {
|
|
20
|
-
const regex = new RegExp(ruleDef._regex);
|
|
21
|
-
const value = String(form[field.field] ?? '');
|
|
22
|
-
if (!regex.test(value)) {
|
|
23
|
-
error = meta.validation_message || `${field.field} failed validation`;
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
error = `Validation error for ${field.field}`;
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
};
|
|
37
|
-
const submit = async () => {
|
|
38
|
-
if (!validate())
|
|
39
|
-
return { error, success };
|
|
40
|
-
const result = await directusClient.request(directusClient.createItem(collectionName, form));
|
|
41
|
-
if (result?.error) {
|
|
42
|
-
error = result.error.message;
|
|
43
|
-
return { error, success };
|
|
44
|
-
}
|
|
45
|
-
success = `${collectionName} created successfully`;
|
|
46
|
-
if (opts?.clearOnSuccess) {
|
|
47
|
-
for (const key of Object.keys(form))
|
|
48
|
-
delete form[key];
|
|
49
|
-
}
|
|
50
|
-
opts?.onSuccess?.();
|
|
51
|
-
return { error, success };
|
|
52
|
-
};
|
|
53
|
-
return {
|
|
54
|
-
form,
|
|
55
|
-
submit,
|
|
56
|
-
get error() {
|
|
57
|
-
return error;
|
|
58
|
-
},
|
|
59
|
-
get success() {
|
|
60
|
-
return success;
|
|
61
|
-
}
|
|
1
|
+
import { widgetRegistry } from './widget-registry';
|
|
2
|
+
export function generateFormField(field) {
|
|
3
|
+
const widget = widgetRegistry[field.interface || 'input'];
|
|
4
|
+
const base = {
|
|
5
|
+
key: field.field,
|
|
6
|
+
widget: widget.component,
|
|
7
|
+
type: field.type,
|
|
8
|
+
options: field.options || {},
|
|
9
|
+
isRepeatable: widget.isRepeatable,
|
|
10
|
+
isFile: widget.isFile,
|
|
11
|
+
isRelational: widget.isRelational
|
|
62
12
|
};
|
|
13
|
+
if ((field.interface === 'repeater' || field.interface === 'group') && field.options?.fields) {
|
|
14
|
+
base.fields = field.options.fields.map((sub) => generateFormField(sub));
|
|
15
|
+
}
|
|
16
|
+
return base;
|
|
17
|
+
}
|
|
18
|
+
export function generateFormSchema(fields) {
|
|
19
|
+
return fields
|
|
20
|
+
.filter(f => f.interface !== 'presentation' && f.interface !== 'divider')
|
|
21
|
+
.map(generateFormField);
|
|
63
22
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
date: {
|
|
12
|
-
component: string;
|
|
13
|
-
};
|
|
14
|
-
json: {
|
|
15
|
-
component: string;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
1
|
+
export interface WidgetDefinition {
|
|
2
|
+
component: string;
|
|
3
|
+
props?: Record<string, any>;
|
|
4
|
+
isRepeatable?: boolean;
|
|
5
|
+
isRelational?: boolean;
|
|
6
|
+
isFile?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const widgetRegistry: Record<string, WidgetDefinition>;
|
|
9
|
+
export declare function extendWidgetRegistryFromDirectus(client: any): Promise<void>;
|
|
@@ -1,7 +1,54 @@
|
|
|
1
|
+
import { readItems } from "@directus/sdk";
|
|
1
2
|
export const widgetRegistry = {
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
// Basic inputs
|
|
4
|
+
input: { component: 'TextInput' },
|
|
5
|
+
textarea: { component: 'TextareaInput' },
|
|
6
|
+
boolean: { component: 'ToggleInput' },
|
|
7
|
+
slider: { component: 'SliderInput' },
|
|
8
|
+
color: { component: 'ColorPicker' },
|
|
9
|
+
rating: { component: 'RatingInput' },
|
|
10
|
+
// Selects
|
|
11
|
+
'select-dropdown': { component: 'SelectInput' },
|
|
12
|
+
'select-multiple-dropdown': { component: 'MultiSelectInput' },
|
|
13
|
+
tags: { component: 'TagInput' },
|
|
4
14
|
checkbox: { component: 'CheckboxInput' },
|
|
15
|
+
radio: { component: 'RadioInput' },
|
|
16
|
+
// Date/time
|
|
17
|
+
datetime: { component: 'DateTimeInput' },
|
|
5
18
|
date: { component: 'DateInput' },
|
|
6
|
-
|
|
19
|
+
time: { component: 'TimeInput' },
|
|
20
|
+
// Files
|
|
21
|
+
file: { component: 'FileInput', isFile: true },
|
|
22
|
+
files: { component: 'FilesInput', isFile: true },
|
|
23
|
+
image: { component: 'ImageInput', isFile: true },
|
|
24
|
+
images: { component: 'ImagesInput', isFile: true },
|
|
25
|
+
// Complex
|
|
26
|
+
repeater: { component: 'RepeaterInput', isRepeatable: true },
|
|
27
|
+
group: { component: 'GroupInput' },
|
|
28
|
+
json: { component: 'JsonEditor' },
|
|
29
|
+
code: { component: 'CodeEditor' },
|
|
30
|
+
wysiwyg: { component: 'WysiwygEditor' },
|
|
31
|
+
markdown: { component: 'MarkdownEditor' },
|
|
32
|
+
// Directus-specific
|
|
33
|
+
icon: { component: 'IconPicker' },
|
|
34
|
+
user: { component: 'UserSelect' },
|
|
35
|
+
role: { component: 'RoleSelect' },
|
|
36
|
+
translation: { component: 'TranslationInput' },
|
|
37
|
+
// Presentation (ignored in forms)
|
|
38
|
+
presentation: { component: 'PresentationBlock' },
|
|
39
|
+
divider: { component: 'DividerBlock' }
|
|
7
40
|
};
|
|
41
|
+
export async function extendWidgetRegistryFromDirectus(client) {
|
|
42
|
+
const extensions = await client.request(readItems('directus_extensions'));
|
|
43
|
+
for (const ext of extensions) {
|
|
44
|
+
if (ext.type !== 'interface')
|
|
45
|
+
continue;
|
|
46
|
+
const name = ext.name;
|
|
47
|
+
if (!widgetRegistry[name]) {
|
|
48
|
+
widgetRegistry[name] = {
|
|
49
|
+
component: 'CustomInterfaceRenderer',
|
|
50
|
+
props: { interfaceName: name }
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meeovi/directus-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Directus Client Library with auto generating forms and tables, Directus SDK and Types, and vue/react components for Directus Visual Editing.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// src/client/createClient.ts
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
createDirectus,
|
|
5
3
|
rest,
|
|
@@ -11,11 +9,13 @@ import {
|
|
|
11
9
|
deleteItem,
|
|
12
10
|
uploadFiles,
|
|
13
11
|
readSingleton,
|
|
14
|
-
readFieldsByCollection
|
|
12
|
+
readFieldsByCollection,
|
|
13
|
+
type DirectusClient
|
|
15
14
|
} from '@directus/sdk';
|
|
16
15
|
|
|
17
16
|
export interface MeeoviDirectusClient<Schema> {
|
|
18
|
-
client:
|
|
17
|
+
client: DirectusClient<Schema>;
|
|
18
|
+
request: any;
|
|
19
19
|
readItem: typeof readItem;
|
|
20
20
|
readItems: typeof readItems;
|
|
21
21
|
createItem: typeof createItem;
|
|
@@ -33,6 +33,7 @@ export function createMeeoviDirectusClient<Schema>(url: string): MeeoviDirectusC
|
|
|
33
33
|
|
|
34
34
|
return {
|
|
35
35
|
client,
|
|
36
|
+
request: client.request,
|
|
36
37
|
readItem,
|
|
37
38
|
readItems,
|
|
38
39
|
createItem,
|
|
@@ -6,7 +6,7 @@ export interface GeneratedFormField {
|
|
|
6
6
|
widget: string;
|
|
7
7
|
type: string;
|
|
8
8
|
options?: Record<string, any>;
|
|
9
|
-
fields?: GeneratedFormField[];
|
|
9
|
+
fields?: GeneratedFormField[];
|
|
10
10
|
isRepeatable?: boolean;
|
|
11
11
|
isFile?: boolean;
|
|
12
12
|
isRelational?: boolean;
|
|
@@ -25,24 +25,14 @@ export function generateFormField(field: DirectusField): GeneratedFormField {
|
|
|
25
25
|
isRelational: widget.isRelational
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
base.fields = field.options.fields.map((sub: any) =>
|
|
31
|
-
generateFormField(sub)
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Handle group
|
|
36
|
-
if (field.interface === 'group' && field.options?.fields) {
|
|
37
|
-
base.fields = field.options.fields.map((sub: any) =>
|
|
38
|
-
generateFormField(sub)
|
|
39
|
-
);
|
|
28
|
+
if ((field.interface === 'repeater' || field.interface === 'group') && field.options?.fields) {
|
|
29
|
+
base.fields = field.options.fields.map((sub: any) => generateFormField(sub));
|
|
40
30
|
}
|
|
41
31
|
|
|
42
32
|
return base;
|
|
43
33
|
}
|
|
44
34
|
|
|
45
|
-
export function generateFormSchema(fields: DirectusField[]) {
|
|
35
|
+
export function generateFormSchema(fields: DirectusField[]): GeneratedFormField[] {
|
|
46
36
|
return fields
|
|
47
37
|
.filter(f => f.interface !== 'presentation' && f.interface !== 'divider')
|
|
48
38
|
.map(generateFormField);
|