@modern-admin/system-prisma 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/index.d.ts +43 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +53 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/stores/ai-task-store.d.ts +43 -0
  6. package/dist/stores/ai-task-store.d.ts.map +1 -0
  7. package/dist/stores/ai-task-store.js +108 -0
  8. package/dist/stores/ai-task-store.js.map +1 -0
  9. package/dist/stores/cache-store.d.ts +30 -0
  10. package/dist/stores/cache-store.d.ts.map +1 -0
  11. package/dist/stores/cache-store.js +61 -0
  12. package/dist/stores/cache-store.js.map +1 -0
  13. package/dist/stores/config-store.d.ts +20 -0
  14. package/dist/stores/config-store.d.ts.map +1 -0
  15. package/dist/stores/config-store.js +61 -0
  16. package/dist/stores/config-store.js.map +1 -0
  17. package/dist/stores/history-store.d.ts +33 -0
  18. package/dist/stores/history-store.d.ts.map +1 -0
  19. package/dist/stores/history-store.js +57 -0
  20. package/dist/stores/history-store.js.map +1 -0
  21. package/dist/stores/log-store.d.ts +23 -0
  22. package/dist/stores/log-store.d.ts.map +1 -0
  23. package/dist/stores/log-store.js +65 -0
  24. package/dist/stores/log-store.js.map +1 -0
  25. package/dist/stores/webhook-store.d.ts +43 -0
  26. package/dist/stores/webhook-store.d.ts.map +1 -0
  27. package/dist/stores/webhook-store.js +111 -0
  28. package/dist/stores/webhook-store.js.map +1 -0
  29. package/dist/types.d.ts +67 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +30 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +52 -0
  34. package/src/index.ts +88 -0
  35. package/src/stores/ai-task-store.ts +154 -0
  36. package/src/stores/cache-store.ts +79 -0
  37. package/src/stores/config-store.ts +80 -0
  38. package/src/stores/history-store.ts +84 -0
  39. package/src/stores/log-store.ts +77 -0
  40. package/src/stores/webhook-store.ts +150 -0
  41. package/src/types.ts +70 -0
