Skip to content

Commit cc0d220

Browse files
authored
Merge pull request #684 from devforth/next
Next
2 parents 986cdb2 + 1205b9d commit cc0d220

14 files changed

Lines changed: 291 additions & 66 deletions

File tree

adminforth/dataConnectors/baseConnector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
3737
client: any;
3838

3939
/**
40-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use .client instead.
40+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use .client instead.
4141
*/
4242
get db() {
4343
afLogger.warn('.db is deprecated, use .client instead');

adminforth/documentation/docs/tutorial/06-Adapters/04-storage-adapters.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pnpm add @adminforth/storage-adapter-s3-compatible
2222
```
2323

2424
Provides S3 compatible interface for object storage services such as MinIO, Wasabi, Cloudflare R2 or other third-party S3 providers.
25-
### How the adapter works:
25+
### How the adapter works
2626

2727
The Amazon S3 adapter uses tagging to mark objects with the special tag `adminforth-candidate-for-cleanup`, and then creates a lifecycle rule that automatically expires objects with that tag.
2828
But not all S3-compatible adapters support tagging, so this adapter has a built-in cleanup mechanism and you have two options:
@@ -51,6 +51,16 @@ If you don't want to use a key/value adapter and you don't need to clean up file
5151
5252
> If somebody uploaded a file and didn't save the record, you will pay for the storage until the file is removed manually
5353
54+
### Choosing Key/value adapter
55+
56+
Since the adapter uses a key/value adapter to store keys for deletion, it is important to use persistent storage, so the data will be safe:
57+
58+
- (⛔️) [RAM adapter](07-key-value-adapters.md#ram-adapter) - not recommended, because after a server restart all data will be lost
59+
- (✅) [Redis adapter](07-key-value-adapters.md#redis-adapter) - Redis itself stores data in-memory, but you can set it up to write data to an `.rdb` file so the database is restored on server restart. However, it requires regular database snapshots and persistent Docker storage setup
60+
- (✅✅) [LevelDB adapter](07-key-value-adapters.md#leveldb-adapter) - can be used, but you need to set up persistent storage in your Docker container, so data won't be lost between restarts
61+
- (✅✅✅) [Resource adapter](07-key-value-adapters.md#resource-based-adapter) - uses a database to store key/value pairs, so data will be safe between restarts, but you need to create an extra table for this storage
62+
63+
5464
### Cloudflare R2 setup example
5565

5666
This adapter requires key/value adapter. For example, we will be using levelDb adapter.

adminforth/documentation/docs/tutorial/06-Adapters/07-key-value-adapters.md

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Key-value adapters are used to store data in a key-value format. They provide a
1111
## RAM Adapter
1212

1313
```bash
14-
pnpm i @adminforth/key-value-adapter-ram
14+
pnpm add @adminforth/key-value-adapter-ram
1515
```
1616

1717
The RAM adapter is a simple in-memory key-value store. It keeps data in process memory, so it is not suitable for multi-process deployments because each process would have its own isolated store. In that case you need a centralized KV adapter such as Redis.
@@ -27,7 +27,7 @@ Cons:
2727
## Redis Adapter
2828

2929
```bash
30-
pnpm i @adminforth/key-value-adapter-redis
30+
pnpm add @adminforth/key-value-adapter-redis
3131
```
3232

3333
Redis uses in-memory storage with $O(1)$ get complexity. It is a great fit for lightweight workloads that fit in RAM, and it also works well for multi-process or replica-based installations as a centralized store. If persistence across restarts is important, configure Redis persistence separately.
@@ -36,7 +36,7 @@ Redis uses in-memory storage with $O(1)$ get complexity. It is a great fit for l
3636
import RedisKeyValueAdapter from '@adminforth/key-value-adapter-redis';
3737

3838
const adapter = new RedisKeyValueAdapter({
39-
redisUrl: 'redis://localhost:6379',
39+
redisUrl: 'redis://localhost:6379/0', // where "/0" - is database number from 0 to 15; Redis can have up to 16 databases"
4040
});
4141

4242
adapter.set('test-key', 'test-value', 120);
@@ -45,7 +45,7 @@ adapter.set('test-key', 'test-value', 120);
4545
## LevelDB Adapter
4646

4747
```bash
48-
pnpm i @adminforth/key-value-adapter-leveldb
48+
pnpm add @adminforth/key-value-adapter-leveldb
4949
```
5050

5151
LevelDB uses disk storage with $O(\log n)$ get complexity. It is a good fit for large or persistent KV datasets that still require fast lookups but do not efficiently fit in RAM. This is a single-process adapter only, so multiple admin processes should not point to the same LevelDB directory.
@@ -60,4 +60,102 @@ const adapter = new LevelDBKeyValueAdapter({
6060
});
6161

6262
adapter.set('test-key', 'test-value', 120);
63+
```
64+
65+
## Resource-based adapter
66+
```bash
67+
pnpm add @adminforth/key-value-adapter-resource
68+
```
69+
70+
Resource adapter uses adminforth resource to store key/value pairs.
71+
72+
### Setup
73+
74+
1) Add schema in `./schema.prisma` file
75+
76+
```
77+
model key_values {
78+
key String @id
79+
value String
80+
collection String?
81+
82+
@@index([key])
83+
@@index([collection])
84+
}
85+
```
86+
87+
2) Apply migration
88+
```bash
89+
pnpm makemigration --name add-adminforth-key-value-tables ; pnpm migrate:local
90+
```
91+
92+
3) Create resource
93+
94+
```ts title="./resources/key_value_resource.ts"
95+
import AdminForth, { AdminForthDataTypes } from 'adminforth';
96+
import type { AdminForthResourceInput, AdminUser } from 'adminforth';
97+
98+
async function allowedForSuperAdmins({ adminUser }: { adminUser: AdminUser }): Promise<boolean> {
99+
return adminUser.dbUser.role === 'superadmin';
100+
}
101+
102+
export default {
103+
dataSource: 'maindb',
104+
table: 'key_values',
105+
resourceId: 'key_values',
106+
label: 'Key values',
107+
columns: [
108+
{
109+
name: 'key',
110+
primaryKey: true,
111+
type: AdminForthDataTypes.STRING,
112+
},
113+
{
114+
name: 'value',
115+
type: AdminForthDataTypes.STRING,
116+
},
117+
{
118+
name: 'collection',
119+
type: AdminForthDataTypes.STRING,
120+
}
121+
],
122+
options: {
123+
allowedActions: {
124+
list: allowedForSuperAdmins,
125+
show: allowedForSuperAdmins,
126+
create: false,
127+
edit: false,
128+
delete: false,
129+
},
130+
},
131+
} as AdminForthResourceInput;
132+
```
133+
134+
4) Register resource
135+
136+
```ts title="./index.ts"
137+
import key_value_resource from './resources/key_value_resource.js';
138+
139+
export const admin = new AdminForth({
140+
...
141+
resources: [
142+
...
143+
key_value_resource,
144+
],
145+
...
146+
});
147+
148+
```
149+
150+
5) Create instance of adapter
151+
152+
```ts
153+
import ResourceKeyValueAdapter from '@adminforth/key-value-adapter-resource'
154+
155+
const adapter = new ResourceKeyValueAdapter({
156+
resourceId: 'key_values',
157+
keyField: 'key',
158+
valueField: 'value',
159+
collectionField: 'collection',
160+
})
63161
```

