Skip to content

Commit 857e8a4

Browse files
committed
feat: add backend validation of json field
AdminForth/1797/implement-jsonformplugin-using
1 parent 191a6c4 commit 857e8a4

3 files changed

Lines changed: 145 additions & 72 deletions

File tree

index.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AdminForthPlugin, AdminForthDataTypes } from "adminforth";
22
import type { IAdminForth, AdminForthResource } from "adminforth";
33
import type { PluginOptions } from './types.js';
4+
import Validator from 'jsonschema';
45

56
export default class JsonFormPlugin extends AdminForthPlugin {
67
options: PluginOptions;
@@ -61,5 +62,58 @@ export default class JsonFormPlugin extends AdminForthPlugin {
6162

6263
column.components.create = formComponent;
6364
column.components.edit = formComponent;
65+
66+
if (!resourceConfig.hooks) {
67+
resourceConfig.hooks = {};
68+
}
69+
if (!resourceConfig.hooks.create) {
70+
resourceConfig.hooks.create = {};
71+
}
72+
if (!resourceConfig.hooks.edit) {
73+
resourceConfig.hooks.edit = {};
74+
}
75+
76+
const pushHook = (hooks: { beforeSave?: any }, fn: any) => {
77+
if (Array.isArray(hooks.beforeSave)) {
78+
hooks.beforeSave.push(fn);
79+
} else if (hooks.beforeSave) {
80+
hooks.beforeSave = [hooks.beforeSave, fn];
81+
} else {
82+
hooks.beforeSave = [fn];
83+
}
84+
};
85+
86+
pushHook(resourceConfig.hooks.create, async ({ record }: { record: any }) => {
87+
return this.validateRecord(record);
88+
});
89+
pushHook(resourceConfig.hooks.edit, async ({ updates }: { updates: any }) => {
90+
if (!(this.options.fieldName in updates)) {
91+
return { ok: true };
92+
}
93+
return this.validateRecord(updates);
94+
});
95+
}
96+
97+
validateRecord(record: any): { ok: boolean; error?: string } {
98+
const value = record?.[this.options.fieldName];
99+
100+
if (value === undefined || value === null) {
101+
return { ok: true };
102+
}
103+
104+
const validator = new Validator.Validator();
105+
const result = validator.validate(value, this.options.schema, { nestedErrors: true });
106+
107+
if (!result.valid) {
108+
const message = result.errors
109+
.map((e) => `${e.property.replace(/^instance/, this.options.fieldName)} ${e.message}`)
110+
.join('; ');
111+
return {
112+
ok: false,
113+
error: `[JsonForm] Invalid value for "${this.options.fieldName}": ${message}`,
114+
};
115+
}
116+
117+
return { ok: true };
64118
}
65119
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,8 @@
5959
"prerelease": true
6060
}
6161
]
62+
},
63+
"dependencies": {
64+
"jsonschema": "^1.5.0"
6265
}
6366
}

pnpm-lock.yaml

Lines changed: 88 additions & 72 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)