@@ -0,0 +1,43 @@
1
+ import type { ISystemStores } from '@modern-admin/core';
2
+ import { PrismaLogStore } from './stores/log-store.js';
3
+ import { PrismaWebhookStore } from './stores/webhook-store.js';
4
+ import { PrismaConfigStore } from './stores/config-store.js';
5
+ import { PrismaHistoryStore } from './stores/history-store.js';
6
+ import { PrismaAiTaskStore } from './stores/ai-task-store.js';
7
+ import { PrismaCacheStore } from './stores/cache-store.js';
8
+ import { type ModelOverrides, type PrismaLike } from './types.js';
9
+ export interface PrismaSystemOptions {
10
+ /**
11
+ * Override Prisma client property names if you renamed the shipped
12
+ * models. Defaults match the camelCased model identifiers from
13
+ * `prisma/modern-admin.prisma`:
14
+ *
15
+ * { log: 'maLog', webhook: 'maWebhook', webhookDelivery: 'maWebhookDelivery',
16
+ * config: 'maConfig', history: 'maHistory', aiTask: 'maAiTask',
17
+ * aiTaskEvent: 'maAiTaskEvent', cache: 'maCache' }
18
+ */
19
+ models?: ModelOverrides;
20
+ }
21
+ export interface PrismaSystem extends ISystemStores {
22
+ logStore: PrismaLogStore;
23
+ webhookStore: PrismaWebhookStore;
24
+ configStore: PrismaConfigStore;
25
+ historyStore: PrismaHistoryStore;
26
+ aiTaskStore: PrismaAiTaskStore;
27
+ cacheStore: PrismaCacheStore;
28
+ }
29
+ /**
30
+ * Build the full bundle of system stores from a Prisma client instance.
31
+ * The host owns the client lifecycle (connect/disconnect); this just wires
32
+ * the model delegates to thin store classes.
33
+ */
34
+ export declare function setupPrismaSystem(prisma: PrismaLike, options?: PrismaSystemOptions): PrismaSystem;
35
+ export { PrismaLogStore } from './stores/log-store.js';
36
+ export { PrismaWebhookStore } from './stores/webhook-store.js';
37
+ export { PrismaConfigStore } from './stores/config-store.js';
38
+ export { PrismaHistoryStore } from './stores/history-store.js';
39
+ export { PrismaAiTaskStore } from './stores/ai-task-store.js';
40
+ export { PrismaCacheStore } from './stores/cache-store.js';
41
+ export type { PrismaDelegate, PrismaLike, ModelOverrides, ModelKey } from './types.js';
42
+ export { DEFAULT_MODELS } from './types.js';
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAA;AAElF,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,QAAQ,EAAE,cAAc,CAAA;IACxB,YAAY,EAAE,kBAAkB,CAAA;IAChC,WAAW,EAAE,iBAAiB,CAAA;IAC9B,YAAY,EAAE,kBAAkB,CAAA;IAChC,WAAW,EAAE,iBAAiB,CAAA;IAC9B,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,mBAAwB,GAChC,YAAY,CAgBd;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ // @modern-admin/system-prisma — Prisma-backed implementations of the
2
+ // runtime system stores defined in `@modern-admin/core/system`.
3
+ //
4
+ // Quick start:
5
+ // 1. Copy `prisma/modern-admin.prisma` into your application's schema
6
+ // (or include via Prisma multi-file schema).
7
+ // 2. Run your usual Prisma migration workflow.
8
+ // 3. Wire stores to subsystems:
9
+ //
10
+ // import { PrismaClient } from '@prisma/client'
11
+ // import { setupPrismaSystem } from '@modern-admin/system-prisma'
12
+ // import { actionLoggingPlugin } from '@modern-admin-pro/feature-logging'
13
+ //
14
+ // const prisma = new PrismaClient()
15
+ // const system = setupPrismaSystem(prisma)
16
+ //
17
+ // new ModernAdmin({
18
+ // databases: [...],
19
+ // plugins: [actionLoggingPlugin({ store: system.logStore })],
20
+ // })
21
+ //
22
+ // If you renamed the shipped models, pass `{ models: { log: 'myLog', ... } }`.
23
+ import { PrismaLogStore } from './stores/log-store.js';
24
+ import { PrismaWebhookStore } from './stores/webhook-store.js';
25
+ import { PrismaConfigStore } from './stores/config-store.js';
26
+ import { PrismaHistoryStore } from './stores/history-store.js';
27
+ import { PrismaAiTaskStore } from './stores/ai-task-store.js';
28
+ import { PrismaCacheStore } from './stores/cache-store.js';
29
+ import { resolveDelegate } from './types.js';
30
+ /**
31
+ * Build the full bundle of system stores from a Prisma client instance.
32
+ * The host owns the client lifecycle (connect/disconnect); this just wires
33
+ * the model delegates to thin store classes.
34
+ */
35
+ export function setupPrismaSystem(prisma, options = {}) {
36
+ const m = options.models;
37
+ return {
38
+ logStore: new PrismaLogStore(resolveDelegate(prisma, 'log', m)),
39
+ webhookStore: new PrismaWebhookStore(resolveDelegate(prisma, 'webhook', m), resolveDelegate(prisma, 'webhookDelivery', m)),
40
+ configStore: new PrismaConfigStore(resolveDelegate(prisma, 'config', m)),
41
+ historyStore: new PrismaHistoryStore(resolveDelegate(prisma, 'history', m)),
42
+ aiTaskStore: new PrismaAiTaskStore(resolveDelegate(prisma, 'aiTask', m), resolveDelegate(prisma, 'aiTaskEvent', m)),
43
+ cacheStore: new PrismaCacheStore(resolveDelegate(prisma, 'cache', m)),
44
+ };
45
+ }
46
+ export { PrismaLogStore } from './stores/log-store.js';
47
+ export { PrismaWebhookStore } from './stores/webhook-store.js';
48
+ export { PrismaConfigStore } from './stores/config-store.js';
49
+ export { PrismaHistoryStore } from './stores/history-store.js';
50
+ export { PrismaAiTaskStore } from './stores/ai-task-store.js';
51
+ export { PrismaCacheStore } from './stores/cache-store.js';
52
+ export { DEFAULT_MODELS } from './types.js';
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,gEAAgE;AAChE,EAAE;AACF,eAAe;AACf,sEAAsE;AACtE,gDAAgD;AAChD,+CAA+C;AAC/C,gCAAgC;AAChC,EAAE;AACF,mDAAmD;AACnD,qEAAqE;AACrE,6EAA6E;AAC7E,EAAE;AACF,uCAAuC;AACvC,8CAA8C;AAC9C,EAAE;AACF,uBAAuB;AACvB,yBAAyB;AACzB,mEAAmE;AACnE,QAAQ;AACR,EAAE;AACF,+EAA+E;AAG/E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAwC,eAAe,EAAE,MAAM,YAAY,CAAA;AAwBlF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAkB,EAClB,UAA+B,EAAE;IAEjC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAA;IACxB,OAAO;QACL,QAAQ,EAAE,IAAI,cAAc,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAC/D,YAAY,EAAE,IAAI,kBAAkB,CAClC,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EACrC,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAC9C;QACD,WAAW,EAAE,IAAI,iBAAiB,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QACxE,YAAY,EAAE,IAAI,kBAAkB,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAC3E,WAAW,EAAE,IAAI,iBAAiB,CAChC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EACpC,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,CAC1C;QACD,UAAU,EAAE,IAAI,gBAAgB,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;KACtE,CAAA;AACH,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { type AiTask, type AiTaskEvent, type AiTaskInput, type AiTaskStatus, type IAiTaskStore } from '@modern-admin/core';
2
+ import type { PrismaDelegate } from '../types.js';
3
+ interface TaskRow {
4
+ id: string;
5
+ kind: string;
6
+ resourceId: string | null;
7
+ recordId: string | null;
8
+ userId: string | null;
9
+ status: string;
10
+ input: unknown;
11
+ output: unknown;
12
+ error: string | null;
13
+ progress: number | null;
14
+ createdAt: Date;
15
+ updatedAt: Date;
16
+ startedAt: Date | null;
17
+ finishedAt: Date | null;
18
+ }
19
+ interface EventRow {
20
+ id: string;
21
+ taskId: string;
22
+ type: string;
23
+ data: unknown;
24
+ createdAt: Date;
25
+ }
26
+ export declare class PrismaAiTaskStore implements IAiTaskStore {
27
+ private readonly taskDelegate;
28
+ private readonly eventDelegate;
29
+ constructor(taskDelegate: PrismaDelegate<TaskRow>, eventDelegate: PrismaDelegate<EventRow>);
30
+ enqueue(input: AiTaskInput): Promise<AiTask>;
31
+ get(id: string): Promise<AiTask | null>;
32
+ list(filter?: Parameters<IAiTaskStore['list']>[0]): Promise<AiTask[]>;
33
+ updateStatus(id: string, patch: {
34
+ status: AiTaskStatus;
35
+ progress?: number | null;
36
+ output?: Record<string, unknown>;
37
+ error?: string;
38
+ }): Promise<AiTask>;
39
+ appendEvent(taskId: string, type: string, data: Record<string, unknown>): Promise<AiTaskEvent>;
40
+ events(taskId: string, sinceId?: string): Promise<AiTaskEvent[]>;
41
+ }
42
+ export {};
43
+ //# sourceMappingURL=ai-task-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-task-store.d.ts","sourceRoot":"","sources":["../../src/stores/ai-task-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,UAAU,OAAO;IACf,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAA;CACxB;AAED,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,IAAI,CAAA;CAChB;AA+BD,qBAAa,iBAAkB,YAAW,YAAY;IAElD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,aAAa;gBADb,YAAY,EAAE,cAAc,CAAC,OAAO,CAAC,EACrC,aAAa,EAAE,cAAc,CAAC,QAAQ,CAAC;IAGpD,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB5C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKvC,IAAI,CAAC,MAAM,GAAE,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiBzE,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,MAAM,EAAE,YAAY,CAAA;QACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAChC,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GACA,OAAO,CAAC,MAAM,CAAC;IAiBZ,WAAW,CACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,WAAW,CAAC;IAOjB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CASvE"}
@@ -0,0 +1,108 @@
1
+ import { uuidv7, } from '@modern-admin/core';
2
+ const rowToTask = (row) => ({
3
+ id: row.id,
4
+ kind: row.kind,
5
+ ...(row.resourceId !== null ? { resourceId: row.resourceId } : {}),
6
+ ...(row.recordId !== null ? { recordId: row.recordId } : {}),
7
+ ...(row.userId !== null ? { userId: row.userId } : {}),
8
+ status: row.status,
9
+ input: row.input ?? {},
10
+ ...(row.output !== null && row.output !== undefined
11
+ ? { output: row.output }
12
+ : {}),
13
+ ...(row.error !== null ? { error: row.error } : {}),
14
+ progress: row.progress,
15
+ createdAt: row.createdAt.toISOString(),
16
+ updatedAt: row.updatedAt.toISOString(),
17
+ ...(row.startedAt !== null ? { startedAt: row.startedAt.toISOString() } : {}),
18
+ ...(row.finishedAt !== null ? { finishedAt: row.finishedAt.toISOString() } : {}),
19
+ });
20
+ const rowToEvent = (row) => ({
21
+ id: row.id,
22
+ taskId: row.taskId,
23
+ type: row.type,
24
+ data: row.data ?? {},
25
+ createdAt: row.createdAt.toISOString(),
26
+ });
27
+ const TERMINAL = ['succeeded', 'failed', 'cancelled'];
28
+ export class PrismaAiTaskStore {
29
+ constructor(taskDelegate, eventDelegate) {
30
+ this.taskDelegate = taskDelegate;
31
+ this.eventDelegate = eventDelegate;
32
+ }
33
+ async enqueue(input) {
34
+ const row = await this.taskDelegate.create({
35
+ data: {
36
+ id: uuidv7(),
37
+ kind: input.kind,
38
+ resourceId: input.resourceId ?? null,
39
+ recordId: input.recordId ?? null,
40
+ userId: input.userId ?? null,
41
+ status: 'pending',
42
+ input: input.input ?? {},
43
+ progress: null,
44
+ },
45
+ });
46
+ return rowToTask(row);
47
+ }
48
+ async get(id) {
49
+ const row = await this.taskDelegate.findUnique({ where: { id } });
50
+ return row ? rowToTask(row) : null;
51
+ }
52
+ async list(filter = {}) {
53
+ const where = {};
54
+ if (filter.kind)
55
+ where['kind'] = filter.kind;
56
+ if (filter.status) {
57
+ const list = Array.isArray(filter.status) ? filter.status : [filter.status];
58
+ where['status'] = { in: list };
59
+ }
60
+ if (filter.userId)
61
+ where['userId'] = filter.userId;
62
+ if (filter.resourceId)
63
+ where['resourceId'] = filter.resourceId;
64
+ const rows = await this.taskDelegate.findMany({
65
+ where,
66
+ orderBy: { createdAt: 'desc' },
67
+ ...(filter.limit !== undefined ? { take: filter.limit } : {}),
68
+ });
69
+ return rows.map(rowToTask);
70
+ }
71
+ async updateStatus(id, patch) {
72
+ const data = { status: patch.status };
73
+ if (patch.progress !== undefined)
74
+ data['progress'] = patch.progress;
75
+ if (patch.output !== undefined)
76
+ data['output'] = patch.output;
77
+ if (patch.error !== undefined)
78
+ data['error'] = patch.error;
79
+ if (patch.status === 'running') {
80
+ // only set startedAt the first time we transition to running
81
+ const current = await this.taskDelegate.findUnique({ where: { id } });
82
+ if (current && !current.startedAt)
83
+ data['startedAt'] = new Date();
84
+ }
85
+ if (TERMINAL.includes(patch.status)) {
86
+ data['finishedAt'] = new Date();
87
+ }
88
+ const row = await this.taskDelegate.update({ where: { id }, data });
89
+ return rowToTask(row);
90
+ }
91
+ async appendEvent(taskId, type, data) {
92
+ const row = await this.eventDelegate.create({
93
+ data: { id: uuidv7(), taskId, type, data },
94
+ });
95
+ return rowToEvent(row);
96
+ }
97
+ async events(taskId, sinceId) {
98
+ const all = await this.eventDelegate.findMany({
99
+ where: { taskId },
100
+ orderBy: { createdAt: 'asc' },
101
+ });
102
+ if (!sinceId)
103
+ return all.map(rowToEvent);
104
+ const idx = all.findIndex((r) => r.id === sinceId);
105
+ return (idx < 0 ? all : all.slice(idx + 1)).map(rowToEvent);
106
+ }
107
+ }
108
+ //# sourceMappingURL=ai-task-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-task-store.js","sourceRoot":"","sources":["../../src/stores/ai-task-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { CacheEntry, ICacheStore } from '@modern-admin/core';
2
+ import type { PrismaDelegate } from '../types.js';
3
+ interface CacheRow {
4
+ key: string;
5
+ value: unknown;
6
+ tags: unknown;
7
+ expiresAt: Date | null;
8
+ createdAt: Date;
9
+ updatedAt: Date;
10
+ }
11
+ export declare class PrismaCacheStore implements ICacheStore {
12
+ private readonly delegate;
13
+ constructor(delegate: PrismaDelegate<CacheRow>);
14
+ get(key: string): Promise<CacheEntry | null>;
15
+ set(key: string, value: unknown, options?: {
16
+ ttlMs?: number;
17
+ tags?: string[];
18
+ }): Promise<void>;
19
+ delete(key: string): Promise<void>;
20
+ /**
21
+ * Tag invalidation walks the table because Prisma's portable `Json` field
22
+ * doesn't support array-contains across all DB engines. For high-volume
23
+ * caches use a Postgres-specific implementation (`tags String[]`) or
24
+ * Redis. Here correctness > throughput by design.
25
+ */
26
+ invalidateTags(tags: string[]): Promise<number>;
27
+ prune(): Promise<number>;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=cache-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-store.d.ts","sourceRoot":"","sources":["../../src/stores/cache-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,UAAU,QAAQ;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,OAAO,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAChB;AAWD,qBAAa,gBAAiB,YAAW,WAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC;IAEzD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU5C,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GAChD,OAAO,CAAC,IAAI,CAAC;IAUV,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;;;;OAKG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/C,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAM/B"}
@@ -0,0 +1,61 @@
1
+ const rowToEntry = (row) => ({
2
+ key: row.key,
3
+ value: row.value,
4
+ tags: Array.isArray(row.tags) ? row.tags : [],
5
+ expiresAt: row.expiresAt ? row.expiresAt.toISOString() : null,
6
+ createdAt: row.createdAt.toISOString(),
7
+ updatedAt: row.updatedAt.toISOString(),
8
+ });
9
+ export class PrismaCacheStore {
10
+ constructor(delegate) {
11
+ this.delegate = delegate;
12
+ }
13
+ async get(key) {
14
+ const row = await this.delegate.findUnique({ where: { key } });
15
+ if (!row)
16
+ return null;
17
+ if (row.expiresAt && row.expiresAt.getTime() < Date.now()) {
18
+ await this.delegate.delete({ where: { key } }).catch(() => undefined);
19
+ return null;
20
+ }
21
+ return rowToEntry(row);
22
+ }
23
+ async set(key, value, options = {}) {
24
+ const expiresAt = options.ttlMs ? new Date(Date.now() + options.ttlMs) : null;
25
+ const tags = options.tags ?? [];
26
+ await this.delegate.upsert({
27
+ where: { key },
28
+ create: { key, value: value ?? null, tags, expiresAt },
29
+ update: { value: value ?? null, tags, expiresAt },
30
+ });
31
+ }
32
+ async delete(key) {
33
+ await this.delegate.delete({ where: { key } }).catch(() => undefined);
34
+ }
35
+ /**
36
+ * Tag invalidation walks the table because Prisma's portable `Json` field
37
+ * doesn't support array-contains across all DB engines. For high-volume
38
+ * caches use a Postgres-specific implementation (`tags String[]`) or
39
+ * Redis. Here correctness > throughput by design.
40
+ */
41
+ async invalidateTags(tags) {
42
+ if (!tags.length)
43
+ return 0;
44
+ const set = new Set(tags);
45
+ const rows = await this.delegate.findMany({});
46
+ const targets = rows.filter((r) => Array.isArray(r.tags) && r.tags.some((t) => set.has(t)));
47
+ if (!targets.length)
48
+ return 0;
49
+ const result = await this.delegate.deleteMany({
50
+ where: { key: { in: targets.map((r) => r.key) } },
51
+ });
52
+ return result.count;
53
+ }
54
+ async prune() {
55
+ const result = await this.delegate.deleteMany({
56
+ where: { expiresAt: { lt: new Date() } },
57
+ });
58
+ return result.count;
59
+ }
60
+ }
61
+ //# sourceMappingURL=cache-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-store.js","sourceRoot":"","sources":["../../src/stores/cache-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type ConfigEntry, type ConfigScope, type IConfigStore } from '@modern-admin/core';
2
+ import type { PrismaDelegate } from '../types.js';
3
+ interface ConfigRow {
4
+ id: string;
5
+ scope: string;
6
+ scopeId: string;
7
+ key: string;
8
+ value: unknown;
9
+ updatedAt: Date;
10
+ }
11
+ export declare class PrismaConfigStore implements IConfigStore {
12
+ private readonly delegate;
13
+ constructor(delegate: PrismaDelegate<ConfigRow>);
14
+ get(scope: ConfigScope, scopeId: string | null, key: string): Promise<unknown>;
15
+ set(scope: ConfigScope, scopeId: string | null, key: string, value: unknown): Promise<void>;
16
+ delete(scope: ConfigScope, scopeId: string | null, key: string): Promise<void>;
17
+ list(scope: ConfigScope, scopeId: string | null): Promise<ConfigEntry[]>;
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/stores/config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAU,MAAM,oBAAoB,CAAA;AAClG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,OAAO,CAAA;IACd,SAAS,EAAE,IAAI,CAAA;CAChB;AAcD,qBAAa,iBAAkB,YAAW,YAAY;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,cAAc,CAAC,SAAS,CAAC;IAG1D,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU9E,GAAG,CACP,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC;IAsBV,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9E,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAO/E"}
@@ -0,0 +1,61 @@
1
+ import { uuidv7 } from '@modern-admin/core';
2
+ const GLOBAL_SCOPE_ID = '';
3
+ const encodeScopeId = (scopeId) => scopeId ?? GLOBAL_SCOPE_ID;
4
+ const decodeScopeId = (scopeId) => scopeId === GLOBAL_SCOPE_ID ? null : scopeId;
5
+ const rowToEntry = (row) => ({
6
+ scope: row.scope,
7
+ scopeId: decodeScopeId(row.scopeId),
8
+ key: row.key,
9
+ value: row.value,
10
+ updatedAt: row.updatedAt.toISOString(),
11
+ });
12
+ export class PrismaConfigStore {
13
+ constructor(delegate) {
14
+ this.delegate = delegate;
15
+ }
16
+ async get(scope, scopeId, key) {
17
+ // findFirst instead of findUnique: tolerates accidental duplicates and
18
+ // returns the most-recently-updated row rather than throwing.
19
+ const row = await this.delegate.findFirst({
20
+ where: { scope, scopeId: encodeScopeId(scopeId), key },
21
+ orderBy: { updatedAt: 'desc' },
22
+ });
23
+ return row?.value;
24
+ }
25
+ async set(scope, scopeId, key, value) {
26
+ const encodedScopeId = encodeScopeId(scopeId);
27
+ // Use findFirst + update-by-id / create instead of upsert with a
28
+ // compound unique key. Prisma 7 + PrismaPg adapter can misidentify
29
+ // compound-key upserts and issue a second INSERT rather than an UPDATE,
30
+ // which violates the unique constraint. Anchoring the update on the
31
+ // surrogate id is always safe.
32
+ const existing = await this.delegate.findFirst({
33
+ where: { scope, scopeId: encodedScopeId, key },
34
+ });
35
+ if (existing) {
36
+ await this.delegate.update({
37
+ where: { id: existing.id },
38
+ data: { value: value ?? null },
39
+ });
40
+ }
41
+ else {
42
+ await this.delegate.create({
43
+ data: { id: uuidv7(), scope, scopeId: encodedScopeId, key, value: value ?? null },
44
+ });
45
+ }
46
+ }
47
+ async delete(scope, scopeId, key) {
48
+ // deleteMany avoids "record not found" and also cleans up any duplicates.
49
+ await this.delegate
50
+ .deleteMany({ where: { scope, scopeId: encodeScopeId(scopeId), key } })
51
+ .catch(() => undefined);
52
+ }
53
+ async list(scope, scopeId) {
54
+ const rows = await this.delegate.findMany({
55
+ where: { scope, scopeId: encodeScopeId(scopeId) },
56
+ orderBy: { key: 'asc' },
57
+ });
58
+ return rows.map(rowToEntry);
59
+ }
60
+ }
61
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/stores/config-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type HistoryEntry, type HistoryOp, type IHistoryStore } from '@modern-admin/core';
2
+ import type { PrismaDelegate } from '../types.js';
3
+ interface HistoryRow {
4
+ id: string;
5
+ resourceId: string;
6
+ recordId: string;
7
+ op: string;
8
+ userId: string | null;
9
+ snapshot: unknown;
10
+ snapshotBefore: unknown;
11
+ diff: unknown;
12
+ createdAt: Date;
13
+ }
14
+ export declare class PrismaHistoryStore implements IHistoryStore {
15
+ private readonly delegate;
16
+ constructor(delegate: PrismaDelegate<HistoryRow>);
17
+ append(input: {
18
+ resourceId: string;
19
+ recordId: string;
20
+ op: HistoryOp;
21
+ userId?: string;
22
+ snapshot: Record<string, unknown>;
23
+ snapshotBefore?: Record<string, unknown>;
24
+ }): Promise<HistoryEntry>;
25
+ list(resourceId: string, recordId: string, options?: {
26
+ limit?: number;
27
+ offset?: number;
28
+ }): Promise<HistoryEntry[]>;
29
+ get(resourceId: string, recordId: string, revisionId: string): Promise<HistoryEntry | null>;
30
+ latest(resourceId: string, recordId: string): Promise<HistoryEntry | null>;
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=history-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-store.d.ts","sourceRoot":"","sources":["../../src/stores/history-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,IAAI,CAAA;CAChB;AAeD,qBAAa,kBAAmB,YAAW,aAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC;IAE3D,MAAM,CAAC,KAAK,EAAE;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,EAAE,EAAE,SAAS,CAAA;QACb,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACzC,GAAG,OAAO,CAAC,YAAY,CAAC;IAenB,IAAI,CACR,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAChD,OAAO,CAAC,YAAY,EAAE,CAAC;IAYpB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAO3F,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAOjF"}
@@ -0,0 +1,57 @@
1
+ import { uuidv7 } from '@modern-admin/core';
2
+ const rowToEntry = (row) => ({
3
+ id: row.id,
4
+ resourceId: row.resourceId,
5
+ recordId: row.recordId,
6
+ op: row.op,
7
+ ...(row.userId !== null ? { userId: row.userId } : {}),
8
+ snapshot: row.snapshot ?? {},
9
+ ...(row.snapshotBefore !== null && row.snapshotBefore !== undefined
10
+ ? { snapshotBefore: row.snapshotBefore }
11
+ : {}),
12
+ createdAt: row.createdAt.toISOString(),
13
+ });
14
+ export class PrismaHistoryStore {
15
+ constructor(delegate) {
16
+ this.delegate = delegate;
17
+ }
18
+ async append(input) {
19
+ const row = await this.delegate.create({
20
+ data: {
21
+ id: uuidv7(),
22
+ resourceId: input.resourceId,
23
+ recordId: input.recordId,
24
+ op: input.op,
25
+ userId: input.userId ?? null,
26
+ snapshot: input.snapshot,
27
+ snapshotBefore: input.snapshotBefore ?? null,
28
+ },
29
+ });
30
+ return rowToEntry(row);
31
+ }
32
+ async list(resourceId, recordId, options = {}) {
33
+ const limit = options.limit ?? 50;
34
+ const offset = options.offset ?? 0;
35
+ const rows = await this.delegate.findMany({
36
+ where: { resourceId, recordId },
37
+ orderBy: { createdAt: 'desc' },
38
+ take: limit,
39
+ ...(offset > 0 ? { skip: offset } : {}),
40
+ });
41
+ return rows.map(rowToEntry);
42
+ }
43
+ async get(resourceId, recordId, revisionId) {
44
+ const row = await this.delegate.findFirst({
45
+ where: { id: revisionId, resourceId, recordId },
46
+ });
47
+ return row ? rowToEntry(row) : null;
48
+ }
49
+ async latest(resourceId, recordId) {
50
+ const row = await this.delegate.findFirst({
51
+ where: { resourceId, recordId },
52
+ orderBy: { createdAt: 'desc' },
53
+ });
54
+ return row ? rowToEntry(row) : null;
55
+ }
56
+ }
57
+ //# sourceMappingURL=history-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-store.js","sourceRoot":"","sources":["../../src/stores/history-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type ActionLogEntry, type ILogStore, type IQueryableLogStore } from '@modern-admin/core';
2
+ import type { PrismaDelegate } from '../types.js';
3
+ interface LogRow {
4
+ id: string;
5
+ resourceId: string;
6
+ action: string;
7
+ recordId: string | null;
8
+ recordIds: unknown;
9
+ userId: string | null;
10
+ payload: unknown;
11
+ result: unknown;
12
+ at: bigint;
13
+ createdAt: Date;
14
+ }
15
+ export declare class PrismaLogStore implements IQueryableLogStore {
16
+ private readonly delegate;
17
+ constructor(delegate: PrismaDelegate<LogRow>);
18
+ record(entry: ActionLogEntry): Promise<void>;
19
+ list(filter?: Parameters<IQueryableLogStore['list']>[0]): Promise<ActionLogEntry[]>;
20
+ }
21
+ /** Narrow type-test: a pure `ILogStore` is enough where readback isn't needed. */
22
+ export type { ILogStore };
23
+ //# sourceMappingURL=log-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["../../src/stores/log-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACzG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,IAAI,CAAA;CAChB;AAkBD,qBAAa,cAAe,YAAW,kBAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC;IAEvD,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5C,IAAI,CAAC,MAAM,GAAE,UAAU,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAoB9F;AAED,kFAAkF;AAClF,YAAY,EAAE,SAAS,EAAE,CAAA"}