@svadmin/core 0.50.0 → 0.53.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/package.json +21 -4
- package/src/access-control-contract.ts +250 -0
- package/src/adapters/casbin.ts +20 -14
- package/src/adapters/casl.ts +22 -19
- package/src/admin-tool.ts +7 -7
- package/src/audit-contract.ts +105 -0
- package/src/audit.ts +88 -128
- package/src/auth-hooks.svelte.ts +593 -261
- package/src/auth-mutation-contract.ts +143 -0
- package/src/auth-query-contract.ts +97 -0
- package/src/captured-mutation.svelte.ts +45 -0
- package/src/chatProvider.svelte.ts +1 -1
- package/src/command-contract.ts +195 -0
- package/src/context.svelte.ts +217 -205
- package/src/contract-context.svelte.ts +37 -0
- package/src/contract-form.svelte.ts +566 -0
- package/src/create-contract.ts +56 -0
- package/src/create-hooks.svelte.ts +347 -0
- package/src/create-many-contract.ts +90 -0
- package/src/create-many-hooks.svelte.ts +396 -0
- package/src/data-transfer.svelte.ts +1 -215
- package/src/defined-options.ts +50 -0
- package/src/delete-contract.ts +50 -0
- package/src/delete-hooks.svelte.ts +403 -0
- package/src/delete-many-contract.ts +60 -0
- package/src/delete-many-hooks.svelte.ts +402 -0
- package/src/enterprise.ts +4 -4
- package/src/export-format.ts +16 -14
- package/src/export-hooks.svelte.ts +191 -0
- package/src/feature-gate-contract.ts +53 -0
- package/src/hook-utils.svelte.ts +53 -105
- package/src/hooks.svelte.ts +19 -776
- package/src/http.ts +88 -87
- package/src/i18n.svelte.ts +64 -2
- package/src/import-contract.ts +106 -0
- package/src/import-hooks.svelte.ts +310 -0
- package/src/index.ts +77 -30
- package/src/inferencer-graphql.ts +7 -6
- package/src/inferencer.ts +9 -0
- package/src/infinite-query.svelte.ts +228 -0
- package/src/invalidation-contract.ts +26 -0
- package/src/live-sse.ts +91 -127
- package/src/live-subscription.svelte.ts +130 -0
- package/src/live-transport.ts +127 -0
- package/src/live-websocket.ts +85 -118
- package/src/live.svelte.ts +66 -68
- package/src/notification.svelte.ts +17 -15
- package/src/permission-catalog.ts +121 -0
- package/src/permission-hints-contract.ts +48 -0
- package/src/permissions.svelte.ts +112 -59
- package/src/plain-data.ts +61 -0
- package/src/provider-bundle.ts +85 -79
- package/src/provider-response.ts +35 -0
- package/src/query-hooks.svelte.ts +241 -288
- package/src/query-invalidation.ts +172 -0
- package/src/query-keys.ts +221 -110
- package/src/query-session.svelte.ts +220 -0
- package/src/query-snapshot.ts +144 -0
- package/src/reactive-projection.ts +53 -0
- package/src/record-decoder.ts +63 -0
- package/src/resource-binding.svelte.ts +19 -0
- package/src/resource-contract.ts +595 -0
- package/src/resource-mutation-types.ts +30 -0
- package/src/resource-schemas.ts +371 -0
- package/src/resource-transport-config.ts +156 -0
- package/src/route-parsing.ts +11 -11
- package/src/router-provider.ts +64 -59
- package/src/router.ts +8 -3
- package/src/routing-hooks.svelte.ts +90 -62
- package/src/schema-validation.ts +92 -0
- package/src/schema.ts +13 -0
- package/src/select-options.ts +95 -0
- package/src/select-query.svelte.ts +191 -0
- package/src/session-query.svelte.ts +103 -0
- package/src/strict-command-hooks.svelte.ts +333 -0
- package/src/strict-hooks.svelte.ts +198 -0
- package/src/table-hooks.svelte.ts +180 -174
- package/src/table-state.svelte.ts +117 -117
- package/src/task-contract.ts +87 -0
- package/src/task-hooks.svelte.ts +190 -180
- package/src/task-provider.ts +115 -0
- package/src/task-subscription.ts +132 -0
- package/src/theme.svelte.ts +155 -154
- package/src/toast.svelte.ts +38 -37
- package/src/types.ts +68 -110
- package/src/unsafe.ts +7 -0
- package/src/update-contract.ts +65 -0
- package/src/update-hooks.svelte.ts +347 -0
- package/src/update-many-contract.ts +79 -0
- package/src/update-many-hooks.svelte.ts +373 -0
- package/src/url-sync.ts +11 -10
- package/src/useCan.ts +96 -31
- package/src/useParsed.svelte.ts +18 -14
- package/src/useStepsForm.svelte.ts +123 -63
- package/src/utility-hooks.svelte.ts +101 -158
- package/src/form-hooks.svelte.ts +0 -889
- package/src/mutation-hooks.svelte.ts +0 -561
- package/src/schema-form.ts +0 -31
package/src/context.svelte.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { definedOptions } from './defined-options';
|
|
1
2
|
// Svelte 5 Context — application trees use scoped context while the module-level
|
|
2
3
|
// setters remain as a compatibility facade for non-component consumers.
|
|
3
4
|
|
|
4
5
|
import { createContext } from 'svelte';
|
|
5
|
-
import type { DataProvider,
|
|
6
|
+
import type { DataProvider,AuthProvider,ResourceDefinition,TaskProvider } from './types';
|
|
6
7
|
import type { RouterProvider } from './router-provider';
|
|
7
8
|
import type { LiveProvider } from './live.svelte';
|
|
8
|
-
import type {
|
|
9
|
+
import type { RegisteredAccessControlProvider } from './permissions.svelte';
|
|
10
|
+
import { captureAccessControlProvider } from './access-control-contract';
|
|
9
11
|
import type { AuditLogProvider } from './audit';
|
|
10
|
-
import type { AgentProvider,
|
|
12
|
+
import type { AgentProvider,ChatProvider } from './chatProvider.svelte';
|
|
11
13
|
import type { EnterpriseRequestContext } from './enterprise';
|
|
12
14
|
import {
|
|
13
15
|
createTenantCacheKey,
|
|
@@ -23,9 +25,9 @@ import type {
|
|
|
23
25
|
TenantCacheKey,
|
|
24
26
|
TenantContext,
|
|
25
27
|
} from './provider-bundle';
|
|
26
|
-
import { getNotificationProvider as getLegacyNotificationProvider,
|
|
27
|
-
import { getAuditLogProvider as getLegacyAuditLogProvider,
|
|
28
|
-
import { getAccessControlProvider as getLegacyAccessControlProvider,
|
|
28
|
+
import { getNotificationProvider as getLegacyNotificationProvider,resetNotificationProvider } from './notification.svelte';
|
|
29
|
+
import { getAuditLogProvider as getLegacyAuditLogProvider,resetAuditLogProvider } from './audit';
|
|
30
|
+
import { getAccessControlProvider as getLegacyAccessControlProvider,resetAccessControlProvider } from './permissions.svelte';
|
|
29
31
|
import { resetAdminOptions } from './options.svelte';
|
|
30
32
|
import { resetI18n } from './i18n.svelte';
|
|
31
33
|
import {
|
|
@@ -53,37 +55,41 @@ import { resetSidebarCollapsed } from './hooks.svelte';
|
|
|
53
55
|
|
|
54
56
|
export type { DataProviderInput } from './provider-bundle';
|
|
55
57
|
|
|
56
|
-
interface AdminContextSourceBase extends Omit<Partial<ProviderBundle>,
|
|
58
|
+
interface AdminContextSourceBase extends Omit<Partial<ProviderBundle>,'dataProvider'> {
|
|
57
59
|
readonly resources: ResourceDefinition[];
|
|
58
|
-
/**
|
|
60
|
+
/** Tenant for the request tree; inherits the nearest provideTenantContext when omitted. */
|
|
59
61
|
readonly tenant?: TenantContext;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
/**
|
|
63
|
-
export type AdminContextSource
|
|
64
|
-
|
|
|
65
|
-
|
|
|
64
|
+
/** Requires either the legacy dataProvider or a first-class ProviderBundle; matching top-level fields take precedence. */
|
|
65
|
+
export type AdminContextSource=AdminContextSourceBase&(
|
|
66
|
+
|{ readonly dataProvider: DataProviderInput; readonly providerBundle?: ProviderBundle }
|
|
67
|
+
|{ readonly dataProvider?: DataProviderInput; readonly providerBundle: ProviderBundle }
|
|
66
68
|
);
|
|
67
69
|
|
|
70
|
+
export type ResolvedProviderBundle = Omit<ProviderBundle, 'accessControlProvider'> & {
|
|
71
|
+
readonly accessControlProvider?: RegisteredAccessControlProvider | null;
|
|
72
|
+
};
|
|
73
|
+
|
|
68
74
|
export interface AdminContextValue {
|
|
69
|
-
readonly providerBundle:
|
|
70
|
-
readonly providers: Record<string,
|
|
71
|
-
readonly authProvider: AuthProvider
|
|
75
|
+
readonly providerBundle: ResolvedProviderBundle;
|
|
76
|
+
readonly providers: Record<string,DataProvider>;
|
|
77
|
+
readonly authProvider: AuthProvider|null;
|
|
72
78
|
readonly resources: ResourceDefinition[];
|
|
73
|
-
readonly routerProvider: RouterProvider
|
|
74
|
-
readonly liveProvider: LiveProvider
|
|
75
|
-
readonly taskProvider: TaskProvider
|
|
76
|
-
readonly accessControlProvider:
|
|
77
|
-
readonly auditLogProvider: AuditLogProvider
|
|
79
|
+
readonly routerProvider: RouterProvider|undefined;
|
|
80
|
+
readonly liveProvider: LiveProvider|undefined;
|
|
81
|
+
readonly taskProvider: TaskProvider|undefined;
|
|
82
|
+
readonly accessControlProvider: RegisteredAccessControlProvider|null;
|
|
83
|
+
readonly auditLogProvider: AuditLogProvider|null;
|
|
78
84
|
readonly notificationProvider: ProviderBundle['notificationProvider'];
|
|
79
|
-
readonly chatProvider: ChatProvider
|
|
80
|
-
readonly agentProvider: AgentProvider
|
|
85
|
+
readonly chatProvider: ChatProvider|null;
|
|
86
|
+
readonly agentProvider: AgentProvider|null;
|
|
81
87
|
readonly organizationProvider: ProviderBundle['organizationProvider'];
|
|
82
88
|
readonly identityGovernanceProvider: ProviderBundle['identityGovernanceProvider'];
|
|
83
89
|
readonly sessionProvider: ProviderBundle['sessionProvider'];
|
|
84
90
|
readonly credentialProvider: ProviderBundle['credentialProvider'];
|
|
85
|
-
readonly tenant: TenantContext
|
|
86
|
-
readonly tenantAdapter: TenantAdapter
|
|
91
|
+
readonly tenant: TenantContext|undefined;
|
|
92
|
+
readonly tenantAdapter: TenantAdapter|undefined;
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
/**
|
|
@@ -95,42 +101,42 @@ export interface AdminContextValue {
|
|
|
95
101
|
* read the module-level compatibility setters dynamically.
|
|
96
102
|
*/
|
|
97
103
|
export interface AdminContextAccessor {
|
|
98
|
-
readonly providerBundle:
|
|
99
|
-
readonly providers: Record<string,
|
|
100
|
-
readonly authProvider: AuthProvider
|
|
104
|
+
readonly providerBundle: ResolvedProviderBundle;
|
|
105
|
+
readonly providers: Record<string,DataProvider>|null;
|
|
106
|
+
readonly authProvider: AuthProvider|null;
|
|
101
107
|
readonly resources: ResourceDefinition[];
|
|
102
|
-
readonly routerProvider: RouterProvider
|
|
103
|
-
readonly liveProvider: LiveProvider
|
|
104
|
-
readonly taskProvider: TaskProvider
|
|
105
|
-
readonly accessControlProvider:
|
|
106
|
-
readonly auditLogProvider: AuditLogProvider
|
|
108
|
+
readonly routerProvider: RouterProvider|undefined;
|
|
109
|
+
readonly liveProvider: LiveProvider|undefined;
|
|
110
|
+
readonly taskProvider: TaskProvider|undefined;
|
|
111
|
+
readonly accessControlProvider: RegisteredAccessControlProvider|null;
|
|
112
|
+
readonly auditLogProvider: AuditLogProvider|null;
|
|
107
113
|
readonly notificationProvider: ProviderBundle['notificationProvider'];
|
|
108
|
-
readonly chatProvider: ChatProvider
|
|
109
|
-
readonly agentProvider: AgentProvider
|
|
114
|
+
readonly chatProvider: ChatProvider|null;
|
|
115
|
+
readonly agentProvider: AgentProvider|null;
|
|
110
116
|
readonly organizationProvider: ProviderBundle['organizationProvider'];
|
|
111
117
|
readonly identityGovernanceProvider: ProviderBundle['identityGovernanceProvider'];
|
|
112
118
|
readonly sessionProvider: ProviderBundle['sessionProvider'];
|
|
113
119
|
readonly credentialProvider: ProviderBundle['credentialProvider'];
|
|
114
|
-
readonly tenant: TenantContext
|
|
115
|
-
readonly tenantAdapter: TenantAdapter
|
|
116
|
-
readonly tenantCacheKey: TenantCacheKey
|
|
120
|
+
readonly tenant: TenantContext|undefined;
|
|
121
|
+
readonly tenantAdapter: TenantAdapter|undefined;
|
|
122
|
+
readonly tenantCacheKey: TenantCacheKey|undefined;
|
|
117
123
|
readonly enterpriseRequestContext: EnterpriseRequestContext;
|
|
118
124
|
getDataProvider(name?: string): DataProvider;
|
|
119
125
|
getDataProviderNames(): string[];
|
|
120
|
-
resolveDataProviderName(resourceName: string,
|
|
121
|
-
getDataProviderForResource(resourceName: string,
|
|
122
|
-
queryKeys(resourceName?: string,
|
|
123
|
-
queryKeyMatcher(resourceName?: string,
|
|
124
|
-
getProviderMeta(resourceName: string
|
|
126
|
+
resolveDataProviderName(resourceName: string,overrideName?: string): string;
|
|
127
|
+
getDataProviderForResource(resourceName: string,overrideName?: string): DataProvider;
|
|
128
|
+
queryKeys(resourceName?: string,overrideName?: string): ReturnType<typeof keys>;
|
|
129
|
+
queryKeyMatcher(resourceName?: string,overrideName?: string): Pick<QueryMatcher,'provider'|'tenant'>;
|
|
130
|
+
getProviderMeta(resourceName: string|undefined,meta?: Record<string,unknown>): Record<string,unknown>|undefined;
|
|
125
131
|
getResource(nameOrIdentifier: string): ResourceDefinition;
|
|
126
132
|
currentPath(): string;
|
|
127
133
|
formatLink(path: string): string;
|
|
128
|
-
navigate(path: string,
|
|
134
|
+
navigate(path: string,options?: { replaceState?: boolean }): Promise<void>;
|
|
129
135
|
back(): void;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
const [getRequiredAdminContext,
|
|
133
|
-
const [getRequiredTenantContext,
|
|
138
|
+
const [getRequiredAdminContext,setAdminContext]=createContext<AdminContextValue>();
|
|
139
|
+
const [getRequiredTenantContext,setScopedTenantContext]=createContext<TenantContext>();
|
|
134
140
|
|
|
135
141
|
/** Provide tenant state to a request/component subtree. No module-level fallback is created. */
|
|
136
142
|
export function provideTenantContext(tenant: TenantContext): TenantContext {
|
|
@@ -139,7 +145,7 @@ export function provideTenantContext(tenant: TenantContext): TenantContext {
|
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
/** Return the nearest request/tree-scoped tenant when called during initialization. */
|
|
142
|
-
export function getTenantContext(): TenantContext
|
|
148
|
+
export function getTenantContext(): TenantContext|undefined {
|
|
143
149
|
try {
|
|
144
150
|
return getRequiredTenantContext();
|
|
145
151
|
} catch {
|
|
@@ -147,83 +153,83 @@ export function getTenantContext(): TenantContext | undefined {
|
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
|
|
150
|
-
function normalizeDataProviders(provider: DataProviderInput): Record<string,
|
|
156
|
+
function normalizeDataProviders(provider: DataProviderInput): Record<string,DataProvider> {
|
|
151
157
|
return isDataProvider(provider)
|
|
152
158
|
? { default: provider }
|
|
153
|
-
:
|
|
159
|
+
:provider;
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
function resolveProviderBundle(source: AdminContextSource):
|
|
157
|
-
const bundled
|
|
158
|
-
const dataProvider
|
|
159
|
-
if
|
|
162
|
+
function resolveProviderBundle(source: AdminContextSource): ResolvedProviderBundle {
|
|
163
|
+
const bundled=source.providerBundle;
|
|
164
|
+
const dataProvider=source.dataProvider??bundled?.dataProvider;
|
|
165
|
+
if(!dataProvider) {
|
|
160
166
|
throw new Error('ProviderBundle requires a dataProvider.');
|
|
161
167
|
}
|
|
162
168
|
|
|
163
|
-
|
|
169
|
+
const directAccessControl = source.accessControlProvider;
|
|
170
|
+
const accessControl = directAccessControl !== undefined ? directAccessControl : bundled?.accessControlProvider;
|
|
171
|
+
return Object.freeze(definedOptions({
|
|
164
172
|
dataProvider,
|
|
165
|
-
authProvider: source.authProvider
|
|
166
|
-
accessControlProvider:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
auditLogProvider: source.auditLogProvider !== undefined ? source.auditLogProvider : bundled?.auditLogProvider,
|
|
171
|
-
notificationProvider: source.notificationProvider !== undefined
|
|
173
|
+
authProvider: source.authProvider!==undefined? source.authProvider:bundled?.authProvider,
|
|
174
|
+
accessControlProvider: accessControl == null ? accessControl : captureAccessControlProvider(accessControl),
|
|
175
|
+
liveProvider: source.liveProvider??bundled?.liveProvider,
|
|
176
|
+
auditLogProvider: source.auditLogProvider!==undefined? source.auditLogProvider:bundled?.auditLogProvider,
|
|
177
|
+
notificationProvider: source.notificationProvider!==undefined
|
|
172
178
|
? source.notificationProvider
|
|
173
|
-
:
|
|
174
|
-
chatProvider: source.chatProvider
|
|
175
|
-
agentProvider: source.agentProvider
|
|
176
|
-
taskProvider: source.taskProvider
|
|
177
|
-
routerProvider: source.routerProvider
|
|
178
|
-
tenantAdapter: source.tenantAdapter
|
|
179
|
-
organizationProvider: source.organizationProvider
|
|
179
|
+
:bundled?.notificationProvider,
|
|
180
|
+
chatProvider: source.chatProvider!==undefined? source.chatProvider:bundled?.chatProvider,
|
|
181
|
+
agentProvider: source.agentProvider!==undefined? source.agentProvider:bundled?.agentProvider,
|
|
182
|
+
taskProvider: source.taskProvider??bundled?.taskProvider,
|
|
183
|
+
routerProvider: source.routerProvider??bundled?.routerProvider,
|
|
184
|
+
tenantAdapter: source.tenantAdapter??bundled?.tenantAdapter,
|
|
185
|
+
organizationProvider: source.organizationProvider!==undefined
|
|
180
186
|
? source.organizationProvider
|
|
181
|
-
:
|
|
182
|
-
identityGovernanceProvider: source.identityGovernanceProvider
|
|
187
|
+
:bundled?.organizationProvider,
|
|
188
|
+
identityGovernanceProvider: source.identityGovernanceProvider!==undefined
|
|
183
189
|
? source.identityGovernanceProvider
|
|
184
|
-
:
|
|
185
|
-
sessionProvider: source.sessionProvider
|
|
190
|
+
:bundled?.identityGovernanceProvider,
|
|
191
|
+
sessionProvider: source.sessionProvider!==undefined
|
|
186
192
|
? source.sessionProvider
|
|
187
|
-
:
|
|
188
|
-
credentialProvider: source.credentialProvider
|
|
193
|
+
:bundled?.sessionProvider,
|
|
194
|
+
credentialProvider: source.credentialProvider!==undefined
|
|
189
195
|
? source.credentialProvider
|
|
190
|
-
:
|
|
191
|
-
};
|
|
196
|
+
:bundled?.credentialProvider,
|
|
197
|
+
}));
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
export function createAdminContext(source: AdminContextSource): AdminContextValue {
|
|
195
|
-
const inheritedTenant
|
|
196
|
-
return {
|
|
201
|
+
const inheritedTenant=getTenantContext();
|
|
202
|
+
return Object.freeze({
|
|
197
203
|
get providerBundle() { return resolveProviderBundle(source); },
|
|
198
204
|
get providers() { return normalizeDataProviders(resolveProviderBundle(source).dataProvider); },
|
|
199
|
-
get authProvider() { return resolveProviderBundle(source).authProvider
|
|
205
|
+
get authProvider() { return resolveProviderBundle(source).authProvider??null; },
|
|
200
206
|
get resources() { return source.resources; },
|
|
201
207
|
get routerProvider() { return resolveProviderBundle(source).routerProvider; },
|
|
202
208
|
get liveProvider() { return resolveProviderBundle(source).liveProvider; },
|
|
203
209
|
get taskProvider() { return resolveProviderBundle(source).taskProvider; },
|
|
204
|
-
get accessControlProvider() { return resolveProviderBundle(source).accessControlProvider
|
|
205
|
-
get auditLogProvider() { return resolveProviderBundle(source).auditLogProvider
|
|
206
|
-
get notificationProvider() { return resolveProviderBundle(source).notificationProvider
|
|
207
|
-
get chatProvider() { return resolveProviderBundle(source).chatProvider
|
|
208
|
-
get agentProvider() { return resolveProviderBundle(source).agentProvider
|
|
209
|
-
get organizationProvider() { return resolveProviderBundle(source).organizationProvider
|
|
210
|
-
get identityGovernanceProvider() { return resolveProviderBundle(source).identityGovernanceProvider
|
|
211
|
-
get sessionProvider() { return resolveProviderBundle(source).sessionProvider
|
|
212
|
-
get credentialProvider() { return resolveProviderBundle(source).credentialProvider
|
|
213
|
-
get tenant() { return source.tenant
|
|
210
|
+
get accessControlProvider() { return resolveProviderBundle(source).accessControlProvider??null; },
|
|
211
|
+
get auditLogProvider() { return resolveProviderBundle(source).auditLogProvider??null; },
|
|
212
|
+
get notificationProvider() { return resolveProviderBundle(source).notificationProvider??null; },
|
|
213
|
+
get chatProvider() { return resolveProviderBundle(source).chatProvider??null; },
|
|
214
|
+
get agentProvider() { return resolveProviderBundle(source).agentProvider??null; },
|
|
215
|
+
get organizationProvider() { return resolveProviderBundle(source).organizationProvider??null; },
|
|
216
|
+
get identityGovernanceProvider() { return resolveProviderBundle(source).identityGovernanceProvider??null; },
|
|
217
|
+
get sessionProvider() { return resolveProviderBundle(source).sessionProvider??null; },
|
|
218
|
+
get credentialProvider() { return resolveProviderBundle(source).credentialProvider??null; },
|
|
219
|
+
get tenant() { return source.tenant??inheritedTenant; },
|
|
214
220
|
get tenantAdapter() { return resolveProviderBundle(source).tenantAdapter; },
|
|
215
|
-
};
|
|
221
|
+
});
|
|
216
222
|
}
|
|
217
223
|
|
|
218
224
|
/** Provide request/tree-scoped admin state to all descendants. */
|
|
219
225
|
export function provideAdminContext(source: AdminContextSource): AdminContextValue {
|
|
220
|
-
const context
|
|
226
|
+
const context=createAdminContext(source);
|
|
221
227
|
setAdminContext(context);
|
|
222
228
|
return context;
|
|
223
229
|
}
|
|
224
230
|
|
|
225
231
|
/** Return the current tree context when called during component initialization/render. */
|
|
226
|
-
export function getAdminContext(): AdminContextValue
|
|
232
|
+
export function getAdminContext(): AdminContextValue|undefined {
|
|
227
233
|
try {
|
|
228
234
|
return getRequiredAdminContext();
|
|
229
235
|
} catch {
|
|
@@ -231,28 +237,28 @@ export function getAdminContext(): AdminContextValue | undefined {
|
|
|
231
237
|
}
|
|
232
238
|
}
|
|
233
239
|
|
|
234
|
-
let providers
|
|
240
|
+
let providers=$state<Record<string,DataProvider>|null>(null);
|
|
235
241
|
|
|
236
242
|
/** Capture the current tree once so delayed callbacks never re-enter getContext. */
|
|
237
243
|
export function captureAdminContext(): AdminContextAccessor {
|
|
238
|
-
const scopedContext
|
|
239
|
-
const adaptedProviders
|
|
244
|
+
const scopedContext=getAdminContext();
|
|
245
|
+
const adaptedProviders=new Map<DataProvider,DataProvider>();
|
|
240
246
|
|
|
241
247
|
function adaptProvider(provider: DataProvider): DataProvider {
|
|
242
|
-
const hasResourceMetadata
|
|
243
|
-
if
|
|
244
|
-
const cached
|
|
245
|
-
if
|
|
246
|
-
const adapted
|
|
247
|
-
adaptedProviders.set(provider,
|
|
248
|
+
const hasResourceMetadata=accessor.resources.some((resource) => resource.provider!==undefined);
|
|
249
|
+
if(!accessor.tenant&&!hasResourceMetadata) return provider;
|
|
250
|
+
const cached=adaptedProviders.get(provider);
|
|
251
|
+
if(cached) return cached;
|
|
252
|
+
const adapted=withProviderMeta(provider,({ resource,meta }) => accessor.getProviderMeta(resource,meta));
|
|
253
|
+
adaptedProviders.set(provider,adapted);
|
|
248
254
|
return adapted;
|
|
249
255
|
}
|
|
250
256
|
|
|
251
|
-
const accessor: AdminContextAccessor
|
|
257
|
+
const accessor: AdminContextAccessor={
|
|
252
258
|
get providerBundle() {
|
|
253
|
-
if
|
|
254
|
-
if
|
|
255
|
-
return {
|
|
259
|
+
if(scopedContext) return scopedContext.providerBundle;
|
|
260
|
+
if(!providers) throw new Error('DataProvider not found. Did you call setDataProvider in App.svelte?');
|
|
261
|
+
return Object.freeze(definedOptions({
|
|
256
262
|
dataProvider: providers,
|
|
257
263
|
authProvider,
|
|
258
264
|
accessControlProvider: getLegacyAccessControlProvider(),
|
|
@@ -263,56 +269,56 @@ export function captureAdminContext(): AdminContextAccessor {
|
|
|
263
269
|
agentProvider: getLegacyAgentProvider(),
|
|
264
270
|
taskProvider: taskProviderState,
|
|
265
271
|
routerProvider,
|
|
266
|
-
};
|
|
272
|
+
}));
|
|
267
273
|
},
|
|
268
|
-
get providers() { return scopedContext
|
|
269
|
-
get authProvider() { return scopedContext
|
|
270
|
-
get resources() { return scopedContext
|
|
271
|
-
get routerProvider() { return scopedContext
|
|
272
|
-
get liveProvider() { return scopedContext
|
|
273
|
-
get taskProvider() { return scopedContext
|
|
274
|
+
get providers() { return scopedContext? scopedContext.providers:providers; },
|
|
275
|
+
get authProvider() { return scopedContext? scopedContext.authProvider:authProvider; },
|
|
276
|
+
get resources() { return scopedContext? scopedContext.resources:resources??[]; },
|
|
277
|
+
get routerProvider() { return scopedContext? scopedContext.routerProvider:routerProvider; },
|
|
278
|
+
get liveProvider() { return scopedContext? scopedContext.liveProvider:liveProviderState; },
|
|
279
|
+
get taskProvider() { return scopedContext? scopedContext.taskProvider:taskProviderState; },
|
|
274
280
|
get accessControlProvider() {
|
|
275
|
-
return scopedContext
|
|
281
|
+
return scopedContext? scopedContext.accessControlProvider:getLegacyAccessControlProvider();
|
|
276
282
|
},
|
|
277
|
-
get auditLogProvider() { return scopedContext
|
|
283
|
+
get auditLogProvider() { return scopedContext? scopedContext.auditLogProvider:getLegacyAuditLogProvider(); },
|
|
278
284
|
get notificationProvider() {
|
|
279
|
-
return scopedContext
|
|
285
|
+
return scopedContext? scopedContext.notificationProvider:getLegacyNotificationProvider();
|
|
280
286
|
},
|
|
281
|
-
get chatProvider() { return scopedContext
|
|
282
|
-
get agentProvider() { return scopedContext
|
|
283
|
-
get organizationProvider() { return scopedContext?.organizationProvider
|
|
284
|
-
get identityGovernanceProvider() { return scopedContext?.identityGovernanceProvider
|
|
285
|
-
get sessionProvider() { return scopedContext?.sessionProvider
|
|
286
|
-
get credentialProvider() { return scopedContext?.credentialProvider
|
|
287
|
+
get chatProvider() { return scopedContext? scopedContext.chatProvider:getLegacyChatProvider(); },
|
|
288
|
+
get agentProvider() { return scopedContext? scopedContext.agentProvider:getLegacyAgentProvider(); },
|
|
289
|
+
get organizationProvider() { return scopedContext?.organizationProvider??null; },
|
|
290
|
+
get identityGovernanceProvider() { return scopedContext?.identityGovernanceProvider??null; },
|
|
291
|
+
get sessionProvider() { return scopedContext?.sessionProvider??null; },
|
|
292
|
+
get credentialProvider() { return scopedContext?.credentialProvider??null; },
|
|
287
293
|
get tenant() { return scopedContext?.tenant; },
|
|
288
294
|
get tenantAdapter() { return scopedContext?.tenantAdapter; },
|
|
289
295
|
get tenantCacheKey() {
|
|
290
|
-
return accessor.tenant
|
|
296
|
+
return accessor.tenant? createTenantCacheKey(accessor.tenant,accessor.tenantAdapter):undefined;
|
|
291
297
|
},
|
|
292
298
|
get enterpriseRequestContext() {
|
|
293
|
-
const tenant
|
|
294
|
-
return {
|
|
299
|
+
const tenant=accessor.tenant;
|
|
300
|
+
return definedOptions({
|
|
295
301
|
tenantId: tenant?.tenantId,
|
|
296
|
-
requestId: typeof tenant?.meta?.requestId
|
|
297
|
-
traceId: typeof tenant?.meta?.traceId
|
|
302
|
+
requestId: typeof tenant?.meta?.['requestId']==='string'? tenant.meta['requestId']:undefined,
|
|
303
|
+
traceId: typeof tenant?.meta?.['traceId']==='string'? tenant.meta['traceId']:undefined,
|
|
298
304
|
meta: tenant?.meta,
|
|
299
|
-
};
|
|
305
|
+
});
|
|
300
306
|
},
|
|
301
307
|
getDataProvider(name) {
|
|
302
|
-
const activeProviders
|
|
303
|
-
if
|
|
304
|
-
const key
|
|
305
|
-
const provider
|
|
306
|
-
if
|
|
308
|
+
const activeProviders=accessor.providers;
|
|
309
|
+
if(!activeProviders) throw new Error('DataProvider not found. Did you call setDataProvider in App.svelte?');
|
|
310
|
+
const key=name??'default';
|
|
311
|
+
const provider=activeProviders[key];
|
|
312
|
+
if(!provider) {
|
|
307
313
|
throw new Error(`DataProvider "${key}" not found. Available: ${Object.keys(activeProviders).join(', ')}`);
|
|
308
314
|
}
|
|
309
315
|
return adaptProvider(provider);
|
|
310
316
|
},
|
|
311
317
|
getDataProviderNames() {
|
|
312
|
-
return accessor.providers
|
|
318
|
+
return accessor.providers? Object.keys(accessor.providers):[];
|
|
313
319
|
},
|
|
314
|
-
resolveDataProviderName(resourceName,
|
|
315
|
-
if
|
|
320
|
+
resolveDataProviderName(resourceName,overrideName) {
|
|
321
|
+
if(overrideName) {
|
|
316
322
|
try {
|
|
317
323
|
accessor.getDataProvider(overrideName);
|
|
318
324
|
return overrideName;
|
|
@@ -322,9 +328,9 @@ export function captureAdminContext(): AdminContextAccessor {
|
|
|
322
328
|
}
|
|
323
329
|
|
|
324
330
|
try {
|
|
325
|
-
const resource
|
|
326
|
-
const providerName
|
|
327
|
-
if
|
|
331
|
+
const resource=accessor.getResource(resourceName);
|
|
332
|
+
const providerName=resource.provider?.dataProviderName??resource.meta?.dataProviderName;
|
|
333
|
+
if(providerName) {
|
|
328
334
|
accessor.getDataProvider(providerName);
|
|
329
335
|
return providerName;
|
|
330
336
|
}
|
|
@@ -334,74 +340,80 @@ export function captureAdminContext(): AdminContextAccessor {
|
|
|
334
340
|
|
|
335
341
|
return 'default';
|
|
336
342
|
},
|
|
337
|
-
getDataProviderForResource(resourceName,
|
|
338
|
-
return accessor.getDataProvider(accessor.resolveDataProviderName(resourceName,
|
|
343
|
+
getDataProviderForResource(resourceName,overrideName) {
|
|
344
|
+
return accessor.getDataProvider(accessor.resolveDataProviderName(resourceName,overrideName));
|
|
339
345
|
},
|
|
340
|
-
queryKeys(resourceName,
|
|
346
|
+
queryKeys(resourceName,overrideName) {
|
|
341
347
|
return keys({
|
|
342
|
-
|
|
343
|
-
|
|
348
|
+
...definedOptions({
|
|
349
|
+
provider: accessor.resolveDataProviderName(resourceName??'',overrideName),
|
|
350
|
+
tenant: accessor.tenantCacheKey?.__svadminTenant
|
|
351
|
+
})
|
|
344
352
|
});
|
|
345
353
|
},
|
|
346
|
-
queryKeyMatcher(resourceName,
|
|
354
|
+
queryKeyMatcher(resourceName,overrideName) {
|
|
347
355
|
return {
|
|
348
|
-
provider: accessor.resolveDataProviderName(resourceName
|
|
356
|
+
provider: accessor.resolveDataProviderName(resourceName??'',overrideName),
|
|
349
357
|
tenant: accessor.tenantCacheKey?.__svadminTenant,
|
|
350
358
|
};
|
|
351
359
|
},
|
|
352
|
-
getProviderMeta(resourceName,
|
|
353
|
-
const resource
|
|
354
|
-
? accessor.resources.find((candidate) => candidate.identifier
|
|
355
|
-
:
|
|
356
|
-
const providerConfig
|
|
357
|
-
const tenant
|
|
358
|
-
if
|
|
360
|
+
getProviderMeta(resourceName,meta) {
|
|
361
|
+
const resource=resourceName
|
|
362
|
+
? accessor.resources.find((candidate) => candidate.identifier===resourceName||candidate.name===resourceName)
|
|
363
|
+
:undefined;
|
|
364
|
+
const providerConfig=resource?.provider;
|
|
365
|
+
const tenant=accessor.tenant;
|
|
366
|
+
if(!providerConfig&&!tenant) return meta;
|
|
359
367
|
|
|
360
368
|
return {
|
|
361
|
-
...(providerConfig?.meta
|
|
362
|
-
...(meta
|
|
363
|
-
...(providerConfig?.transport
|
|
364
|
-
...(providerConfig?.adapter
|
|
365
|
-
...(tenant
|
|
369
|
+
...(providerConfig?.meta??{}),
|
|
370
|
+
...(meta??{}),
|
|
371
|
+
...(providerConfig?.transport===undefined? {}:{ transport: providerConfig.transport }),
|
|
372
|
+
...(providerConfig?.adapter===undefined? {}:{ adapter: providerConfig.adapter }),
|
|
373
|
+
...(tenant? resolveTenantProviderMeta(tenant,accessor.tenantAdapter):{}),
|
|
366
374
|
};
|
|
367
375
|
},
|
|
368
376
|
getResource(nameOrIdentifier) {
|
|
369
|
-
const resource
|
|
370
|
-
(candidate) => candidate.identifier
|
|
377
|
+
const resource=accessor.resources.find(
|
|
378
|
+
(candidate) => candidate.identifier===nameOrIdentifier||candidate.name===nameOrIdentifier,
|
|
371
379
|
);
|
|
372
|
-
if
|
|
380
|
+
if(!resource) throw new Error(`Resource "${nameOrIdentifier}" not found in resource definitions.`);
|
|
373
381
|
return resource;
|
|
374
382
|
},
|
|
375
383
|
currentPath() {
|
|
376
|
-
if
|
|
384
|
+
if(scopedContext) return currentPathWithProvider(scopedContext.routerProvider);
|
|
377
385
|
return currentLegacyPath();
|
|
378
386
|
},
|
|
379
387
|
formatLink(path) {
|
|
380
|
-
if
|
|
388
|
+
if(scopedContext) return formatLinkWithProvider(scopedContext.routerProvider,path);
|
|
381
389
|
return formatLegacyLink(path);
|
|
382
390
|
},
|
|
383
|
-
async navigate(path,
|
|
384
|
-
if
|
|
385
|
-
await navigateWithProvider(scopedContext.routerProvider,
|
|
391
|
+
async navigate(path,options) {
|
|
392
|
+
if(scopedContext) {
|
|
393
|
+
await navigateWithProvider(scopedContext.routerProvider,path,options);
|
|
386
394
|
return;
|
|
387
395
|
}
|
|
388
|
-
await navigateLegacy(path,
|
|
396
|
+
await navigateLegacy(path,options);
|
|
389
397
|
},
|
|
390
398
|
back() {
|
|
391
|
-
const activeRouter
|
|
392
|
-
if
|
|
399
|
+
const activeRouter=accessor.routerProvider;
|
|
400
|
+
if(activeRouter?.back) {
|
|
393
401
|
activeRouter.back();
|
|
394
|
-
} else if
|
|
402
|
+
} else if(typeof window!=='undefined') {
|
|
395
403
|
window.history.back();
|
|
396
404
|
}
|
|
397
405
|
},
|
|
398
406
|
};
|
|
399
407
|
|
|
408
|
+
Object.defineProperties(accessor, {
|
|
409
|
+
accessControlProvider: { configurable: false },
|
|
410
|
+
providerBundle: { configurable: false },
|
|
411
|
+
});
|
|
400
412
|
return accessor;
|
|
401
413
|
}
|
|
402
414
|
|
|
403
415
|
export function setDataProvider(provider: DataProviderInput): void {
|
|
404
|
-
providers
|
|
416
|
+
providers=normalizeDataProviders(provider);
|
|
405
417
|
}
|
|
406
418
|
|
|
407
419
|
export function getDataProvider(name?: string): DataProvider {
|
|
@@ -412,45 +424,45 @@ export function getDataProviderNames(): string[] {
|
|
|
412
424
|
return captureAdminContext().getDataProviderNames();
|
|
413
425
|
}
|
|
414
426
|
|
|
415
|
-
export function getDataProviderForResource(resourceName: string,
|
|
416
|
-
return captureAdminContext().getDataProviderForResource(resourceName,
|
|
427
|
+
export function getDataProviderForResource(resourceName: string,overrideName?: string): DataProvider {
|
|
428
|
+
return captureAdminContext().getDataProviderForResource(resourceName,overrideName);
|
|
417
429
|
}
|
|
418
430
|
|
|
419
|
-
export function getProviderBundle():
|
|
431
|
+
export function getProviderBundle(): ResolvedProviderBundle {
|
|
420
432
|
return captureAdminContext().providerBundle;
|
|
421
433
|
}
|
|
422
434
|
|
|
423
435
|
function isDataProvider(value: unknown): value is DataProvider {
|
|
424
436
|
return (
|
|
425
|
-
value
|
|
426
|
-
typeof value
|
|
427
|
-
'getList' in value
|
|
428
|
-
typeof (value as DataProvider).getList
|
|
437
|
+
value!==null&&
|
|
438
|
+
typeof value==='object'&&
|
|
439
|
+
'getList' in value&&
|
|
440
|
+
typeof (value as DataProvider).getList==='function'
|
|
429
441
|
);
|
|
430
442
|
}
|
|
431
443
|
|
|
432
444
|
// ─── Auth Provider ──────────────────────────────────────────────
|
|
433
445
|
|
|
434
|
-
let authProvider
|
|
446
|
+
let authProvider=$state<AuthProvider|null>(null);
|
|
435
447
|
|
|
436
|
-
export function setAuthProvider(provider: AuthProvider
|
|
437
|
-
authProvider
|
|
448
|
+
export function setAuthProvider(provider: AuthProvider|null|undefined): void {
|
|
449
|
+
authProvider=provider||null;
|
|
438
450
|
}
|
|
439
451
|
|
|
440
452
|
export function getAuthProvider(): AuthProvider;
|
|
441
|
-
export function getAuthProvider(options: { optional: true }): AuthProvider
|
|
442
|
-
export function getAuthProvider(options?: { optional?: boolean }): AuthProvider
|
|
443
|
-
const activeAuthProvider
|
|
444
|
-
if
|
|
453
|
+
export function getAuthProvider(options: { optional: true }): AuthProvider|null;
|
|
454
|
+
export function getAuthProvider(options?: { optional?: boolean }): AuthProvider|null {
|
|
455
|
+
const activeAuthProvider=captureAdminContext().authProvider;
|
|
456
|
+
if(!activeAuthProvider&&!options?.optional) throw new Error('AuthProvider not found. Did you call setAuthProvider in App.svelte?');
|
|
445
457
|
return activeAuthProvider;
|
|
446
458
|
}
|
|
447
459
|
|
|
448
460
|
// ─── Resources ──────────────────────────────────────────────────
|
|
449
461
|
|
|
450
|
-
let resources
|
|
462
|
+
let resources=$state.raw<ResourceDefinition[]>([]);
|
|
451
463
|
|
|
452
464
|
export function setResources(newResources: ResourceDefinition[]): void {
|
|
453
|
-
resources
|
|
465
|
+
resources=newResources;
|
|
454
466
|
}
|
|
455
467
|
|
|
456
468
|
export function getResources(): ResourceDefinition[] {
|
|
@@ -463,42 +475,42 @@ export function getResource(nameOrIdentifier: string): ResourceDefinition {
|
|
|
463
475
|
|
|
464
476
|
// ─── Router Provider ────────────────────────────────────────────
|
|
465
477
|
|
|
466
|
-
let routerProvider
|
|
478
|
+
let routerProvider=$state<RouterProvider|undefined>(undefined);
|
|
467
479
|
|
|
468
|
-
export function setRouterProvider(provider: RouterProvider
|
|
469
|
-
routerProvider
|
|
480
|
+
export function setRouterProvider(provider: RouterProvider|undefined): void {
|
|
481
|
+
routerProvider=provider;
|
|
470
482
|
}
|
|
471
483
|
|
|
472
|
-
export function getRouterProvider(): RouterProvider
|
|
484
|
+
export function getRouterProvider(): RouterProvider|undefined {
|
|
473
485
|
return captureAdminContext().routerProvider;
|
|
474
486
|
}
|
|
475
487
|
|
|
476
488
|
|
|
477
489
|
// ─── Live Provider ──────────────────────────────────────────────
|
|
478
490
|
|
|
479
|
-
let liveProviderState
|
|
491
|
+
let liveProviderState=$state<LiveProvider|undefined>(undefined);
|
|
480
492
|
|
|
481
493
|
export function setLiveProvider(provider: LiveProvider): void {
|
|
482
|
-
liveProviderState
|
|
494
|
+
liveProviderState=provider;
|
|
483
495
|
}
|
|
484
496
|
|
|
485
|
-
export function getLiveProvider(): LiveProvider
|
|
497
|
+
export function getLiveProvider(): LiveProvider|undefined {
|
|
486
498
|
return captureAdminContext().liveProvider;
|
|
487
499
|
}
|
|
488
500
|
|
|
489
501
|
// ─── Task Provider ──────────────────────────────────────────────
|
|
490
502
|
|
|
491
|
-
let taskProviderState
|
|
503
|
+
let taskProviderState=$state<TaskProvider|undefined>(undefined);
|
|
492
504
|
|
|
493
|
-
export function setTaskProvider(provider: TaskProvider
|
|
494
|
-
taskProviderState
|
|
505
|
+
export function setTaskProvider(provider: TaskProvider|undefined): void {
|
|
506
|
+
taskProviderState=provider;
|
|
495
507
|
}
|
|
496
508
|
|
|
497
509
|
export function getTaskProvider(): TaskProvider;
|
|
498
|
-
export function getTaskProvider(options: { optional: true }): TaskProvider
|
|
499
|
-
export function getTaskProvider(options?: { optional?: boolean }): TaskProvider
|
|
500
|
-
const activeTaskProvider
|
|
501
|
-
if
|
|
510
|
+
export function getTaskProvider(options: { optional: true }): TaskProvider|undefined;
|
|
511
|
+
export function getTaskProvider(options?: { optional?: boolean }): TaskProvider|undefined {
|
|
512
|
+
const activeTaskProvider=captureAdminContext().taskProvider;
|
|
513
|
+
if(!activeTaskProvider&&!options?.optional) {
|
|
502
514
|
throw new Error('TaskProvider not found. Did you call setTaskProvider in App.svelte?');
|
|
503
515
|
}
|
|
504
516
|
return activeTaskProvider;
|
|
@@ -507,12 +519,12 @@ export function getTaskProvider(options?: { optional?: boolean }): TaskProvider
|
|
|
507
519
|
// ─── Reset — for testing / HMR ─────────────────────────────────
|
|
508
520
|
|
|
509
521
|
export function resetContext(): void {
|
|
510
|
-
providers
|
|
511
|
-
authProvider
|
|
512
|
-
resources
|
|
513
|
-
routerProvider
|
|
514
|
-
liveProviderState
|
|
515
|
-
taskProviderState
|
|
522
|
+
providers=null;
|
|
523
|
+
authProvider=null;
|
|
524
|
+
resources=[];
|
|
525
|
+
routerProvider=undefined;
|
|
526
|
+
liveProviderState=undefined;
|
|
527
|
+
taskProviderState=undefined;
|
|
516
528
|
resetNotificationProvider();
|
|
517
529
|
resetAuditLogProvider();
|
|
518
530
|
resetAccessControlProvider();
|