Skip to content

Commit a9707e8

Browse files
authored
Merge pull request #575 from devforth/next
Next
2 parents 5cfbc0b + f8d092a commit a9707e8

35 files changed

Lines changed: 608 additions & 538 deletions

AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11

22
# AGENTS.md
33

4+
## Package manager
5+
6+
All packages and projects in this repo use `pnpm` and not `npm`.
7+
Howeverer internally (e.g. in `codeInjector`) adminforth still supports both `npm` and `pnpm` style install commands, so users of framework itself can use it with either package manager. But in all dev demo/live demo, plugins, adapters, and documentation, we use `pnpm` as the standard.
8+
49
## General engineering rules
510

611
Write code as if the system contracts are already defined and trusted.

adminforth/dataConnectors/sqlite.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
99

1010
async setupClient(url: string): Promise<void> {
1111
this.client = betterSqlite3(url.replace('sqlite://', ''));
12+
this.client.aggregate('median', {
13+
start: (): number[] => [],
14+
step: (acc: number[], val: any) => {
15+
if (val != null) acc.push(Number(val));
16+
},
17+
result: (acc: number[]): number | null => {
18+
if (acc.length === 0) return null;
19+
const sorted = acc.slice().sort((a, b) => a - b);
20+
const mid = Math.floor(sorted.length / 2);
21+
return sorted.length % 2 === 0
22+
? (sorted[mid - 1] + sorted[mid]) / 2
23+
: sorted[mid];
24+
},
25+
});
1226
}
1327
async getAllTables(): Promise<Array<string>> {
1428
const stmt = this.client.prepare(
@@ -358,7 +372,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
358372
case 'avg': selectParts.push(`AVG("${rule.field}") AS "${alias}"`); break;
359373
case 'min': selectParts.push(`MIN("${rule.field}") AS "${alias}"`); break;
360374
case 'max': selectParts.push(`MAX("${rule.field}") AS "${alias}"`); break;
361-
case 'median': throw new Error('Aggregates.median() with GroupBy.Field is not supported in SQLite.');
375+
case 'median': selectParts.push(`median("${rule.field}") AS "${alias}"`); break;
362376
}
363377
}
364378

adminforth/documentation/blog/2024-10-01-ai-blog/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Add modules:
4747

4848
```bash
4949
cd ai-blog
50-
npm i @adminforth/upload @adminforth/rich-editor @adminforth/text-complete @adminforth/chat-gpt slugify http-proxy @adminforth/image-generation-adapter-openai @adminforth/completion-adapter-open-ai-chat-gpt
50+
npm i @adminforth/upload @adminforth/rich-editor @adminforth/text-complete @adminforth/chat-gpt slugify http-proxy @adminforth/image-generation-adapter-openai @adminforth/completion-adapter-openai-responses
5151
```
5252

5353

@@ -475,7 +475,7 @@ import UploadPlugin from '@adminforth/upload';
475475
import RichEditorPlugin from '@adminforth/rich-editor';
476476
import ChatGptPlugin from '@adminforth/chat-gpt';
477477
import slugify from 'slugify';
478-
import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt";
478+
import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses";
479479
import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai';
480480

