@svadmin/devtools 0.2.1
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/README.md +39 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +128 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @svadmin/devtools
|
|
2
|
+
|
|
3
|
+
Headless diagnostics core for svadmin.
|
|
4
|
+
|
|
5
|
+
`@svadmin/devtools-contract` defines the JSON-safe snapshot, event, and
|
|
6
|
+
diagnostic vocabulary. This package adds the runtime pieces that adapters, SSR,
|
|
7
|
+
and the CLI can share:
|
|
8
|
+
|
|
9
|
+
- `createDevtoolsCollector()` — a bounded, redacting in-memory collector with
|
|
10
|
+
`recordEvent`, `recordDiagnostic`, `snapshot`, `subscribe`, and `clear`.
|
|
11
|
+
- `buildProviderDiagnostics(bundle)` — provider configuration/capability matrix.
|
|
12
|
+
- `buildResourceDiagnostics(resources)` / `buildRouteDiagnostics(resources)` —
|
|
13
|
+
resource operations, menu visibility, provider routing, and route paths.
|
|
14
|
+
- `toPermissionDiagnostic(resource, action, result)` — normalizes access-control
|
|
15
|
+
results for display.
|
|
16
|
+
- Re-exports the whole `@svadmin/devtools-contract` surface.
|
|
17
|
+
|
|
18
|
+
UI rendering stays in `@svadmin/ui` (`DevTools.svelte`); this package is the
|
|
19
|
+
headless boundary so non-UI consumers do not depend on `devframe` or Svelte.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createDevtoolsCollector, buildProviderDiagnostics } from '@svadmin/devtools';
|
|
25
|
+
|
|
26
|
+
const collector = createDevtoolsCollector({ source: 'frontend', maxEvents: 200 });
|
|
27
|
+
|
|
28
|
+
collector.recordDiagnostic({
|
|
29
|
+
code: 'provider.missing',
|
|
30
|
+
source: 'frontend',
|
|
31
|
+
severity: 'warning',
|
|
32
|
+
message: 'liveProvider is not configured',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const snapshot = collector.snapshot({ requestId: 'req-1' });
|
|
36
|
+
const providers = buildProviderDiagnostics(config.providers);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Secrets are redacted by `redactDevtoolsRecord` before a snapshot is produced.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @svadmin/devtools — headless diagnostics core.
|
|
3
|
+
*
|
|
4
|
+
* Folds the `@svadmin/devtools-contract` snapshot/event/diagnostic vocabulary
|
|
5
|
+
* into a small runtime collector plus pure diagnostic builders. UI rendering
|
|
6
|
+
* stays in `@svadmin/ui`; this package is what adapters, SSR, and the CLI can
|
|
7
|
+
* use to publish redacted, JSON-safe diagnostics.
|
|
8
|
+
*/
|
|
9
|
+
export { createDevtoolsSnapshot, redactDevtoolsRecord } from '@svadmin/devtools-contract';
|
|
10
|
+
export type { DevtoolsCacheDiagnostics, DevtoolsDiagnostic, DevtoolsEvent, DevtoolsLocation, DevtoolsProviderDiagnostic, DevtoolsQueryDiagnostic, DevtoolsSeverity, DevtoolsSnapshot, DevtoolsSource, DevtoolsTraceContext, SvadminDevtoolsSnapshot, } from '@svadmin/devtools-contract';
|
|
11
|
+
import { type DevtoolsDiagnostic, type DevtoolsEvent, type DevtoolsProviderDiagnostic, type DevtoolsSnapshot, type DevtoolsSource, type DevtoolsTraceContext } from '@svadmin/devtools-contract';
|
|
12
|
+
import type { ProviderBundle, ResourceDefinition } from '@svadmin/core';
|
|
13
|
+
export interface DevtoolsCollectorOptions {
|
|
14
|
+
source?: DevtoolsSource;
|
|
15
|
+
maxEvents?: number;
|
|
16
|
+
maxDiagnostics?: number;
|
|
17
|
+
context?: DevtoolsTraceContext;
|
|
18
|
+
}
|
|
19
|
+
export interface DevtoolsCollector {
|
|
20
|
+
readonly source: DevtoolsSource;
|
|
21
|
+
recordEvent(event: DevtoolsEvent): void;
|
|
22
|
+
recordDiagnostic(diagnostic: DevtoolsDiagnostic): void;
|
|
23
|
+
clear(): void;
|
|
24
|
+
snapshot(context?: DevtoolsTraceContext): DevtoolsSnapshot;
|
|
25
|
+
subscribe(listener: (snapshot: DevtoolsSnapshot) => void): () => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Bounded in-memory collector. Events and diagnostics are capped so a long-lived
|
|
29
|
+
* admin session cannot grow without limit; snapshots are redacted on build.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createDevtoolsCollector(options?: DevtoolsCollectorOptions): DevtoolsCollector;
|
|
32
|
+
/** Builds provider diagnostics from a composed ProviderBundle. */
|
|
33
|
+
export declare function buildProviderDiagnostics(bundle: ProviderBundle): DevtoolsProviderDiagnostic[];
|
|
34
|
+
export interface DevtoolsResourceOperations {
|
|
35
|
+
list: boolean;
|
|
36
|
+
create: boolean;
|
|
37
|
+
edit: boolean;
|
|
38
|
+
delete: boolean;
|
|
39
|
+
show: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface DevtoolsResourceDiagnostic {
|
|
42
|
+
name: string;
|
|
43
|
+
label: string;
|
|
44
|
+
showInMenu: boolean;
|
|
45
|
+
operations: DevtoolsResourceOperations;
|
|
46
|
+
dataProvider?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function buildResourceDiagnostics(resources: readonly ResourceDefinition[]): DevtoolsResourceDiagnostic[];
|
|
49
|
+
export interface DevtoolsRouteDiagnostic {
|
|
50
|
+
resource: string;
|
|
51
|
+
path: string;
|
|
52
|
+
}
|
|
53
|
+
export declare function buildRouteDiagnostics(resources: readonly ResourceDefinition[], basePath?: string): DevtoolsRouteDiagnostic[];
|
|
54
|
+
export interface DevtoolsPermissionDiagnostic {
|
|
55
|
+
resource: string;
|
|
56
|
+
action: string;
|
|
57
|
+
allowed: boolean;
|
|
58
|
+
reason?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare function toPermissionDiagnostic(resource: string, action: string, result: {
|
|
61
|
+
can: boolean;
|
|
62
|
+
reason?: string;
|
|
63
|
+
}): DevtoolsPermissionDiagnostic;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @svadmin/devtools — headless diagnostics core.
|
|
3
|
+
*
|
|
4
|
+
* Folds the `@svadmin/devtools-contract` snapshot/event/diagnostic vocabulary
|
|
5
|
+
* into a small runtime collector plus pure diagnostic builders. UI rendering
|
|
6
|
+
* stays in `@svadmin/ui`; this package is what adapters, SSR, and the CLI can
|
|
7
|
+
* use to publish redacted, JSON-safe diagnostics.
|
|
8
|
+
*/
|
|
9
|
+
export { createDevtoolsSnapshot, redactDevtoolsRecord } from '@svadmin/devtools-contract';
|
|
10
|
+
import { createDevtoolsSnapshot, } from '@svadmin/devtools-contract';
|
|
11
|
+
function mergeContext(base, extra) {
|
|
12
|
+
const requestId = extra.requestId ?? base.requestId;
|
|
13
|
+
const traceId = extra.traceId ?? base.traceId;
|
|
14
|
+
const correlationId = extra.correlationId ?? base.correlationId;
|
|
15
|
+
return {
|
|
16
|
+
...(requestId !== undefined ? { requestId } : {}),
|
|
17
|
+
...(traceId !== undefined ? { traceId } : {}),
|
|
18
|
+
...(correlationId !== undefined ? { correlationId } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Bounded in-memory collector. Events and diagnostics are capped so a long-lived
|
|
23
|
+
* admin session cannot grow without limit; snapshots are redacted on build.
|
|
24
|
+
*/
|
|
25
|
+
export function createDevtoolsCollector(options = {}) {
|
|
26
|
+
const source = options.source ?? 'frontend';
|
|
27
|
+
const maxEvents = options.maxEvents ?? 500;
|
|
28
|
+
const maxDiagnostics = options.maxDiagnostics ?? 200;
|
|
29
|
+
const baseContext = options.context ?? {};
|
|
30
|
+
let events = [];
|
|
31
|
+
let diagnostics = [];
|
|
32
|
+
const listeners = new Set();
|
|
33
|
+
function build(context = {}) {
|
|
34
|
+
const merged = mergeContext(baseContext, context);
|
|
35
|
+
return createDevtoolsSnapshot({
|
|
36
|
+
source,
|
|
37
|
+
diagnostics,
|
|
38
|
+
events,
|
|
39
|
+
...(merged.requestId !== undefined ? { requestId: merged.requestId } : {}),
|
|
40
|
+
...(merged.traceId !== undefined ? { traceId: merged.traceId } : {}),
|
|
41
|
+
...(merged.correlationId !== undefined ? { correlationId: merged.correlationId } : {}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function notify() {
|
|
45
|
+
const snapshot = build();
|
|
46
|
+
for (const listener of listeners)
|
|
47
|
+
listener(snapshot);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
source,
|
|
51
|
+
recordEvent(event) {
|
|
52
|
+
events = [...events, event].slice(-maxEvents);
|
|
53
|
+
notify();
|
|
54
|
+
},
|
|
55
|
+
recordDiagnostic(diagnostic) {
|
|
56
|
+
diagnostics = [...diagnostics, diagnostic].slice(-maxDiagnostics);
|
|
57
|
+
notify();
|
|
58
|
+
},
|
|
59
|
+
clear() {
|
|
60
|
+
events = [];
|
|
61
|
+
diagnostics = [];
|
|
62
|
+
notify();
|
|
63
|
+
},
|
|
64
|
+
snapshot(context) {
|
|
65
|
+
return build(context);
|
|
66
|
+
},
|
|
67
|
+
subscribe(listener) {
|
|
68
|
+
listeners.add(listener);
|
|
69
|
+
if (events.length > 0 || diagnostics.length > 0)
|
|
70
|
+
listener(build());
|
|
71
|
+
return () => listeners.delete(listener);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const PROVIDER_CAPABILITIES = [
|
|
76
|
+
['dataProvider', 'data'],
|
|
77
|
+
['authProvider', 'auth'],
|
|
78
|
+
['accessControlProvider', 'access-control'],
|
|
79
|
+
['liveProvider', 'live'],
|
|
80
|
+
['auditLogProvider', 'audit-log'],
|
|
81
|
+
['notificationProvider', 'notification'],
|
|
82
|
+
['chatProvider', 'ai'],
|
|
83
|
+
['agentProvider', 'ai'],
|
|
84
|
+
['taskProvider', 'task'],
|
|
85
|
+
['routerProvider', 'router'],
|
|
86
|
+
['tenantAdapter', 'tenant'],
|
|
87
|
+
['organizationProvider', 'organization'],
|
|
88
|
+
['identityGovernanceProvider', 'identity-governance'],
|
|
89
|
+
['sessionProvider', 'session'],
|
|
90
|
+
['credentialProvider', 'credentials'],
|
|
91
|
+
];
|
|
92
|
+
/** Builds provider diagnostics from a composed ProviderBundle. */
|
|
93
|
+
export function buildProviderDiagnostics(bundle) {
|
|
94
|
+
return PROVIDER_CAPABILITIES.map(([key, capability]) => ({
|
|
95
|
+
name: key,
|
|
96
|
+
configured: bundle[key] !== undefined && bundle[key] !== null,
|
|
97
|
+
capabilities: capability,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
export function buildResourceDiagnostics(resources) {
|
|
101
|
+
return resources.map((resource) => ({
|
|
102
|
+
name: resource.name,
|
|
103
|
+
label: resource.label,
|
|
104
|
+
showInMenu: resource.showInMenu ?? true,
|
|
105
|
+
operations: {
|
|
106
|
+
list: true,
|
|
107
|
+
create: resource.canCreate ?? true,
|
|
108
|
+
edit: resource.canEdit ?? true,
|
|
109
|
+
delete: resource.canDelete ?? true,
|
|
110
|
+
show: resource.canShow ?? true,
|
|
111
|
+
},
|
|
112
|
+
...(resource.provider?.dataProviderName !== undefined
|
|
113
|
+
? { dataProvider: resource.provider.dataProviderName }
|
|
114
|
+
: {}),
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
export function buildRouteDiagnostics(resources, basePath = '') {
|
|
118
|
+
const prefix = basePath.replace(/\/+$/u, '');
|
|
119
|
+
return resources.map((resource) => ({ resource: resource.name, path: `${prefix}/${resource.name}` }));
|
|
120
|
+
}
|
|
121
|
+
export function toPermissionDiagnostic(resource, action, result) {
|
|
122
|
+
return {
|
|
123
|
+
resource,
|
|
124
|
+
action,
|
|
125
|
+
allowed: result.can,
|
|
126
|
+
...(result.reason !== undefined ? { reason: result.reason } : {}),
|
|
127
|
+
};
|
|
128
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@svadmin/devtools",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Headless diagnostics core for svadmin — query traces, provider diagnostics, permission/resource/route inspection",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"svadmin",
|
|
9
|
+
"devtools",
|
|
10
|
+
"diagnostics",
|
|
11
|
+
"observability",
|
|
12
|
+
"admin"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/vibeunion/svadmin.git",
|
|
17
|
+
"directory": "packages/devtools"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"svadmin": {
|
|
33
|
+
"capabilities": [
|
|
34
|
+
"devtools-traces",
|
|
35
|
+
"provider-diagnostics",
|
|
36
|
+
"resource-diagnostics"
|
|
37
|
+
],
|
|
38
|
+
"core": "^0.55.0",
|
|
39
|
+
"stability": "experimental",
|
|
40
|
+
"migration": null
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@svadmin/devtools-contract": "^0.2.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@svadmin/core": "^0.58.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"@svadmin/core": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"typescript": "^7.0.2"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "bun ../../scripts/build-node-package.ts"
|
|
58
|
+
}
|
|
59
|
+
}
|