Skip to content

Commit 988e707

Browse files
authored
Merge pull request #17 from devforth/add-zod-schemas
Add zod schemas
2 parents ccbe3ed + bcfc83d commit 988e707

3 files changed

Lines changed: 56 additions & 21 deletions

File tree

index.ts

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1-
import AdminForth, { AdminForthPlugin, Filters, suggestIfTypo, AdminForthDataTypes, RAMLock, filtersTools, AdminForthFilterOperators } from "adminforth";
1+
import AdminForth, { AdminForthPlugin, parseBody, Filters, suggestIfTypo, AdminForthDataTypes, RAMLock, filtersTools, AdminForthFilterOperators } from "adminforth";
22
import type { IAdminForth, IHttpServer, AdminForthComponentDeclaration, AdminForthResourceColumn, AdminForthResource, BeforeLoginConfirmationFunction, AdminForthConfigMenuItem, AdminUser } from "adminforth";
33
import type { PluginOptions, SupportedLanguage } from './types.js';
4+
import { z } from "zod";
45
import iso6391 from 'iso-639-1';
6+
7+
const updateFieldBodySchema = z.object({
8+
resourceId: z.string(),
9+
recordId: z.union([z.string(), z.number()]),
10+
field: z.string(),
11+
value: z.unknown(),
12+
reviewed: z.boolean().nullish(),
13+
}).strict();
14+
15+
const translateSelectedBodySchema = z.object({
16+
selectedLanguages: z.array(z.string()).optional(),
17+
selectedIds: z.array(z.union([z.string(), z.number()])),
18+
}).strict();
19+
20+
const getFilteredIdsBodySchema = z.object({
21+
filters: z.any(),
22+
}).passthrough();
523
import { iso31661Alpha2ToAlpha3 } from 'iso-3166';
624
import path from 'path';
725
import fs from 'fs-extra';
@@ -1252,8 +1270,11 @@ export default class I18nPlugin extends AdminForthPlugin {
12521270
server.endpoint({
12531271
method: 'POST',
12541272
path: `/plugin/${this.pluginInstanceId}/update-field`,
1255-
handler: async ({ body, adminUser, headers }) => {
1256-
const { resourceId, recordId, field, value, reviewed } = body;
1273+
handler: async ({ body, adminUser, headers, response }) => {
1274+
const parsed = parseBody(updateFieldBodySchema, body, response);
1275+
if ('error' in parsed) return parsed.error;
1276+
const data = parsed.data;
1277+
const { resourceId, recordId, field, value, reviewed } = data;
12571278
if (resourceId !== this.resourceConfig.resourceId) {
12581279
return { error: 'Invalid resourceId' };
12591280
}
@@ -1274,7 +1295,7 @@ export default class I18nPlugin extends AdminForthPlugin {
12741295
let result;
12751296
await lock.run(`edit-trans-${recordId}`, async () => {
12761297
// put into lock so 2 editors will not update the same record at the same time
1277-
oldRecord = await connector.getRecordByPrimaryKey(resource, recordId)
1298+
oldRecord = await connector.getRecordByPrimaryKey(resource, recordId as string)
12781299

12791300
if (!oldRecord) {
12801301
result = { error: 'Record not found' };
@@ -1305,7 +1326,7 @@ export default class I18nPlugin extends AdminForthPlugin {
13051326
return { error: result.error };
13061327
}
13071328

1308-
const updatedRecord = await connector.getRecordByPrimaryKey(resource, recordId);
1329+
const updatedRecord = await connector.getRecordByPrimaryKey(resource, recordId as string);
13091330

13101331
return { record: updatedRecord };
13111332
}
@@ -1315,15 +1336,22 @@ export default class I18nPlugin extends AdminForthPlugin {
13151336
method: 'POST',
13161337
path: `/plugin/${this.pluginInstanceId}/translate-selected-to-languages`,
13171338
noAuth: false,
1318-
handler: async ({ body, tr, adminUser }) => {
1319-
const selectedLanguages = body.selectedLanguages;
1320-
const selectedIds = body.selectedIds;
1339+
handler: async ({ body, tr, adminUser, response }) => {
1340+
const parsed = parseBody(translateSelectedBodySchema, body, response);
1341+
if ('error' in parsed) return parsed.error;
1342+
const data = parsed.data;
1343+
const selectedLanguages = data.selectedLanguages;
1344+
const selectedIds = data.selectedIds;
13211345

13221346
if (!Array.isArray(selectedIds) || selectedIds.length === 0) {
13231347
return { ok: false, error: 'No records selected' };
13241348
}
13251349

1326-
const jobId = await this.bulkTranslate({ selectedIds, selectedLanguages, adminUser });
1350+
const jobId = await this.bulkTranslate({
1351+
selectedIds: selectedIds as string[],
1352+
selectedLanguages: selectedLanguages as SupportedLanguage[] | undefined,
1353+
adminUser,
1354+
});
13271355

13281356
return {
13291357
ok: true,
@@ -1335,7 +1363,10 @@ export default class I18nPlugin extends AdminForthPlugin {
13351363
server.endpoint({
13361364
method: 'POST',
13371365
path: `/plugin/${this.pluginInstanceId}/get_filtered_ids`,
1338-
handler: async ({ body, adminUser, headers, query, cookies, requestUrl }) => {
1366+
handler: async ({ body, adminUser, headers, query, cookies, requestUrl, response }) => {
1367+
const parsed = parseBody(getFilteredIdsBodySchema, body, response);
1368+
if ('error' in parsed) return parsed.error;
1369+
const data = parsed.data;
13391370
const resource = this.resourceConfig;
13401371

13411372
for (const hook of resource.hooks?.list?.beforeDatasourceRequest || []) {

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@
3535
"fs-extra": "^11.3.2",
3636
"iso-3166": "^4.3.0",
3737
"iso-639-1": "^3.1.3",
38-
"p-limit": "^7.3.0"
38+
"p-limit": "^7.3.0",
39+
"zod": "^4.3.6"
3940
},
4041
"peerDependencies": {
41-
"adminforth": "^3.6.21"
42+
"adminforth": "^3.7.1"
4243
},
4344
"devDependencies": {
4445
"@types/node": "^22.10.7",
45-
"adminforth": "^3.6.21",
46+
"adminforth": "^3.7.1",
4647
"i18n-iso-countries": "^7.13.0",
4748
"semantic-release": "^24.2.1",
4849
"semantic-release-slack-bot": "^4.0.2",

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)