Skip to content
Merged

Next #575

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@

# AGENTS.md

## Package manager

All packages and projects in this repo use `pnpm` and not `npm`.
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.

## General engineering rules

Write code as if the system contracts are already defined and trusted.
Expand Down
16 changes: 15 additions & 1 deletion adminforth/dataConnectors/sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData

async setupClient(url: string): Promise<void> {
this.client = betterSqlite3(url.replace('sqlite://', ''));
this.client.aggregate('median', {
start: (): number[] => [],
step: (acc: number[], val: any) => {
if (val != null) acc.push(Number(val));
},
result: (acc: number[]): number | null => {
if (acc.length === 0) return null;
const sorted = acc.slice().sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 === 0
? (sorted[mid - 1] + sorted[mid]) / 2
: sorted[mid];
},
});
}
async getAllTables(): Promise<Array<string>> {
const stmt = this.client.prepare(
Expand Down Expand Up @@ -358,7 +372,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
case 'avg': selectParts.push(`AVG("${rule.field}") AS "${alias}"`); break;
case 'min': selectParts.push(`MIN("${rule.field}") AS "${alias}"`); break;
case 'max': selectParts.push(`MAX("${rule.field}") AS "${alias}"`); break;
case 'median': throw new Error('Aggregates.median() with GroupBy.Field is not supported in SQLite.');
case 'median': selectParts.push(`median("${rule.field}") AS "${alias}"`); break;
}
}

Expand Down
6 changes: 3 additions & 3 deletions adminforth/documentation/blog/2024-10-01-ai-blog/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Add modules:

```bash
cd ai-blog
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
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
```


Expand Down Expand Up @@ -475,7 +475,7 @@ import UploadPlugin from '@adminforth/upload';
import RichEditorPlugin from '@adminforth/rich-editor';
import ChatGptPlugin from '@adminforth/chat-gpt';
import slugify from 'slugify';
import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt";
import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses";
import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai';

