@praxisui/core 9.0.57 → 9.0.58
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 +22 -0
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-core.mjs +39 -0
- package/package.json +1 -1
- package/types/praxisui-core.d.ts +15 -2
package/README.md
CHANGED
|
@@ -167,6 +167,28 @@ Component-owned config editors, AI authoring manifests, and runtime profiles are
|
|
|
167
167
|
|
|
168
168
|
The validator performs no rendering, dispatch, HTTP call or persistence. Pass the same `ComponentMetadataRegistry` that the target host uses for dynamic materialization. Registry presence is the materializability evidence supported by the current contract; component packages remain responsible for publishing and testing their own metadata providers.
|
|
169
169
|
|
|
170
|
+
## Remote Configuration Persistence
|
|
171
|
+
|
|
172
|
+
`providePraxisGlobalConfigBootstrap` is the official host entry point for
|
|
173
|
+
`ApiConfigStorage`. Set `scope` explicitly whenever ownership is a product
|
|
174
|
+
decision instead of a lookup preference:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
providePraxisGlobalConfigBootstrap({
|
|
178
|
+
remote: { apiPath: "/api" },
|
|
179
|
+
scope: "tenant",
|
|
180
|
+
headersFactory: () => enterpriseRuntimeContext.headers(),
|
|
181
|
+
errorPolicy: "fail",
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Use `scope: "tenant"` for a shared governed document such as an application
|
|
186
|
+
page composition, and `scope: "user"` for personal preferences. Omitting the
|
|
187
|
+
option deliberately preserves the `praxis-config-starter` resolution rule:
|
|
188
|
+
requests carrying `X-User-ID` resolve user config first, while tenant config is
|
|
189
|
+
the fallback for reads. Scope selects persistence ownership; it never replaces
|
|
190
|
+
server-side identity resolution or write authorization.
|
|
191
|
+
|
|
170
192
|
## Dynamic Page Runtime
|
|
171
193
|
|
|
172
194
|
`DynamicWidgetPageComponent` renders `WidgetPageDefinition` documents.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-03T03:04:37.933Z",
|
|
4
4
|
"packageName": "@praxisui/core",
|
|
5
|
-
"packageVersion": "9.0.
|
|
5
|
+
"packageVersion": "9.0.58",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 4,
|
|
@@ -16296,6 +16296,7 @@ class ResourceActionOpenAdapterService {
|
|
|
16296
16296
|
if (options.initialValue) {
|
|
16297
16297
|
payload.widget.inputs['initialValue'] = this.clone(options.initialValue);
|
|
16298
16298
|
}
|
|
16299
|
+
this.applyInteractionPresentation(payload, action);
|
|
16299
16300
|
if (action.scope === 'ITEM') {
|
|
16300
16301
|
if (options.resourceId != null) {
|
|
16301
16302
|
payload.widget.inputs['resourceId'] = options.resourceId;
|
|
@@ -16313,6 +16314,43 @@ class ResourceActionOpenAdapterService {
|
|
|
16313
16314
|
this.applyExecutionInputs(payload, action, options);
|
|
16314
16315
|
return payload;
|
|
16315
16316
|
}
|
|
16317
|
+
applyInteractionPresentation(payload, action) {
|
|
16318
|
+
const requiresFormConfirmation = action.execution?.interaction.mode === 'FORM'
|
|
16319
|
+
&& action.execution.interaction.confirmationRequired;
|
|
16320
|
+
const confirmationMessage = requiresFormConfirmation
|
|
16321
|
+
? String(action.description ?? '').trim() || String(action.title ?? '').trim()
|
|
16322
|
+
: '';
|
|
16323
|
+
if (requiresFormConfirmation && !confirmationMessage) {
|
|
16324
|
+
throw new Error(`ResourceActionOpenAdapterService requires description or title for confirmed FORM action "${action.id}".`);
|
|
16325
|
+
}
|
|
16326
|
+
const successMessage = String(action.successMessage ?? '').trim();
|
|
16327
|
+
if (!confirmationMessage && !successMessage) {
|
|
16328
|
+
return;
|
|
16329
|
+
}
|
|
16330
|
+
const inputs = payload.widget.inputs;
|
|
16331
|
+
const currentConfig = this.clone(inputs['config'] ?? {});
|
|
16332
|
+
const currentMessages = this.clone(currentConfig['messages'] ?? {});
|
|
16333
|
+
if (confirmationMessage) {
|
|
16334
|
+
currentMessages['confirmations'] = {
|
|
16335
|
+
...(currentMessages['confirmations'] ?? {}),
|
|
16336
|
+
submit: confirmationMessage,
|
|
16337
|
+
};
|
|
16338
|
+
}
|
|
16339
|
+
if (successMessage) {
|
|
16340
|
+
const customActions = {
|
|
16341
|
+
...(currentMessages['customActions'] ?? {}),
|
|
16342
|
+
};
|
|
16343
|
+
customActions['submit'] = {
|
|
16344
|
+
...(customActions['submit'] ?? {}),
|
|
16345
|
+
success: successMessage,
|
|
16346
|
+
};
|
|
16347
|
+
currentMessages['customActions'] = customActions;
|
|
16348
|
+
}
|
|
16349
|
+
inputs['config'] = {
|
|
16350
|
+
...currentConfig,
|
|
16351
|
+
messages: currentMessages,
|
|
16352
|
+
};
|
|
16353
|
+
}
|
|
16316
16354
|
resolveDynamicFormPreset() {
|
|
16317
16355
|
const preset = SURFACE_OPEN_PRESETS.find((candidate) => candidate.id === 'praxis-dynamic-form');
|
|
16318
16356
|
if (!preset) {
|
|
@@ -19802,6 +19840,7 @@ function providePraxisGlobalConfigBootstrap(options) {
|
|
|
19802
19840
|
const baseUrl = resolveBaseUrl(normalized.remote);
|
|
19803
19841
|
const apiOptions = {
|
|
19804
19842
|
...(baseUrl ? { baseUrl } : {}),
|
|
19843
|
+
...(normalized.scope ? { scope: normalized.scope } : {}),
|
|
19805
19844
|
headersFactory,
|
|
19806
19845
|
defaultHeaders: normalized.includeDefaultHeaders ? undefined : {},
|
|
19807
19846
|
errorPolicy: normalized.errorPolicy,
|
package/package.json
CHANGED
package/types/praxisui-core.d.ts
CHANGED
|
@@ -6191,8 +6191,13 @@ declare const CONFIG_STORAGE: InjectionToken<ConfigStorage>;
|
|
|
6191
6191
|
*/
|
|
6192
6192
|
interface ApiConfigStorageOptions {
|
|
6193
6193
|
baseUrl?: string;
|
|
6194
|
-
/**
|
|
6195
|
-
|
|
6194
|
+
/**
|
|
6195
|
+
* Explicit ui_user_config ownership.
|
|
6196
|
+
*
|
|
6197
|
+
* Omit only when the host deliberately wants the backend resolution rule
|
|
6198
|
+
* (user first when X-User-ID is present, then tenant on reads).
|
|
6199
|
+
*/
|
|
6200
|
+
scope?: 'user' | 'tenant';
|
|
6196
6201
|
/** Factory to supply headers (tenant/user/env/updatedBy) per request. */
|
|
6197
6202
|
headersFactory?: () => Record<string, string | undefined>;
|
|
6198
6203
|
/** Default headers applied when the headersFactory omits them. */
|
|
@@ -10863,6 +10868,7 @@ interface ResourceActionOpenAdapterOptions {
|
|
|
10863
10868
|
declare class ResourceActionOpenAdapterService {
|
|
10864
10869
|
private readonly discovery;
|
|
10865
10870
|
toPayload(action: ResourceActionCatalogItem, options: ResourceActionOpenAdapterOptions): SurfaceOpenPayload;
|
|
10871
|
+
private applyInteractionPresentation;
|
|
10866
10872
|
private resolveDynamicFormPreset;
|
|
10867
10873
|
private buildStableInstanceId;
|
|
10868
10874
|
private applyExecutionInputs;
|
|
@@ -11867,6 +11873,13 @@ interface PraxisGlobalConfigBootstrapOptions {
|
|
|
11867
11873
|
baseUrl?: string;
|
|
11868
11874
|
apiPath?: string;
|
|
11869
11875
|
};
|
|
11876
|
+
/**
|
|
11877
|
+
* Explicit ownership for every config key handled by this bootstrap.
|
|
11878
|
+
* Use `tenant` for shared governed configuration and `user` for personal
|
|
11879
|
+
* preferences. When omitted, praxis-config-starter applies its canonical
|
|
11880
|
+
* header-based resolution rule.
|
|
11881
|
+
*/
|
|
11882
|
+
scope?: 'user' | 'tenant';
|
|
11870
11883
|
headers?: Record<string, string>;
|
|
11871
11884
|
headersFactory?: () => Record<string, string>;
|
|
11872
11885
|
includeDefaultHeaders?: boolean;
|