adminforth/types/Back.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ export type BeforeDataSourceRequestFunction = (params: {
719719
ok: boolean,
720720
error?: string | null,
721721
/**
722-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use redirectToRecordId instead.
722+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use redirectToRecordId instead.
723723
*/
724724
newRecordId?: string,
725725
redirectToRecordId?: string
@@ -767,7 +767,7 @@ export type CreateResourceRecordResult = {
767767
/**
768768
* Optional id of an existing record to redirect to
769769
* (used when a beforeSave hook aborts creation and supplies newRecordId, allows to implement programmatic creation via API).
770-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use redirectToRecordId instead.
770+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use redirectToRecordId instead.
771771
*/
772772
newRecordId?: any;
773773

@@ -800,7 +800,7 @@ export type CreateResourceRecordParams = {
800800
/**
801801
* HTTP response object.
802802
*
803-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
803+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
804804
*/
805805
response?: IAdminForthHttpResponse;
806806

@@ -828,7 +828,7 @@ export type UpdateResourceRecordParams =
828828
/**
829829
* Full record data with applied changes.
830830
*
831-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use updates instead.
831+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use updates instead.
832832
*/
833833
record: any;
834834

@@ -845,7 +845,7 @@ export type UpdateResourceRecordParams =
845845
/**
846846
* HTTP response object.
847847
*
848-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
848+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
849849
*/
850850
response?: IAdminForthHttpResponse;
851851

@@ -873,7 +873,7 @@ export type UpdateResourceRecordParams =
873873
/**
874874
* Full record data with applied changes.
875875
*
876-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use updates instead.
876+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use updates instead.
877877
*/
878878
record?: never;
879879

@@ -890,7 +890,7 @@ export type UpdateResourceRecordParams =
890890
/**
891891
* HTTP response object.
892892
*
893-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
893+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
894894
*/
895895
response?: IAdminForthHttpResponse;
896896

@@ -932,7 +932,7 @@ export type DeleteResourceRecordParams = {
932932
/**
933933
* HTTP response object.
934934
*
935-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
935+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
936936
*/
937937
response?: IAdminForthHttpResponse;
938938

@@ -985,7 +985,7 @@ export type BeforeDeleteSaveFunction = (params: {
985985
/**
986986
* HTTP response object.
987987
*
988-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
988+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
989989
*/
990990
response?: IAdminForthHttpResponse,
991991
/**
@@ -1015,7 +1015,7 @@ export type BeforeEditSaveFunction = (params: {
10151015
/**
10161016
* Record with updates
10171017
*
1018-
* @deprecated. Will be removed in 2.0.0. Use updates instead.
1018+
* @deprecated. Will be removed in 4.0.0. Use updates instead.
10191019
*/
10201020
record: any, // legacy, 'updates' should be used instead
10211021
/**
@@ -1029,7 +1029,7 @@ export type BeforeEditSaveFunction = (params: {
10291029
/**
10301030
* HTTP response object.
10311031
*
1032-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1032+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
10331033
*/
10341034
response: IAdminForthHttpResponse,
10351035
/**
@@ -1058,7 +1058,7 @@ export type BeforeCreateSaveFunction = (params: {
10581058
/**
10591059
* HTTP response object.
10601060
*
1061-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1061+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
10621062
*/
10631063
response: IAdminForthHttpResponse,
10641064

@@ -1067,7 +1067,7 @@ export type BeforeCreateSaveFunction = (params: {
10671067
ok: boolean,
10681068
error?: string | null,
10691069
/**
1070-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use redirectToRecordId instead.
1070+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use redirectToRecordId instead.
10711071
*/
10721072
newRecordId?: string,
10731073
redirectToRecordId?: string
@@ -1101,7 +1101,7 @@ export type AfterCreateSaveFunction = (params: {
11011101
/**
11021102
* HTTP response object.
11031103
*
1104-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1104+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
11051105
*/
11061106
response: IAdminForthHttpResponse,
11071107
/**
@@ -1138,7 +1138,7 @@ export type AfterDeleteSaveFunction = (params: {
11381138
/**
11391139
* HTTP response object.
11401140
*
1141-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1141+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
11421142
*/
11431143
response: IAdminForthHttpResponse,
11441144
/**
@@ -1168,7 +1168,7 @@ export type AfterEditSaveFunction = (params: {
11681168
/**
11691169
* Record after update.
11701170
*
1171-
* @deprecated. Will be removed in 2.0.0. Use updates instead.
1171+
* @deprecated. Will be removed in 4.0.0. Use updates instead.
11721172
*/
11731173
record: any, // legacy, 'updates' should be used instead
11741174
/**
@@ -1182,7 +1182,7 @@ export type AfterEditSaveFunction = (params: {
11821182
/**
11831183
* HTTP response object.
11841184
*
1185-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1185+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
11861186
*/
11871187
response: IAdminForthHttpResponse,
11881188
/**
@@ -1202,7 +1202,7 @@ export type BeforeLoginConfirmationFunction = (params?: {
12021202
/**
12031203
* HTTP response object.
12041204
*
1205-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1205+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
12061206
*/
12071207
response: IAdminForthHttpResponse,
12081208
/**
@@ -1236,7 +1236,7 @@ export type AdminUserAuthorizeFunction = ((params?: {
12361236
/**
12371237
* HTTP response object.
12381238
*
1239-
* @deprecated Since 1.2.9. Will be removed in 2.0.0. Use extra.response instead.
1239+
* @deprecated Since 1.2.9. Will be removed in 4.0.0. Use extra.response instead.
12401240
*/
12411241
response: IAdminForthHttpResponse,
12421242
/**
@@ -2123,7 +2123,7 @@ export interface ResourceOptionsInput extends Omit<NonNullable<AdminForthResourc
21232123
/**
21242124
* Custom bulk actions list. Bulk actions available in list view when user selects multiple records by
21252125
* using checkboxes.
2126-
* @deprecated Since 2.26.5. Will be removed in 3.0.0. Use `actions` instead.
2126+
* @deprecated Since 2.26.5. Will be removed in 4.0.0. Use `actions` instead.
21272127
21282128
*/
21292129
bulkActions?: Array<AdminForthBulkAction>,

adminforth/types/FrontendAPI.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export interface FrontendAPIInterface {
9696
setFilter(filter: FilterParams): void;
9797

9898
/**
99-
* @deprecated does the same as setFilter, kept for backward compatibility, will be removed in 2.0.0
99+
* @deprecated does the same as setFilter, kept for backward compatibility, will be removed in 4.0.0
100100
*
101101
* Update a filter in the list
102102
*

dev-demo/Taskfile.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ vars:
6262
- "adminforth-completion-adapter-anthropic-messages"
6363
- "adminforth-completion-adapter-google-gemini"
6464
- "adminforth-audio-adapter-openai"
65+
- "adminforth-key-value-adapter-resource"
6566

6667
CONNECTORS:
6768
- "adminforth-connector-clickhouse"

0 commit comments

Comments
 (0)