@mostajs/audit 2.2.2 → 2.3.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/lib/audit-factory.d.ts +10 -1
- package/dist/lib/audit-factory.js +31 -13
- package/llms.txt +130 -0
- package/package.json +19 -14
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { logAudit, getAuditUser } from './lib/audit';
|
|
2
|
+
export { configureAudit, getAuditRepo, resetAuditRepo, type IAuditLogRepository } from './lib/audit-factory';
|
|
2
3
|
export { dlog, dwarn, createLogger, isDebugEnabled, type ScopedLogger } from './lib/debug-log';
|
|
3
4
|
export { AuditLogRepository } from './repositories/audit-log.repository';
|
|
4
5
|
export { AuditLogSchema } from './schemas/audit-log.schema';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
3
3
|
// Core
|
|
4
4
|
export { logAudit, getAuditUser } from './lib/audit';
|
|
5
|
+
// Configuration (DI) : l'hôte injecte son dialecte ORM (depuis son .env) — voie recommandée.
|
|
6
|
+
export { configureAudit, getAuditRepo, resetAuditRepo } from './lib/audit-factory';
|
|
5
7
|
// Volatile debug logger (complement de logAudit pour la trace pm2/stdout)
|
|
6
8
|
export { dlog, dwarn, createLogger, isDebugEnabled } from './lib/debug-log';
|
|
7
9
|
// Repository & Schema
|
|
@@ -8,7 +8,16 @@ export interface IAuditLogRepository {
|
|
|
8
8
|
findByResource(resourceId: string, modules?: string[]): Promise<AuditLogDTO[]>;
|
|
9
9
|
deleteOlderThan(days: number): Promise<number>;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Injection de dépendance (RECOMMANDÉ) : l'application hôte fournit SON dialecte ORM, construit
|
|
13
|
+
* depuis SON `.env`. C'est la voie la moins dépendante et la moins risquée — aucun résolveur,
|
|
14
|
+
* aucune seconde instance d'ORM (donc pas de double-package). Sans injection, repli sur
|
|
15
|
+
* `@mostajs/data-plug` (résolution depuis le `.env` de l'hôte).
|
|
16
|
+
*/
|
|
17
|
+
export declare function configureAudit(opts: {
|
|
18
|
+
dialect: unknown;
|
|
19
|
+
}): void;
|
|
20
|
+
/** Get audit repository — dialecte injecté (DI) sinon résolu depuis le `.env` via data-plug. */
|
|
12
21
|
export declare function getAuditRepo(): Promise<IAuditLogRepository>;
|
|
13
22
|
/** Reset cache (for tests) */
|
|
14
23
|
export declare function resetAuditRepo(): void;
|
|
@@ -1,26 +1,44 @@
|
|
|
1
1
|
// audit-factory.ts — Centralized repository factory
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
2
|
+
// DI-first : l'application hôte injecte SON dialecte (depuis SON .env). Repli optionnel sur
|
|
3
|
+
// @mostajs/data-plug (remplace @mostajs/octoswitcher). Aucune dépendance dure de résolveur.
|
|
4
|
+
// Author: Dr Hamid MADANI <drmdh@msn.com>
|
|
5
5
|
// ============================================================
|
|
6
|
-
// Factory —
|
|
6
|
+
// Factory — DI-first, repli .env via data-plug
|
|
7
7
|
// ============================================================
|
|
8
8
|
let _cached = null;
|
|
9
|
-
|
|
9
|
+
let _injectedDialect = null;
|
|
10
|
+
/**
|
|
11
|
+
* Injection de dépendance (RECOMMANDÉ) : l'application hôte fournit SON dialecte ORM, construit
|
|
12
|
+
* depuis SON `.env`. C'est la voie la moins dépendante et la moins risquée — aucun résolveur,
|
|
13
|
+
* aucune seconde instance d'ORM (donc pas de double-package). Sans injection, repli sur
|
|
14
|
+
* `@mostajs/data-plug` (résolution depuis le `.env` de l'hôte).
|
|
15
|
+
*/
|
|
16
|
+
export function configureAudit(opts) {
|
|
17
|
+
if (opts && opts.dialect) {
|
|
18
|
+
_injectedDialect = opts.dialect;
|
|
19
|
+
_cached = null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Get audit repository — dialecte injecté (DI) sinon résolu depuis le `.env` via data-plug. */
|
|
10
23
|
export async function getAuditRepo() {
|
|
11
24
|
if (_cached)
|
|
12
25
|
return _cached;
|
|
13
|
-
const { getDialect } = await import('@mostajs/octoswitcher');
|
|
14
|
-
const { registerSchemas } = await import('@mostajs/orm');
|
|
15
26
|
const { AuditLogRepository } = await import('../repositories/audit-log.repository.js');
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
await dialect.initSchema(getAllSchemas());
|
|
27
|
+
// 1) Dialecte injecté par l'hôte (DI) — chemin principal, zéro dépendance résolveur.
|
|
28
|
+
if (_injectedDialect) {
|
|
29
|
+
_cached = new AuditLogRepository(_injectedDialect);
|
|
30
|
+
return _cached;
|
|
21
31
|
}
|
|
32
|
+
// 2) Repli : résolution depuis le `.env` de l'hôte via @mostajs/data-plug (remplace octoswitcher).
|
|
33
|
+
// Import par spécifieur variable → dépendance OPTIONNELLE (inutile si l'hôte injecte).
|
|
34
|
+
const spec = '@mostajs/data-plug';
|
|
35
|
+
const mod = (await import(spec));
|
|
36
|
+
const dialect = await mod.getDialect();
|
|
22
37
|
_cached = new AuditLogRepository(dialect);
|
|
23
38
|
return _cached;
|
|
24
39
|
}
|
|
25
40
|
/** Reset cache (for tests) */
|
|
26
|
-
export function resetAuditRepo() {
|
|
41
|
+
export function resetAuditRepo() {
|
|
42
|
+
_cached = null;
|
|
43
|
+
_injectedDialect = null;
|
|
44
|
+
}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @mostajs/audit — fiche LLM
|
|
2
|
+
> Journalisation d'audit fire-and-forget : logAudit() non bloquant + consultation paginée, stats, export CSV/JSON.
|
|
3
|
+
|
|
4
|
+
- Version: 2.2.2 · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
|
|
5
|
+
- Chemin: mostajs/mosta-audit · Statut audit: complet (dist/)
|
|
6
|
+
|
|
7
|
+
## RÔLE
|
|
8
|
+
Module de journalisation d'audit de l'écosystème mostajs. Expose un `logAudit()` fire-and-forget — il ne lève jamais d'exception et ne bloque jamais le flux appelant — pour tracer les actions métier (création, modification, suppression…). Fournit la consultation paginée et filtrée des logs (handler API Next.js), un export CSV/JSON, des statistiques agrégées, une page d'administration et un logger debug volatile complémentaire (stdout/pm2). Fonctionne en mode ORM ou NET selon `MOSTA_DATA`.
|
|
9
|
+
|
|
10
|
+
## INSTALLATION
|
|
11
|
+
npm i @mostajs/audit @mostajs/orm
|
|
12
|
+
|
|
13
|
+
## EXPORTS
|
|
14
|
+
Point d'entrée racine (`.`) :
|
|
15
|
+
- Core: logAudit, getAuditUser
|
|
16
|
+
- Debug logger: dlog, dwarn, createLogger, isDebugEnabled
|
|
17
|
+
- Repository/Schéma: AuditLogRepository, AuditLogSchema
|
|
18
|
+
- API: createAuditHandlers, createAuditExportHandler
|
|
19
|
+
- Export: auditToCsv, auditToJson
|
|
20
|
+
- Stats: getAuditStats
|
|
21
|
+
- Menu/i18n/Page: auditMenuContribution, auditT, AuditPage (default)
|
|
22
|
+
- Types: MostaAuditConfig, AuditParams, AuditFilters, AuditLogDTO, ExportOptions, AuditStats, ScopedLogger
|
|
23
|
+
|
|
24
|
+
## EXPORTS PAR SOUS-CHEMIN
|
|
25
|
+
- `./lib/audit` — logAudit, getAuditUser
|
|
26
|
+
- `./api/route` — createAuditHandlers
|
|
27
|
+
- `./types` — MostaAuditConfig, AuditParams, AuditFilters, AuditLogDTO
|
|
28
|
+
- `./lib/menu` — auditMenuContribution
|
|
29
|
+
- `./register` — register(registry)
|
|
30
|
+
- `./pages/AuditPage` — page d'administration
|
|
31
|
+
- `./lib/i18n` — t (auditT)
|
|
32
|
+
- `./lib/module-info` — getSchemas, moduleInfo (pour @mostajs/setup)
|
|
33
|
+
- `./lib/export` — auditToCsv, auditToJson ; type ExportOptions
|
|
34
|
+
- `./lib/audit-stats` — getAuditStats ; type AuditStats
|
|
35
|
+
- `./lib/handlers/audit-export` — createAuditExportHandler
|
|
36
|
+
- `./lib/debug-log` — dlog, dwarn, createLogger, isDebugEnabled ; type ScopedLogger
|
|
37
|
+
- `./schemas/audit-log.schema` — AuditLogSchema
|
|
38
|
+
- `./repositories/audit-log.repository` — AuditLogRepository
|
|
39
|
+
|
|
40
|
+
## API — SIGNATURES
|
|
41
|
+
logAudit(params: AuditParams): Promise<void> // fire-and-forget : ne throw jamais, ne bloque jamais
|
|
42
|
+
getAuditUser(session: any): { userId, userName, userRole } // extrait d'une session NextAuth
|
|
43
|
+
createAuditHandlers(permission: string, checkPermission: PermissionChecker): { GET } // consultation paginée
|
|
44
|
+
createAuditExportHandler(...) // handler d'export
|
|
45
|
+
auditToCsv(logs: any[]): string · auditToJson(logs: any[]): string
|
|
46
|
+
getAuditStats(repo: any, days?: number): Promise<AuditStats>
|
|
47
|
+
dlog(scope, data): void // actif si MOSTAJS_DEBUG=1 ou hors prod
|
|
48
|
+
dwarn(scope, data): void // toujours actif
|
|
49
|
+
createLogger(namespace: string): ScopedLogger // { dlog, dwarn }
|
|
50
|
+
isDebugEnabled(): boolean
|
|
51
|
+
|
|
52
|
+
AuditLogRepository extends BaseRepository<AuditLogDTO> (dialect: IDialect) :
|
|
53
|
+
findPaginated(filters?: AuditFilters, options?): Promise<{ data: AuditLogDTO[], total: number }>
|
|
54
|
+
findByResource(resourceId, modules?, options?): Promise<AuditLogDTO[]>
|
|
55
|
+
deleteOlderThan(days: number): Promise<number> // rétention / purge
|
|
56
|
+
|
|
57
|
+
PermissionChecker = (permission: string) => Promise<{ error: NextResponse|null, session: any }>
|
|
58
|
+
|
|
59
|
+
## TYPES CLÉS
|
|
60
|
+
AuditParams { userId, userName, userRole, action, module, resource?, resourceId?, details?:Record<string,any>, ipAddress?, status?:'success'|'failure' }
|
|
61
|
+
AuditLogDTO { id, userId, userName, userRole, action, module, resource, resourceId, details:Record|null, ipAddress, status:'success'|'failure', timestamp }
|
|
62
|
+
AuditFilters { module?, action?, userId?, status?, from?:Date, to?:Date, page?, limit? }
|
|
63
|
+
MostaAuditConfig { modules?:string[], actions?:string[] } // valeurs pour les filtres UI
|
|
64
|
+
AuditStats { totalLogs, byModule:Record<string,number>, byAction:Record<string,number>, byStatus:{success,failure}, topUsers:[{userName,count}], recentErrors[] }
|
|
65
|
+
ExportOptions { format:'csv'|'json', from?, to?, module?, action?, limit? }
|
|
66
|
+
ScopedLogger { dlog(scope,data), dwarn(scope,data) }
|
|
67
|
+
|
|
68
|
+
## PATTERN
|
|
69
|
+
```ts
|
|
70
|
+
// Tracer une action
|
|
71
|
+
import { logAudit, getAuditUser } from '@mostajs/audit'
|
|
72
|
+
await logAudit({
|
|
73
|
+
...getAuditUser(session),
|
|
74
|
+
action: 'user_create',
|
|
75
|
+
module: 'users',
|
|
76
|
+
resource: 'John Doe',
|
|
77
|
+
resourceId: user.id,
|
|
78
|
+
details: { email: 'john@x.com' },
|
|
79
|
+
status: 'success',
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Route de consultation Next.js
|
|
83
|
+
import { createAuditHandlers } from '@mostajs/audit/api/route'
|
|
84
|
+
export const { GET } = createAuditHandlers('audit:view', checkPermission)
|
|
85
|
+
// GET /api/audit-log?page=1&limit=50&module=users&action=create
|
|
86
|
+
|
|
87
|
+
// Purge de rétention
|
|
88
|
+
const repo = new AuditLogRepository(await getDialect())
|
|
89
|
+
await repo.deleteOlderThan(90)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## INTÉGRATION (DI-first, depuis le .env de l'hôte) — depuis 2.3.0
|
|
93
|
+
`getAuditRepo()`/`logAudit()` résolvent le dialecte ainsi :
|
|
94
|
+
1. **Injecté** par l'hôte (RECOMMANDÉ) : `configureAudit({ dialect })` — zéro résolveur, copie ORM unique.
|
|
95
|
+
2. **Repli** : `@mostajs/data-plug` (`getDialect()` lit le `.env` de l'hôte) — remplace octoswitcher, optionnel.
|
|
96
|
+
```ts
|
|
97
|
+
import { configureAudit } from '@mostajs/audit' // ou '@mostajs/audit/lib/audit-factory'
|
|
98
|
+
import { logAudit } from '@mostajs/audit/lib/audit'
|
|
99
|
+
import { AuditLogSchema } from '@mostajs/audit/schemas/audit-log.schema'
|
|
100
|
+
import { AuditLogRepository } from '@mostajs/audit/repositories/audit-log.repository'
|
|
101
|
+
|
|
102
|
+
// 1) Ajouter AuditLogSchema à VOS schémas (migration crée la table `auditlogs`).
|
|
103
|
+
// ⚠ relation `userId → User` (m2o, requise) : l'hôte DOIT exposer un schéma `name:"User"`.
|
|
104
|
+
// 2) Injecter VOTRE dialecte (construit depuis VOTRE .env) — une fois :
|
|
105
|
+
configureAudit({ dialect: await getOrm() })
|
|
106
|
+
// 3) Tracer (fire-and-forget) :
|
|
107
|
+
await logAudit({ userId, userName, userRole, action: 'order.create', module: 'commandes', resource: '2026-…' })
|
|
108
|
+
// 4) Consulter : new AuditLogRepository(await getOrm()).findPaginated(filters) → { data, total } ; UI native.
|
|
109
|
+
```
|
|
110
|
+
> En test : importer par SOUS-CHEMINS (la racine charge AuditPage → lucide-react). Voir @mostajs/mjs-unit.
|
|
111
|
+
|
|
112
|
+
## DÉPEND DE (depuis 2.3.0 — « le moins dépendant »)
|
|
113
|
+
- **Aucune dépendance dure** (`dependencies: {}`).
|
|
114
|
+
- Peers : **@mostajs/orm** (requis — l'hôte le fournit → copie unique, pas de double-package) ;
|
|
115
|
+
**@mostajs/data-plug** (optionnel — uniquement pour le repli `.env`) ; @mostajs/menu/socle/ui, lucide-react,
|
|
116
|
+
next, react (tous optionnels, UI seulement).
|
|
117
|
+
- ❌ Retirés : @mostajs/net (inutilisé), @mostajs/octoswitcher (→ remplacé par data-plug, optionnel).
|
|
118
|
+
|
|
119
|
+
## PIÈGES
|
|
120
|
+
- logAudit est volontairement fire-and-forget : il avale ses propres erreurs (échec d'écriture audit → silencieux). Ne pas s'en servir comme garantie transactionnelle ; ne pas l'attendre comme bloquant critique.
|
|
121
|
+
- logAudit ≠ debug-log : `logAudit` persiste en DB ; `dlog`/`dwarn` ne font que tracer en stdout (volatile, pour pm2). dlog n'est actif que si `MOSTAJS_DEBUG=1` ou hors production ; dwarn est toujours actif.
|
|
122
|
+
- createAuditHandlers exige une callback `checkPermission` (typiquement fournie par `@mostajs/auth`) ; le module ne gère pas la session.
|
|
123
|
+
- Le mode de données (ORM/NET) est piloté par `MOSTA_DATA` ; le repo factory interne lit l'environnement automatiquement.
|
|
124
|
+
- getAuditUser attend une session de forme NextAuth ; si la forme diffère, fournir manuellement userId/userName/userRole.
|
|
125
|
+
- deleteOlderThan supprime définitivement les lignes : prévoir l'archivage avant purge si rétention légale.
|
|
126
|
+
|
|
127
|
+
## RÉFÉRENCES
|
|
128
|
+
- README.md (racine du module)
|
|
129
|
+
- audit.wire.json, wire.json — déclaration de câblage
|
|
130
|
+
- LICENSE (AGPL-3.0-or-later)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/audit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Reusable audit logging module — fire-and-forget logAudit() with paginated consultation",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -90,7 +90,8 @@
|
|
|
90
90
|
"wire.json",
|
|
91
91
|
"audit.wire.json",
|
|
92
92
|
"LICENSE",
|
|
93
|
-
"README.md"
|
|
93
|
+
"README.md",
|
|
94
|
+
"llms.txt"
|
|
94
95
|
],
|
|
95
96
|
"keywords": [
|
|
96
97
|
"audit",
|
|
@@ -107,17 +108,15 @@
|
|
|
107
108
|
"engines": {
|
|
108
109
|
"node": ">=18.0.0"
|
|
109
110
|
},
|
|
110
|
-
"scripts": {
|
|
111
|
-
"build": "tsc",
|
|
112
|
-
"prepublishOnly": "npm run build"
|
|
113
|
-
},
|
|
114
111
|
"peerDependencies": {
|
|
115
112
|
"@mostajs/menu": ">=1.0.2",
|
|
116
113
|
"@mostajs/socle": ">=2.0.0",
|
|
117
114
|
"@mostajs/ui": ">=1.0.0",
|
|
118
115
|
"lucide-react": ">=0.400.0",
|
|
119
116
|
"next": ">=14",
|
|
120
|
-
"react": ">=18"
|
|
117
|
+
"react": ">=18",
|
|
118
|
+
"@mostajs/orm": ">=1.7.0",
|
|
119
|
+
"@mostajs/data-plug": ">=1.0.0"
|
|
121
120
|
},
|
|
122
121
|
"peerDependenciesMeta": {
|
|
123
122
|
"next": {
|
|
@@ -134,6 +133,12 @@
|
|
|
134
133
|
},
|
|
135
134
|
"lucide-react": {
|
|
136
135
|
"optional": true
|
|
136
|
+
},
|
|
137
|
+
"@mostajs/data-plug": {
|
|
138
|
+
"optional": true
|
|
139
|
+
},
|
|
140
|
+
"@mostajs/socle": {
|
|
141
|
+
"optional": true
|
|
137
142
|
}
|
|
138
143
|
},
|
|
139
144
|
"devDependencies": {
|
|
@@ -145,15 +150,15 @@
|
|
|
145
150
|
"lucide-react": "^0.575.0",
|
|
146
151
|
"next": "^16.1.6",
|
|
147
152
|
"react": "^19.0.0",
|
|
148
|
-
"typescript": "^5.6.0"
|
|
149
|
-
|
|
150
|
-
"dependencies": {
|
|
151
|
-
"@mostajs/net": "^2.0.0",
|
|
152
|
-
"@mostajs/octoswitcher": "^1.0.0",
|
|
153
|
-
"@mostajs/orm": "^1.7.0"
|
|
153
|
+
"typescript": "^5.6.0",
|
|
154
|
+
"@mostajs/mjs-unit": "^0.3.0"
|
|
154
155
|
},
|
|
155
156
|
"funding": {
|
|
156
157
|
"type": "github",
|
|
157
158
|
"url": "https://github.com/sponsors/apolocine"
|
|
159
|
+
},
|
|
160
|
+
"scripts": {
|
|
161
|
+
"build": "tsc",
|
|
162
|
+
"test": "bash test-scripts/run-tests.sh"
|
|
158
163
|
}
|
|
159
|
-
}
|
|
164
|
+
}
|