Skip to content

Commit 31203cc

Browse files
committed
Merge branch 'next' of github.com:devforth/adminforth into next
2 parents 7c48ae7 + c48b9a0 commit 31203cc

26 files changed

Lines changed: 1493 additions & 447 deletions

File tree

adminforth/dataConnectors/postgres.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ import AdminForthBaseConnector from './baseConnector.js';
55
import pkg from 'pg';
66
import { afLogger, dbLogger } from '../modules/logger.js';
77

8-
const { Client } = pkg;
8+
const { Pool } = pkg;
9+
const { Client, types } = pkg;
10+
11+
// postgres-date (used by pg for OID 1114/1082) parses no-TZ strings with new Date(y,m,d,...)
12+
// which treats them as LOCAL server time. Return raw strings so getFieldValue can parse as UTC.
13+
types.setTypeParser(1114, (val) => val); // TIMESTAMP WITHOUT TIME ZONE
14+
types.setTypeParser(1082, (val) => val); // DATE
915

1016

1117
class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
1218

1319
async setupClient(url: string): Promise<void> {
14-
this.client = new Client({
20+
this.client = new Pool({
1521
connectionString: url
1622
});
1723
try {
@@ -200,7 +206,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
200206
return null;
201207
}
202208
if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
203-
return dayjs(value).toISOString();
209+
return dayjs(value.replace(' ', 'T') + 'Z').toISOString();
204210
} else if (field._underlineType == 'varchar') {
205211
return dayjs(value).toISOString();
206212
} else {
@@ -212,7 +218,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
212218
if (!value) {
213219
return null;
214220
}
215-
return dayjs(value).toISOString().split('T')[0];
221+
return value;
216222
}
217223

218224
if (field.type == AdminForthDataTypes.BOOLEAN) {

adminforth/documentation/docs/tutorial/03-Customization/04-hooks.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ When user clicks the "Save" button on edit page, AdminForth makes a request to t
5252

5353
![Saving data on edit page](image-27.png)
5454

55-
Practically you can use `edit.beforeSave` hook to modify the data or populate new fields before it is saved to the database.
55+
Practically you can use `hooks.edit.beforeSave` hook to modify the data or populate new fields before it is saved to the database.
5656

57-
> 👆 Note: according to diagram you should understand that interrupting flow from `edit.afterSave` does not prevent data modification in DB
57+
> 👆 Note: according to diagram you should understand that interrupting flow from `hooks.edit.afterSave` does not prevent data modification in DB
5858
5959
## Saving data on create page
6060

@@ -266,4 +266,4 @@ always performed before any hooks and any database requests.
266266

267267
## All hooks
268268

269-
Check all hooks in the [API reference](/docs/api/Back/interfaces/AdminForthResource).
269+
Check all hooks in the [API reference](/docs/api/Back/interfaces/AdminForthResource).

adminforth/documentation/docs/tutorial/03-Customization/16-websocket.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
AdminForth provide own build-in websocket interface which allows to stream some data to frontend from backend.
55

6+
If in production you run through a reverse proxy such as Nginx, ensure websocket upgrade is enabled on the `/afws` path under your AdminForth base URL, otherwise websocket will not work. See [Deploy in Docker > Nginx version](/docs/tutorial/deploy#nginx-version).
7+
68
In two words, to subscribe to a topic from any frontend component you need to do next
79

810
```javascript

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

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,18 @@ docker compose -p stack-my-app -f compose.yml up -d --build --remove-orphans --w
115115
If you want to deploy your AdminForth application to a sub-folder like `https://mydomain.com/admin` you
116116
should do the following:
117117

118-
1) Open `index.ts` file and change `ADMIN_BASE_URL` constant to your subpath:
118+
1) Open `index.ts` file and set the same subpath in `ADMIN_BASE_URL` and `baseUrl`:
119119

120120
```ts title='./index.ts'
121121
//diff-remove
122122
const ADMIN_BASE_URL = '';
123123
//diff-add
124124
const ADMIN_BASE_URL = '/admin/';
125+
126+
export const admin = new AdminForth({
127+
baseUrl: ADMIN_BASE_URL,
128+
...
129+
});
125130
```
126131

127132
2) Open `compose.yml` file and change `traefik.http.routers.adminforth.rule` to your subpath:
@@ -141,11 +146,18 @@ Now you can access your AdminForth application by going to `https://mydomain.com
141146

142147
If you want to automate the deployment process with CI follow [our docker - traefik guide](https://devforth.io/blog/onlogs-open-source-simplified-web-logs-viewer-for-dockers/)
143148

144-
# Nginx version
149+
## Nginx version
145150

146-
If you are using Nginx instead of traefik, here is siple proxy pass config:
151+
If you are using Nginx instead of traefik, proxy both regular HTTP traffic and AdminForth websocket endpoint.
147152

148-
```
153+
AdminForth websocket always uses `<baseUrl>/afws`, where `<baseUrl>` is the same value you pass to `baseUrl: ADMIN_BASE_URL` in `index.ts`.
154+
155+
- If `ADMIN_BASE_URL = ''`, use `/afws`.
156+
- If `ADMIN_BASE_URL = '/admin/'`, use `/admin/afws`.
157+
158+
For root deployment, the config can look like this:
159+
160+
```nginx
149161
server {
150162
listen 80;
151163
server_name demo.adminforth.dev;
@@ -163,6 +175,17 @@ server {
163175
gzip_min_length 2000;
164176
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
165177
178+
location /afws {
179+
proxy_http_version 1.1;
180+
proxy_read_timeout 220s;
181+
proxy_set_header Upgrade $http_upgrade;
182+
proxy_set_header Connection "upgrade";
183+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
184+
proxy_set_header Host $http_host;
185+
proxy_redirect off;
186+
proxy_pass http://127.0.0.1:3500;
187+
}
188+
166189
location / {
167190
proxy_read_timeout 220s;
168191
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -173,6 +196,35 @@ server {
173196
}
174197
```
175198

199+
If you deploy AdminForth under a subpath, use the same prefix in Nginx locations. For example, when `ADMIN_BASE_URL = '/admin/'`, the websocket path becomes `/admin/afws`:
200+
201+
```nginx
202+
server {
203+
...
204+
205+
location /admin/afws {
206+
proxy_http_version 1.1;
207+
proxy_read_timeout 220s;
208+
proxy_set_header Upgrade $http_upgrade;
209+
proxy_set_header Connection "upgrade";
210+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
211+
proxy_set_header Host $http_host;
212+
proxy_redirect off;
213+
proxy_pass http://127.0.0.1:3500;
214+
}
215+
216+
location /admin/ {
217+
proxy_read_timeout 220s;
218+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
219+
proxy_set_header Host $http_host;
220+
proxy_redirect off;
221+
proxy_pass http://127.0.0.1:3500;
222+
}
223+
}
224+
```
225+
226+
If websocket upgrade is not configured on the correct `<baseUrl>/afws` path, realtime AdminForth features will not work behind Nginx.
227+
176228
# Environment variables best practices
177229

178230
Use `.env` file for sensitive variables like `OPENAI_API_KEY` locally.

0 commit comments

Comments
 (0)