@juice-js/audit 0.0.0-stage → 1.0.0-alpha.2

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.
@@ -0,0 +1,216 @@
1
+ import * as i0 from "@angular/core";
2
+ import { EnvironmentProviders, InjectionToken, PipeTransform } from "@angular/core";
3
+ import { Observable } from "rxjs";
4
+ import { Params, Routes } from "@angular/router";
5
+ import { Menus } from "@juice-js/core";
6
+ /** How the host app mounts Juice Audit. */
7
+ export interface AuditOptions {
8
+ /** The origin of the API that maps MapJuiceAudit(); empty when it serves the app (same origin). */
9
+ apiBase: string;
10
+ /** Where MapJuiceAudit() mapped the API on that origin (its `prefix`). */
11
+ apiPath: string;
12
+ /** Where the host mounts {@link AUDIT_ROUTES}: `/` for the whole app, or a path such as `/audit`. */
13
+ basePath: string;
14
+ /**
15
+ * A link to a trace in a tracing UI, shown beside the trace id of each record: for the Juice Observability pages
16
+ * mounted at `/observability`, `id => ['/observability/traces', id]`. A string is an external URL. Without it, no link.
17
+ */
18
+ traceLink?: ((traceId: string) => unknown[] | string | null) | null;
19
+ }
20
+ export declare const AUDIT_OPTIONS: InjectionToken<AuditOptions>;
21
+ /** Configures the pages: where the API is, where the host mounted the routes, and where a trace opens. */
22
+ export declare function provideJuiceAudit(options?: Partial<AuditOptions>): EnvironmentProviders;
23
+ /** `/audit/` → `/audit`; `` and `/` → `/`. */
24
+ export declare function normalizeBasePath(basePath: string): string;
25
+ /** Router links to the pages, under the host's mount path. */
26
+ export declare class AuditLinks {
27
+ private readonly options;
28
+ readonly base: string;
29
+ /** `to('access-logs', id)` → `['/audit', 'access-logs', id]`. */
30
+ to(...segments: unknown[]): unknown[];
31
+ /** The host's link to a trace in its tracing UI, if it gave one. */
32
+ externalTrace(traceId: string | null | undefined): {
33
+ route: unknown[];
34
+ } | {
35
+ href: string;
36
+ } | null;
37
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuditLinks, never>;
38
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
39
+ }
40
+ /** `['access-logs', id] | jaLink`: the same as {@link AuditLinks.to} in a template. */
41
+ export declare class AuditLinkPipe implements PipeTransform {
42
+ private readonly links;
43
+ transform(segments: unknown[]): unknown[];
44
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuditLinkPipe, never>;
45
+ static ɵpipe: i0.ɵɵPipeDeclaration<AuditLinkPipe, "jaLink", true>;
46
+ }
47
+ /** The audit API's shapes (Juice.Audit.Api, MapJuiceAudit()). Times are ISO 8601. */
48
+ export interface AuditPage<T> {
49
+ items: T[];
50
+ nextCursor?: string | null;
51
+ }
52
+ /** One audited HTTP request, message, mediator request or notification. */
53
+ export interface AccessLogSummary {
54
+ id: string;
55
+ dateTime: string;
56
+ user: string | null;
57
+ tenantId: string | null;
58
+ action: string;
59
+ /** The HTTP method, or MESSAGE, REQUEST or NOTIFICATION for work outside a request. */
60
+ method: string | null;
61
+ path: string | null;
62
+ status: number | null;
63
+ elapsedMs: number | null;
64
+ app: string | null;
65
+ traceId: string | null;
66
+ isRestricted: boolean;
67
+ }
68
+ export interface AccessLogDetail {
69
+ id: string;
70
+ dateTime: string;
71
+ user: string | null;
72
+ tenantId: string | null;
73
+ action: string;
74
+ traceId: string | null;
75
+ isRestricted: boolean;
76
+ metadata: Record<string, string | null>;
77
+ request: {
78
+ method: string | null;
79
+ scheme: string | null;
80
+ host: string | null;
81
+ path: string | null;
82
+ query: string | null;
83
+ headers: string | null;
84
+ data: string | null;
85
+ remoteIp: string | null;
86
+ zone: string | null;
87
+ } | null;
88
+ response: {
89
+ status: number | null;
90
+ elapsedMs: number | null;
91
+ message: string | null;
92
+ error: string | null;
93
+ headers: string | null;
94
+ data: string | null;
95
+ } | null;
96
+ server: {
97
+ app: string | null;
98
+ appVersion: string | null;
99
+ machine: string | null;
100
+ os: string | null;
101
+ } | null;
102
+ /** Data changes recorded under the same trace id. */
103
+ dataChanges: number;
104
+ }
105
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
106
+ [key: string]: JsonValue;
107
+ };
108
+ /** A row change: inserted, modified or deleted, with its keys. */
109
+ export interface DataChangeSummary {
110
+ id: string;
111
+ dateTime: string;
112
+ user: string | null;
113
+ tenantId: string | null;
114
+ action: string;
115
+ database: string | null;
116
+ schema: string | null;
117
+ table: string;
118
+ keys: JsonValue;
119
+ traceId: string | null;
120
+ }
121
+ export interface DataChangeDetail extends DataChangeSummary {
122
+ /** `{ OriginalValues: {…}, CurrentValues: {…} }`, as the audited app reported them. */
123
+ changes: JsonValue;
124
+ }
125
+ export interface AuditTrace {
126
+ traceId: string;
127
+ accessLogs: AccessLogDetail[];
128
+ dataChanges: DataChangeDetail[];
129
+ /** More records share the trace than the API returns. */
130
+ truncated: boolean;
131
+ }
132
+ export interface AuditCount {
133
+ name: string;
134
+ count: number;
135
+ errors: number;
136
+ }
137
+ export interface AuditOverview {
138
+ from: string;
139
+ to: string;
140
+ requests: number;
141
+ clientErrors: number;
142
+ serverErrors: number;
143
+ restricted: number;
144
+ dataChanges: number;
145
+ statuses: AuditCount[];
146
+ apps: AuditCount[];
147
+ users: AuditCount[];
148
+ tables: AuditCount[];
149
+ changeActions: AuditCount[];
150
+ recentErrors: AccessLogSummary[];
151
+ slowest: AccessLogSummary[];
152
+ }
153
+ /** An access record's list row, from its detail (the trace endpoint returns details). */
154
+ export declare function accessLogSummary(d: AccessLogDetail): AccessLogSummary;
155
+ export type AuditQuery = Record<string, string | number | boolean | null | undefined>;
156
+ /**
157
+ * The audit API that Juice.Audit.Api maps with MapJuiceAudit(). It is scoped to the caller's tenant on the server, and
158
+ * the host's bearer-token interceptor authenticates the calls.
159
+ */
160
+ export declare class AuditApiService {
161
+ private readonly http;
162
+ private readonly base;
163
+ private get;
164
+ /** Access records, newest first; pass the previous page's `nextCursor` as `cursor` for the next. */
165
+ accessLogs(query: AuditQuery): Observable<AuditPage<AccessLogSummary>>;
166
+ accessLog(id: string): Observable<AccessLogDetail>;
167
+ /** Data changes, newest first, paged like {@link accessLogs}. */
168
+ dataChanges(query: AuditQuery): Observable<AuditPage<DataChangeSummary>>;
169
+ dataChange(id: string): Observable<DataChangeDetail>;
170
+ trace(traceId: string): Observable<AuditTrace>;
171
+ overview(query: AuditQuery): Observable<AuditOverview>;
172
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuditApiService, never>;
173
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
174
+ }
175
+ export declare const AUDIT_RANGES: Record<string, number>;
176
+ /**
177
+ * The time window that follows the user between the audit pages. It lives in the URL (`range`, or `from` and `to`), so
178
+ * every page is a deep link and the back button restores it.
179
+ */
180
+ export declare class AuditContextService {
181
+ private readonly router;
182
+ private readonly params;
183
+ readonly range: import("@angular/core").Signal<string>;
184
+ readonly absolute: import("@angular/core").Signal<{
185
+ from: string;
186
+ to: string;
187
+ } | null>;
188
+ /** The window as ISO strings, evaluated now for a relative range. */
189
+ window(): {
190
+ from: string;
191
+ to: string;
192
+ };
193
+ /** Query parameters for a link: the window plus the target page's own. */
194
+ keep(extra?: Params): Params;
195
+ /** Changes the window on the current page, keeping its other parameters. */
196
+ set(change: {
197
+ range?: string | null;
198
+ from?: string | null;
199
+ to?: string | null;
200
+ }): void;
201
+ /** Sets the current page's own query parameters (its filters), keeping the window. */
202
+ filter(change: Params): void;
203
+ private leaf;
204
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuditContextService, never>;
205
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
206
+ }
207
+ /**
208
+ * The audit pages. Detail pages are deep links and carry the time window in their query parameters. The host mounts
209
+ * them at its `basePath` (see {@link provideJuiceAudit}) and adds its own guards.
210
+ */
211
+ export declare const AUDIT_ROUTES: Routes;
212
+ /**
213
+ * The side menu entries (juice-layout), linking under `basePath`. Their ids start with `audit-`, so they sit beside
214
+ * another package's menus (such as @juice-js/observability's) in one MenuModule.
215
+ */
216
+ export declare function auditMenus(basePath?: string, order?: number): Menus;