481481
export default {
@@ -591,7 +591,7 @@ export default {
591591
new RichEditorPlugin({
592592
htmlFieldName: 'content',
593593
completion: {
594-
adapter: new CompletionAdapterOpenAIChatGPT({
594+
adapter: new CompletionAdapterOpenAIResponses({
595595
openAiApiKey: process.env.OPENAI_API_KEY as string,
596596
model: 'gpt-4o',
597597
expert: {

adminforth/documentation/docs/tutorial/001-gettingStarted.md

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ After the resource file is generated, extend it with display and validation sett
197197
To properly apply these changes, refer to the example below and adjust the configuration according to your settings
198198

199199
```ts title="./resources/apartments.ts"
200-
import { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
200+
import { AdminForthResourceInput, AdminForthDataTypes } from 'adminforth';
201201

202202
export default {
203203
dataSource: 'maindb',
@@ -206,32 +206,41 @@ export default {
206206
resourceId: 'apartments'
207207
//diff-add
208208
resourceId: 'aparts', // resourceId is defaulted to table name but you can redefine it like this e.g.
209+
//diff-add
209210
// in case of same table names from different data sources
210211
label: 'Apartments', // label is defaulted to table name but you can change it
211212
//diff-add
212213
recordLabel: (r) => `🏡 ${r.title}`,
213214
columns: [
214215
{
215216
name: 'id',
217+
//diff-add
216218
type: AdminForthDataTypes.STRING,
217219
//diff-add
218220
label: 'Identifier', // if you wish you can redefine label, defaulted to uppercased name
219221
showIn: { // show column in filter and in show page
220-
//diff-add
222+
//diff-remove
223+
all:true,
224+
//diff-add
221225
list: false,
222226
//diff-add
223227
edit: false,
224228
//diff-add
225229
create: false,
226230
},
231+
//diff-add
227232
primaryKey: true,
228233
//diff-add
229234
fillOnCreate: ({ initialRecord, adminUser }) => Math.random().toString(36).substring(7), // called during creation to generate content of field, initialRecord is values user entered, adminUser object of user who creates record
230235
},
231236
{
232-
name: 'title',
237+
name: "title",
238+
//diff-add
233239
required: true,
234-
showIn: { all: true }, // all available options
240+
showIn: {
241+
all:true, // all available options
242+
},
243+
//diff-add
235244
type: AdminForthDataTypes.STRING,
236245
//diff-add
237246
maxLength: 255, // you can set max length for string fields
@@ -240,14 +249,24 @@ export default {
240249
},
241250
{
242251
name: 'created_at',
252+
//diff-add
243253
type: AdminForthDataTypes.DATETIME,
254+
//diff-add
244255
allowMinMaxQuery: true,
245-
showIn: { create: false },
256+
showIn: {
257+
//diff-remove
258+
all:true,
259+
//diff-add
260+
create: false,
261+
},
246262
//diff-add
247263
fillOnCreate: ({ initialRecord, adminUser }) => (new Date()).toISOString(),
248264
},
249265
{
250266
name: 'price',
267+
showIn: {
268+
all:true,
269+
},
251270
//diff-add
252271
inputSuffix: 'USD', // you can add a suffix to an input field that will be displayed when creating or editing records
253272
//diff-add
@@ -257,16 +276,25 @@ export default {
257276
},
258277
{
259278
name: 'square_meter',
279+
//diff-add
260280
label: 'Square',
281+
//diff-add
261282
allowMinMaxQuery: true,
283+
showIn: {
284+
all:true,
285+
},
262286
//diff-add
263287
minValue: 1, // you can set min /max value for number columns so users will not be able to enter more/less
264288
//diff-add
265289
maxValue: 1000,
266290
},
267291
{
268292
name: 'number_of_rooms',
293+
//diff-add
269294
allowMinMaxQuery: true,
295+
showIn: {
296+
all:true,
297+
},
270298
//diff-add
271299
enum: [
272300
//diff-add
@@ -284,11 +312,20 @@ export default {
284312
},
285313
{
286314
name: 'description',
315+
//diff-add
287316
sortable: false,
288-
showIn: { list: false },
317+
showIn: {
318+
//diff-remove
319+
all:true,
320+
//diff-add
321+
list: false,
322+
}
289323
},
290324
{
291325
name: 'country',
326+
showIn: {
327+
all:true,
328+
},
292329
//diff-add
293330
enum: [{
294331
//diff-add
@@ -362,18 +399,27 @@ export default {
362399
name: 'listed',
363400
//diff-add
364401
required: true, // will be required on create/edit
402+
showIn: {
403+
all:true,
404+
}
365405
},
366406
{
367407
name: 'realtor_id',
408+
//diff-add
368409
foreignResource: {
410+
//diff-add
369411
resourceId: 'adminuser',
370412
//diff-add
371413
searchableFields: ["id", "email"], // fields available for search in filter
414+
//diff-add
415+
},
416+
showIn: {
417+
all:true,
372418
}
373419
}
374420
],
375421
options: {
376-
listPageSize: 12,
422+
listPageSize: 10,
377423
//diff-add
378424
allowedActions: {
379425
//diff-add
@@ -439,8 +485,17 @@ export const admin = new AdminForth({
439485
},
440486
{
441487
label: 'Users',
442-
...
443-
}
488+
icon: 'flowbite:user-solid',
489+
resourceId: 'adminuser'
490+
},
491+
{
492+
label: "Apartments",
493+
icon: "flowbite:user-solid",
494+
//diff-remove
495+
resourceId: "apartments",
496+
//diff-add
497+
resourceId: "aparts",
498+
},
444499
],
445500
...
446501
});
@@ -467,7 +522,7 @@ async function seedDatabase() {
467522
//diff-add
468523
title: `Apartment ${i}`,
469524
//diff-add
470-
square_meter: (Math.random() * 100).toFixed(1),
525+
square_meter: Number((Math.random() * 100).toFixed(1)),
471526
//diff-add
472527
price: (Math.random() * 10000).toFixed(2),
473528
//diff-add
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Email Adapters
2+
3+
Used to send emails.
4+
5+
[Email adapter base class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/EmailAdapter.ts#L17)
6+
7+
## AWS SES Email Adapter
8+
9+
```bash
10+
pnpm i @adminforth/email-adapter-aws-ses
11+
```
12+
13+
Enables email delivery via [Amazon Simple Email Service (SES)](https://aws.amazon.com/ses/), suitable for high-volume, programmatic email sending.
14+
15+
## Mailgun Email Adapter
16+
17+
```bash
18+
pnpm i @adminforth/email-adapter-mailgun
19+
```
20+
21+
Allows sending transactional or marketing emails using [Mailgun](https://www.mailgun.com/), a developer-friendly email service.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# OAuth2 Adapters
2+
3+
Used to authenticate users via OAuth 2.0 providers.
4+
5+
[OAuth2Adapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/OAuth2Adapter.ts#L9)
6+
7+
## Google OAuth Adapter
8+
9+
```bash
10+
pnpm i @adminforth/google-oauth-adapter
11+
```
12+
13+
Supports Google sign-in to allow users to authenticate using their Google or Google Workspaces accounts.
14+
15+
## GitHub OAuth Adapter
16+
17+
```bash
18+
pnpm i @adminforth/github-oauth-adapter
19+
```
20+
21+
Enables authentication via GitHub accounts, useful for developer tools and open-source apps.
22+
23+
## Facebook OAuth Adapter
24+
25+
```bash
26+
pnpm i @adminforth/facebook-oauth-adapter
27+
```
28+
29+
Allows users to log in with Facebook credentials. Facebook OAuth is commonly used for social media integrations.
30+
31+
## Keycloak OAuth Adapter
32+
33+
```bash
34+
pnpm i @adminforth/keycloak-oauth-adapter
35+
```
36+
37+
Connects AdminForth to an open-source [Keycloak](https://www.keycloak.org/) identity provider for enterprise-grade SSO (Single Sign-On).
38+
39+
## Microsoft OAuth Adapter
40+
41+
```bash
42+
pnpm i @adminforth/microsoft-oauth-adapter
43+
```
44+
45+
Supports login through Microsoft accounts including Azure AD, Office365, and Outlook.com.
46+
47+
## Twitch OAuth Adapter
48+
49+
```bash
50+
pnpm i @adminforth/twitch-oauth-adapter
51+
```
52+
53+
Adds support for Twitch authentication, useful for streaming or creator-oriented platforms.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Image Generation Adapters
2+
3+
Used for image-generating AI tools.
4+
5+
[ImageGenerationAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/ImageGenerationAdapter.ts#L32)
6+
7+
## OpenAI Image Generation Adapter
8+
9+
```bash
10+
pnpm i @adminforth/image-generation-adapter-openai
11+
```
12+
13+
Uses OpenAI image generation models such as DALL·E, `gpt-image-1`, and `gpt-image-1.5` to generate images from text prompts.
14+
15+
Up to the winter 2026 OpenAI models are one of the most powerful image generation models available, especially GPT-Image-1.5, which is why we started with them.
16+
17+
## Gemini (Nano Banana) Image Generation Adapter
18+
19+
```bash
20+
pnpm i @adminforth/image-generation-adapter-nano-banana
21+
```
22+
23+
Uses the latest `gemini-3.1-flash-image-preview` model for instant image generation with text descriptions.
24+
25+
This model is the top of the Nano Banana line as of 2026, combining the speed of the Flash series with the improved detail of version 3.1. The adapter lets you integrate the advanced capabilities of previous models into your interface and generate precise visuals even for specific or complex prompts.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Storage Adapters
2+
3+
Used for storing files.
4+
5+
[StorageAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/StorageAdapter.ts#L8)
6+
7+
## Amazon S3 Storage Adapter
8+
9+
```bash
10+
pnpm i @adminforth/storage-adapter-amazon-s3
11+
```
12+
13+
Stores uploaded files in [Amazon S3](https://aws.amazon.com/s3/), providing scalable cloud storage. It can be forked and customized to work with S3-compatible services such as MinIO, Wasabi, or other third-party S3 providers.
14+
15+
## Local Storage Adapter
16+
17+
```bash
18+
pnpm i @adminforth/storage-adapter-local
19+
```
20+
21+
Stores files locally on the server filesystem. It is suitable for development or small self-hosted setups, but cloud storage is generally a better production option for reliability and scalability.

0 commit comments

Comments
 (0)