Skip to content

Commit 8c8dfb3

Browse files
committed
Merge branch 'main' of github.com:devforth/adminforth
2 parents 186b93a + a8e1bd0 commit 8c8dfb3

21 files changed

Lines changed: 358 additions & 134 deletions

File tree

adminforth/dataConnectors/baseConnector.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,13 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
471471
return this.setFieldValue(field, null);
472472
}
473473
if (typeof value !== 'boolean') {
474-
throw new Error(`Value is not a boolean. Field ${field.name} with type is ${field.type}, but got value: ${value} with type ${typeof value}`);
474+
const errorMessage = `Value is not a boolean. Field ${field.name} with type is ${field.type}, but got value: ${value} with type ${typeof value}`;
475+
if (value !== 1 && value !== 0) {
476+
throw new Error(errorMessage);
477+
} else {
478+
afLogger.warn(errorMessage);
479+
afLogger.warn(`Ignore this warn, if you are using an sqlite database`);
480+
}
475481
}
476482
return this.setFieldValue(field, value);
477483
}

adminforth/documentation/docs/tutorial/05-deploy.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ You can use it to build your AdminForth application in Docker container.
2222

2323
## Building the image
2424

25+
> Make sure that you have database url in your .env.prod file
26+
2527
Now you can build your image:
2628

2729
```bash

adminforth/documentation/docs/tutorial/08-UsageOfLogger.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,27 @@ AF_LOG_SINGLE_LINE=true pnpm start
7070

7171
Accepted truthy values are `true` and `1`. When unset, logs use the default multi-line pretty format.
7272

73+
## Catching unhandled API handler errors
74+
75+
When an unhandled error is thrown inside an AdminForth API endpoint handler (built-in or custom), AdminForth logs the
76+
error and responds with `500 Internal server error`. If you also want to forward these errors somewhere — for example
77+
to report them to an external error-tracking service like [Sentry](https://sentry.io/), or to do your own custom
78+
logging — set the `expressErrorCallback` option in your AdminForth config:
79+
80+
```ts
81+
import AdminForth from 'adminforth';
82+
import * as Sentry from '@sentry/node';
83+
84+
export const admin = new AdminForth({
85+
// ...rest of your config
86+
expressErrorCallback: ({ error, extra, adminforth }) => {
87+
Sentry.captureException(error, {
88+
extra: {
89+
requestUrl: extra.requestUrl,
90+
query: extra.query,
91+
},
92+
});
93+
},
94+
});
95+
```
96+
-23.6 KB
Loading
387 KB
Loading
512 KB
Loading
42 KB
Loading
51.7 KB
Loading

adminforth/modules/codeInjector.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1252,8 +1252,18 @@ class CodeInjector implements ICodeInjector {
12521252
}
12531253
});
12541254
devServer.stderr.on('data', (data) => {
1255+
const text = data.toString();
1256+
// pnpm/npm echo the script command they are about to run (e.g. "$ vite") to stderr,
1257+
// and emit empty lines. These are not errors, so don't log them as such.
1258+
const meaningful = stripAnsiCodes(text)
1259+
.split('\n')
1260+
.filter((line: string) => line.trim() && !line.trim().startsWith('$ '));
1261+
if (meaningful.length === 0) {
1262+
process.env.HEAVY_DEBUG && console.log(`[AdminForth SPA]:`, text);
1263+
return;
1264+
}
12551265
afLogger.error(`[AdminForth SPA ERROR]:`);
1256-
afLogger.error(data.toString());
1266+
afLogger.error(text);
12571267
});
12581268

12591269
}

adminforth/modules/utils.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import crypto from 'crypto';
66
import { AdminForthConfig, AdminForthResource, AdminForthResourceColumnInputCommon,Filters, IAdminForth, Predicate } from '../index.js';
77
import { RateLimiterMemory, RateLimiterAbstract } from "rate-limiter-flexible";
88
import { PERIOD_UNITS, type PeriodString, type PeriodUnit } from '../types/Back.js';
9+
import { z } from "zod";
10+
911
// @ts-ignore-next-line
1012

1113

@@ -644,4 +646,21 @@ export function applyRegexValidation(value, validation) {
644646
${horizontal}
645647
${RESET}
646648
`;
647-
}
649+
}
650+
651+
652+
export function parseBody<T>(
653+
schema: z.ZodType<T>,
654+
body: unknown,
655+
response: { setStatus: (code: number, message: string) => void },
656+
): { ok: true; data: T } | { ok: false; error: { error: string; details: unknown } } {
657+
const parsed = schema.safeParse(body ?? {});
658+
if (!parsed.success) {
659+
response.setStatus(400, '');
660+
return {
661+
ok: false,
662+
error: { error: 'Request body validation failed', details: parsed.error.issues },
663+
};
664+
}
665+
return { ok: true, data: parsed.data };
666+
}

0 commit comments

Comments
 (0)