export default {
Expand Down Expand Up @@ -591,7 +591,7 @@ export default {
new RichEditorPlugin({
htmlFieldName: 'content',
completion: {
adapter: new CompletionAdapterOpenAIChatGPT({
adapter: new CompletionAdapterOpenAIResponses({
openAiApiKey: process.env.OPENAI_API_KEY as string,
model: 'gpt-4o',
expert: {
Expand Down
75 changes: 65 additions & 10 deletions adminforth/documentation/docs/tutorial/001-gettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ After the resource file is generated, extend it with display and validation sett
To properly apply these changes, refer to the example below and adjust the configuration according to your settings

```ts title="./resources/apartments.ts"
import { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
import { AdminForthResourceInput, AdminForthDataTypes } from 'adminforth';

export default {
dataSource: 'maindb',
Expand All @@ -206,32 +206,41 @@ export default {
resourceId: 'apartments'
//diff-add
resourceId: 'aparts', // resourceId is defaulted to table name but you can redefine it like this e.g.
//diff-add
// in case of same table names from different data sources
label: 'Apartments', // label is defaulted to table name but you can change it
//diff-add
recordLabel: (r) => `🏡 ${r.title}`,
columns: [
{
name: 'id',
//diff-add
type: AdminForthDataTypes.STRING,
//diff-add
label: 'Identifier', // if you wish you can redefine label, defaulted to uppercased name
showIn: { // show column in filter and in show page
//diff-add
//diff-remove
all:true,
//diff-add
list: false,
//diff-add
edit: false,
//diff-add
create: false,
},
//diff-add
primaryKey: true,
//diff-add
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
},
{
name: 'title',
name: "title",
//diff-add
required: true,
showIn: { all: true }, // all available options
showIn: {
all:true, // all available options
},
//diff-add
type: AdminForthDataTypes.STRING,
//diff-add
maxLength: 255, // you can set max length for string fields
Expand All @@ -240,14 +249,24 @@ export default {
},
{
name: 'created_at',
//diff-add
type: AdminForthDataTypes.DATETIME,
//diff-add
allowMinMaxQuery: true,
showIn: { create: false },
showIn: {
//diff-remove
all:true,
//diff-add
create: false,
},
//diff-add
fillOnCreate: ({ initialRecord, adminUser }) => (new Date()).toISOString(),
},
{
name: 'price',
showIn: {
all:true,
},
//diff-add
inputSuffix: 'USD', // you can add a suffix to an input field that will be displayed when creating or editing records
//diff-add
Expand All @@ -257,16 +276,25 @@ export default {
},
{
name: 'square_meter',
//diff-add
label: 'Square',
//diff-add
allowMinMaxQuery: true,
showIn: {
all:true,
},
//diff-add
minValue: 1, // you can set min /max value for number columns so users will not be able to enter more/less
//diff-add
maxValue: 1000,
},
{
name: 'number_of_rooms',
//diff-add
allowMinMaxQuery: true,
showIn: {
all:true,
},
//diff-add
enum: [
//diff-add
Expand All @@ -284,11 +312,20 @@ export default {
},
{
name: 'description',
//diff-add
sortable: false,
showIn: { list: false },
showIn: {
//diff-remove
all:true,
//diff-add
list: false,
}
},
{
name: 'country',
showIn: {
all:true,
},
//diff-add
enum: [{
//diff-add
Expand Down Expand Up @@ -362,18 +399,27 @@ export default {
name: 'listed',
//diff-add
required: true, // will be required on create/edit
showIn: {
all:true,
}
},
{
name: 'realtor_id',
//diff-add
foreignResource: {
//diff-add
resourceId: 'adminuser',
//diff-add
searchableFields: ["id", "email"], // fields available for search in filter
//diff-add
},
showIn: {
all:true,
}
}
],
options: {
listPageSize: 12,
listPageSize: 10,
//diff-add
allowedActions: {
//diff-add
Expand Down Expand Up @@ -439,8 +485,17 @@ export const admin = new AdminForth({
},
{
label: 'Users',
...
}
icon: 'flowbite:user-solid',
resourceId: 'adminuser'
},
{
label: "Apartments",
icon: "flowbite:user-solid",
//diff-remove
resourceId: "apartments",
//diff-add
resourceId: "aparts",
},
],
...
});
Expand All @@ -467,7 +522,7 @@ async function seedDatabase() {
//diff-add
title: `Apartment ${i}`,
//diff-add
square_meter: (Math.random() * 100).toFixed(1),
square_meter: Number((Math.random() * 100).toFixed(1)),
//diff-add
price: (Math.random() * 10000).toFixed(2),
//diff-add
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Email Adapters

Used to send emails.

[Email adapter base class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/EmailAdapter.ts#L17)

## AWS SES Email Adapter

```bash
pnpm i @adminforth/email-adapter-aws-ses
```

Enables email delivery via [Amazon Simple Email Service (SES)](https://aws.amazon.com/ses/), suitable for high-volume, programmatic email sending.

## Mailgun Email Adapter

```bash
pnpm i @adminforth/email-adapter-mailgun
```

Allows sending transactional or marketing emails using [Mailgun](https://www.mailgun.com/), a developer-friendly email service.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# OAuth2 Adapters

Used to authenticate users via OAuth 2.0 providers.

[OAuth2Adapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/OAuth2Adapter.ts#L9)

## Google OAuth Adapter

```bash
pnpm i @adminforth/google-oauth-adapter
```

Supports Google sign-in to allow users to authenticate using their Google or Google Workspaces accounts.

## GitHub OAuth Adapter

```bash
pnpm i @adminforth/github-oauth-adapter
```

Enables authentication via GitHub accounts, useful for developer tools and open-source apps.

## Facebook OAuth Adapter

```bash
pnpm i @adminforth/facebook-oauth-adapter
```

Allows users to log in with Facebook credentials. Facebook OAuth is commonly used for social media integrations.

## Keycloak OAuth Adapter

```bash
pnpm i @adminforth/keycloak-oauth-adapter
```

Connects AdminForth to an open-source [Keycloak](https://www.keycloak.org/) identity provider for enterprise-grade SSO (Single Sign-On).

## Microsoft OAuth Adapter

```bash
pnpm i @adminforth/microsoft-oauth-adapter
```

Supports login through Microsoft accounts including Azure AD, Office365, and Outlook.com.

## Twitch OAuth Adapter

```bash
pnpm i @adminforth/twitch-oauth-adapter
```

Adds support for Twitch authentication, useful for streaming or creator-oriented platforms.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Image Generation Adapters

Used for image-generating AI tools.

[ImageGenerationAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/ImageGenerationAdapter.ts#L32)

## OpenAI Image Generation Adapter

```bash
pnpm i @adminforth/image-generation-adapter-openai
```

Uses OpenAI image generation models such as DALL·E, `gpt-image-1`, and `gpt-image-1.5` to generate images from text prompts.

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.

## Gemini (Nano Banana) Image Generation Adapter

```bash
pnpm i @adminforth/image-generation-adapter-nano-banana
```

Uses the latest `gemini-3.1-flash-image-preview` model for instant image generation with text descriptions.

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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Storage Adapters

Used for storing files.

[StorageAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/StorageAdapter.ts#L8)

## Amazon S3 Storage Adapter

```bash
pnpm i @adminforth/storage-adapter-amazon-s3
```

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.

## Local Storage Adapter

```bash
pnpm i @adminforth/storage-adapter-local
```

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.
Loading