@svadmin/core 0.39.0 → 0.39.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/package.json +1 -1
- package/src/enterprise.ts +60 -0
- package/src/index.ts +4 -0
- package/src/route-parsing.ts +14 -0
- package/src/useParsed.svelte.ts +3 -36
package/package.json
CHANGED
package/src/enterprise.ts
CHANGED
|
@@ -18,6 +18,66 @@ export interface EnterpriseRequestContext {
|
|
|
18
18
|
meta?: Readonly<Record<string, unknown>>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/** Provider 调用使用的严格请求上下文;三项边界标识不可省略。 */
|
|
22
|
+
export interface StrictEnterpriseRequestContext {
|
|
23
|
+
tenantId: string | number;
|
|
24
|
+
requestId: string;
|
|
25
|
+
traceId: string;
|
|
26
|
+
meta?: Readonly<Record<string, unknown>>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface EnterpriseRequestContextInput {
|
|
30
|
+
tenantId: string | number;
|
|
31
|
+
requestId?: string;
|
|
32
|
+
traceId?: string;
|
|
33
|
+
meta?: Readonly<Record<string, unknown>>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function nonEmpty(value: string, field: string): string {
|
|
37
|
+
const normalized = value.trim();
|
|
38
|
+
if (!normalized) throw new Error(`${field} must not be empty.`);
|
|
39
|
+
return normalized;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function validatedTenantId(tenantId: string | number): string | number {
|
|
43
|
+
if (typeof tenantId === 'string') return nonEmpty(tenantId, 'tenantId');
|
|
44
|
+
if (!Number.isFinite(tenantId)) throw new Error('tenantId must be a finite number.');
|
|
45
|
+
return tenantId;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function createRequestId(): string {
|
|
49
|
+
const randomUUID = globalThis.crypto?.randomUUID;
|
|
50
|
+
if (!randomUUID) throw new Error('crypto.randomUUID is required to create an enterprise request context.');
|
|
51
|
+
return randomUUID.call(globalThis.crypto);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Create a validated provider context while preserving one trace across the request tree. */
|
|
55
|
+
export function createEnterpriseRequestContext(
|
|
56
|
+
input: EnterpriseRequestContextInput,
|
|
57
|
+
): StrictEnterpriseRequestContext {
|
|
58
|
+
const requestId = nonEmpty(input.requestId || createRequestId(), 'requestId');
|
|
59
|
+
return {
|
|
60
|
+
tenantId: validatedTenantId(input.tenantId),
|
|
61
|
+
requestId,
|
|
62
|
+
traceId: nonEmpty(input.traceId || requestId, 'traceId'),
|
|
63
|
+
...(input.meta ? { meta: input.meta } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Narrow a legacy optional context at the provider boundary and fail closed on missing identity. */
|
|
68
|
+
export function assertEnterpriseRequestContext(
|
|
69
|
+
context: EnterpriseRequestContext,
|
|
70
|
+
): asserts context is StrictEnterpriseRequestContext {
|
|
71
|
+
if (context.tenantId === undefined || context.tenantId === null) {
|
|
72
|
+
throw new Error('tenantId must not be empty.');
|
|
73
|
+
}
|
|
74
|
+
validatedTenantId(context.tenantId);
|
|
75
|
+
nonEmpty(context.requestId ?? '', 'requestId');
|
|
76
|
+
nonEmpty(context.traceId ?? '', 'traceId');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type EnterpriseProviderRequestContext = StrictEnterpriseRequestContext;
|
|
80
|
+
|
|
21
81
|
export interface Organization {
|
|
22
82
|
id: string;
|
|
23
83
|
name: string;
|
package/src/index.ts
CHANGED
|
@@ -93,6 +93,9 @@ export type {
|
|
|
93
93
|
EnterpriseActionError,
|
|
94
94
|
EnterpriseActionResult,
|
|
95
95
|
EnterpriseRequestContext,
|
|
96
|
+
EnterpriseRequestContextInput,
|
|
97
|
+
EnterpriseProviderRequestContext,
|
|
98
|
+
StrictEnterpriseRequestContext,
|
|
96
99
|
EnterpriseSecurityEvent,
|
|
97
100
|
EnterpriseSecurityPolicy,
|
|
98
101
|
IdentityGovernanceProvider,
|
|
@@ -106,6 +109,7 @@ export type {
|
|
|
106
109
|
SessionProvider,
|
|
107
110
|
WebhookSummary,
|
|
108
111
|
} from './enterprise';
|
|
112
|
+
export { assertEnterpriseRequestContext, createEnterpriseRequestContext } from './enterprise';
|
|
109
113
|
export { setChatProvider, getChatProvider, setChatContext, getChatContext, setAgentProvider, getAgentProvider, registerApproval, resolveApproval, hasPendingApprovals, resetChatProvider } from './chatProvider.svelte';
|
|
110
114
|
export type { ChatProvider, ChatMessage, ChatContext, ChatAction, AgentProvider, AgentEvent, AgentOptions, AdminTool, AdminToolParameter, ToolResult } from './chatProvider.svelte';
|
|
111
115
|
export { getTheme, setTheme, toggleTheme, getResolvedTheme, getColorTheme, setColorTheme, getColorThemes, configureTheme, getThemeConfig, clearCssOverrides, builtinPresets, registerColorPreset, getColorPresets, registerThemeOwner, updateThemeOwner, unregisterThemeOwner, resetTheme } from './theme.svelte';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ParsedResourceAction = {
|
|
2
|
+
action: 'list' | 'create' | 'edit' | 'show' | 'clone';
|
|
3
|
+
id?: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export function parseResourceActionSegments(restSegments: string[]): ParsedResourceAction {
|
|
7
|
+
if (restSegments.length === 0) return { action: 'list' };
|
|
8
|
+
if (restSegments[0] === 'create') return { action: 'create' };
|
|
9
|
+
if (restSegments[0] === 'edit' && restSegments[1]) return { action: 'edit', id: restSegments[1] };
|
|
10
|
+
if (restSegments[0] === 'show' && restSegments[1]) return { action: 'show', id: restSegments[1] };
|
|
11
|
+
if (restSegments[0] === 'clone' && restSegments[1]) return { action: 'clone', id: restSegments[1] };
|
|
12
|
+
if (restSegments[1] === 'edit') return { action: 'edit', id: restSegments[0] };
|
|
13
|
+
return { action: 'show', id: restSegments[0] };
|
|
14
|
+
}
|
package/src/useParsed.svelte.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { registerRouterSync } from './router';
|
|
5
5
|
import { captureAdminContext } from './context.svelte';
|
|
6
|
+
import { parseResourceActionSegments } from './route-parsing';
|
|
6
7
|
|
|
7
8
|
interface ParsedRoute {
|
|
8
9
|
resource?: string;
|
|
@@ -107,47 +108,13 @@ export function useParsed(): ParsedRoute {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
if (restSegments.length === 0) {
|
|
112
|
-
result.action = 'list';
|
|
113
|
-
} else if (restSegments[0] === 'create') {
|
|
114
|
-
result.action = 'create';
|
|
115
|
-
} else if (restSegments[0] === 'edit' && restSegments[1]) {
|
|
116
|
-
result.action = 'edit';
|
|
117
|
-
result.id = restSegments[1];
|
|
118
|
-
} else if (restSegments[0] === 'show' && restSegments[1]) {
|
|
119
|
-
result.action = 'show';
|
|
120
|
-
result.id = restSegments[1];
|
|
121
|
-
} else if (restSegments[0] === 'clone' && restSegments[1]) {
|
|
122
|
-
result.action = 'clone';
|
|
123
|
-
result.id = restSegments[1];
|
|
124
|
-
} else if (restSegments[0]) {
|
|
125
|
-
// Legacy: /:resource/:id
|
|
126
|
-
result.action = 'show';
|
|
127
|
-
result.id = restSegments[0];
|
|
128
|
-
}
|
|
111
|
+
Object.assign(result, parseResourceActionSegments(segments.slice(resourceIndex + 1)));
|
|
129
112
|
} else {
|
|
130
113
|
// Fallback if resource definitions are not loaded yet
|
|
131
114
|
result.resource = segments[0];
|
|
132
115
|
result.resourcePath = segments[0];
|
|
133
116
|
|
|
134
|
-
|
|
135
|
-
result.action = 'list';
|
|
136
|
-
} else if (segments[1] === 'create') {
|
|
137
|
-
result.action = 'create';
|
|
138
|
-
} else if (segments[1] === 'edit' && segments[2]) {
|
|
139
|
-
result.action = 'edit';
|
|
140
|
-
result.id = segments[2];
|
|
141
|
-
} else if (segments[1] === 'show' && segments[2]) {
|
|
142
|
-
result.action = 'show';
|
|
143
|
-
result.id = segments[2];
|
|
144
|
-
} else if (segments[1] === 'clone' && segments[2]) {
|
|
145
|
-
result.action = 'clone';
|
|
146
|
-
result.id = segments[2];
|
|
147
|
-
} else if (segments[1]) {
|
|
148
|
-
result.action = 'show';
|
|
149
|
-
result.id = segments[1];
|
|
150
|
-
}
|
|
117
|
+
Object.assign(result, parseResourceActionSegments(segments.slice(1)));
|
|
151
118
|
}
|
|
152
119
|
|
|
153
120
|
return result;
|