@nexia/sdk 0.7.2 → 0.8.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/dist/actions.d.ts +4 -0
- package/dist/approval.d.ts +3 -0
- package/dist/host.d.ts +38 -10
- package/dist/host.js +97 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/organization-target.d.ts +5 -1
- package/dist/resources/resource-form.d.ts +64 -0
- package/dist/resources/resource-form.js +4 -0
- package/dist/shell.d.ts +3 -1
- package/dist/vite.d.mts +9 -0
- package/dist/vite.mjs +65 -0
- package/package.json +3 -2
- package/dist/resources/resource-information.d.ts +0 -164
- package/dist/resources/resource-information.js +0 -12
package/dist/actions.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface NxActionsProps {
|
|
|
9
9
|
id: string;
|
|
10
10
|
label: string;
|
|
11
11
|
}>;
|
|
12
|
+
/** Declared inputs from the displayed record, such as concurrency tokens.
|
|
13
|
+
* Captured when confirmation opens; server planning/authorization still apply.
|
|
14
|
+
* Do not pass credentials or secrets. */
|
|
15
|
+
inputByAction?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
12
16
|
legalEntityPublicId?: string | null;
|
|
13
17
|
disabledKeys?: readonly string[];
|
|
14
18
|
onSuccess?: (actionKey: string, response: unknown) => void;
|
package/dist/approval.d.ts
CHANGED
|
@@ -155,6 +155,9 @@ export interface ApprovalBusinessFormSlotPropsV2 {
|
|
|
155
155
|
binding: ApprovalBusinessFormBinding;
|
|
156
156
|
subject?: ApprovalBusinessFormSubject;
|
|
157
157
|
appDraftRef?: string | null;
|
|
158
|
+
/** Source resource identity for an opted-in copy. Authorize in the App and
|
|
159
|
+
* import allowed fields into a new draft; never treat it as appDraftRef. */
|
|
160
|
+
copySourceResourceId?: string | null;
|
|
158
161
|
registerController: (controller: ApprovalBusinessFormController | null) => void;
|
|
159
162
|
}
|
|
160
163
|
export type ApprovalBusinessFormWidgetLoader = () => Promise<{
|
package/dist/host.d.ts
CHANGED
|
@@ -3,21 +3,20 @@ import { type ComponentType, type ReactNode } from 'react';
|
|
|
3
3
|
import type { AxiosInstance } from 'axios';
|
|
4
4
|
import type { ApprovalBusinessFormRegistrar, ApprovalBusinessFormRegistry } from './approval';
|
|
5
5
|
import type { ContextQueryResult, PermissionsQueryResult } from './context';
|
|
6
|
-
import type { DataMigrationBackgroundOperationClient, DataMigrationRegistrar, DataMigrationRegistry } from './data-migration';
|
|
7
|
-
import type { ProcessUserTaskFormRegistrar, ProcessUserTaskFormRegistry } from './process';
|
|
6
|
+
import type { DataMigrationBackgroundOperationClient, DataMigrationProviderRegistration, DataMigrationRegistrar, DataMigrationRegistry, DataMigrationStageRegistration, DataMigrationTargetRegistration } from './data-migration';
|
|
7
|
+
import type { ProcessUserTaskFormRegistration, ProcessUserTaskFormRegistrar, ProcessUserTaskFormRegistry } from './process';
|
|
8
8
|
import type { AppRouteFrameProps, AutoRegisterPackageSurfacesOptions, FormFieldErrors, InspectorActionProps, InspectorResourceActionsProps, MessageApi, MutationFormError, NxAdaptiveSplitProps, NxActionButtonProps, NxAlertProps, NxButtonProps, NxLinkButtonProps, NxIconButtonProps, NxIconLinkProps, NxCanonicalRoutePaneProps, NxCheckboxProps, NxColumnBrowserProps, NxColumnPickerProps, NxComboboxProps, NxDatePickerProps, NxDateRangePickerProps, NxDetailRowProps, NxEmptyViewProps, NxFieldGroupProps, NxFieldLegendProps, NxFieldsetProps, NxFileDropzoneProps, NxFormFieldProps, NxFormSectionProps, NxDropdownMenuProps, NxInsightFilterBarProps, NxInsightSurfaceProps, NxHelpTooltipProps, NxOverviewBandProps, InsightFilterControls, UseInsightFilterStateOptions, NxLoadingBlockProps, NxModalDialogProps, NxOrgChartProps, NxMissingRequiredReferencesAlertProps, NxPageFrameProps, NxPaginationProps, NxRadioGroupProps, NxRadioProps, NxRefreshControlProps, NxSearchFieldProps, NxSectionCardProps, SectionRowProps, NxSectionStackProps, NxResponsiveRegionProps, NxSelectProps, NxStatCardProps, NxStatusBadgeProps, NxSwitchProps, NxTabNavProps, NxTextAreaProps, NxTextInputProps, NxTooltipProps, OpenResourceWorkTab, ResourceCreateCompletion, ResourceCreateReceiverRegistration, ResourceInspectorAdapterRegistry, ResourceInspectorAdapterRegistrar, ResourceInspectorPanelProps, ResourceInspectorQueryProps, ResourceInspectorStackHostProps, ResourceInspectorStackProviderProps, ResourceInspectorStateProps, ResourceLinkProps, ResourceListParams, ResourceListParamsControls, ResourceListToolbarMoreMenuProps, ResourcePrimaryCellProps, ResourceRowActionsMenuProps, ResourceStatusBadgeProps, ResourceTableProps, ResourceTableSort, ResourceTextCellProps, UseRegisterListLocateActionOptions, UseResourceListParamsOptions, TabContextActionRegistration, RegisterDraftActionOptions, ToastOptions, WorkSectionProps, FavoriteTarget, WorkSurfaceLabelInput, WorkSurfaceLabels, WorkSurfaceProps } from './shell';
|
|
9
9
|
import type { AgentComponentRenderer, AttachmentDeleteResult, AttachmentQueryResult, AttachmentUploadOptions, AttachmentUploadResult, ApprovalRoutePoliciesQueryResult, ApprovalSharedLinesQueryResult, DashboardWidgetAutoHeightRef, LegalEntityMemberListParams, LegalEntityMemberQueryResult, LegalEntityApplicabilityQueryResult, LegalEntityQueryResult, MediaUploadResult, OperatingUnitQueryResult, OperatingUnitQueryScope, OperatingUnitScopeFieldProps, OperatingUnitScopeResult, OperatingUnitSelectionResult, PartyListParams, PartyQueryResult, TrustedAssetListParams, TrustedAssetsQueryResult, UploadFileClient } from './platform';
|
|
10
10
|
import type { NxOrganizationTargetSelectorProps, NxOperatingUnitSelectorProps, OrganizationListScopeMode, OrganizationListScopeResult, OrganizationTargetQuery, OrganizationTargetQueryResult } from './organization-target';
|
|
11
11
|
import type { NxCalendarProps, NxResourceSchedulerProps, ResourceBoardProps, ResourceScheduleProps } from './resources/resource-projections';
|
|
12
12
|
import type { NxDatasetExportWorkspaceProps, NxDatasetImportWorkspaceProps, NxInlineResourceCreateProps, NxResourceImportDialogProps, NxResourceTransferActionsProps } from './resources/resource-transfer';
|
|
13
|
-
import type {
|
|
13
|
+
import type { NxResourceFormLegalEntityFieldProps } from './resources/resource-form';
|
|
14
14
|
import type { SignatureAuthenticationMethodSelectorProps, SignatureInvitationChannelSelectorProps, SignatureRequestPreparationEditorProps, SignatureRequestPreparationExactPreviewProps, SignatureRequestPreparationPlacementEditorProps, SignatureSingleRequestDialogProps } from './signature';
|
|
15
15
|
import type { ResourceProjectionChangeSubscription } from './resource-reference';
|
|
16
16
|
import type { ResourceCreateDestinationRegistry } from './resource-create-destination';
|
|
17
17
|
export type { ResourceProjectionChangeSubscription } from './resource-reference';
|
|
18
18
|
/** Host-only visual component prop contracts. App packages import these from ./host. */
|
|
19
19
|
export type { AppRoutePrefetchContext, AppRoutePrefetcher, AutoRegisterPackageSurfacesOptions, PackageSurfaceLoader, PackageSurfaceOverride, PackageSurfaceOverrideRegistration, NxAdaptiveSplitAsideWidth, NxAdaptiveSplitBreakpoint, NxAdaptiveSplitDensity, NxAdaptiveSplitProps, NxActionButtonProps, NxAlertProps, NxButtonProps, NxLinkButtonProps, NxIconButtonProps, NxIconLinkProps, NxCanonicalRoutePaneProps, NxCheckboxProps, NxColumnBrowserLabels, NxColumnBrowserProps, NxColumnNode, NxColumnPickerLabels, NxColumnPickerProps, NxComboboxProps, NxDatePickerProps, NxDateRangePickerProps, NxDetailRowProps, NxDropdownMenuProps, NxEmptyViewProps, NxFieldGroupProps, NxFieldLegendProps, NxFieldsetProps, NxFileDropzoneProps, NxFormFieldProps, NxFormSectionProps, NxInsightFilterBarProps, NxInsightSurfaceProps, NxHelpTooltipProps, NxLoadingBlockProps, NxModalDialogProps, NxOrgChartItem, NxOrgChartLabels, NxOrgChartMember, NxOrgChartProps, NxMissingRequiredReferencesAlertProps, NxOverviewBandProps, NxPageFrameProps, NxRadioGroupProps, NxRadioProps, NxRefreshControlProps, NxResponsiveRegionProps, ResourceListToolbarMoreMenuProps, NxSearchFieldProps, NxSectionCardProps, SectionRowProps, NxSectionStackProps, NxSelectProps, NxStatCardProps, NxStatusBadgeProps, NxSwitchProps, NxTabNavItem, NxTabNavProps, NxTextAreaProps, NxTextInputProps, NxTooltipProps, ResourceListRefreshConfig, ResourceTableDensity, ResourceTableStyle, ResourceTableSummaryRow, } from './shell';
|
|
20
|
-
export type { NxResourceInformationFormProps, NxResourceFormLegalEntityFieldProps, NxResourceInformationViewProps, ResourceInformationControlProjection, ResourceInformationControlSlot, ResourceInformationCustomProjection, ResourceInformationEditProjection, ResourceInformationEditRenderContext, ResourceInformationField, ResourceInformationFieldSpan, ResourceInformationMode, ResourceInformationReadOnlyProjection, ResourceInformationRequirement, ResourceInformationSchema, ResourceInformationSection, ResourceInformationTranslator, ResourceInformationValue, } from './resources/resource-information';
|
|
21
20
|
export type { NxCalendarActionBinding, NxCalendarActionCommand, NxCalendarActionResult, NxCalendarInteraction, NxCalendarOccurrence, NxCalendarProps, NxCalendarRange, NxCalendarSelection, NxCalendarTemporalRange, NxCalendarView, NxResourceSchedulerActionBinding, NxResourceSchedulerActionCommand, NxResourceSchedulerActionResult, NxResourceSchedulerInteraction, NxResourceSchedulerOccurrence, NxResourceSchedulerProps, NxResourceSchedulerResource, NxResourceSchedulerSelection, NxResourceSchedulerView, ResourceBoardCard, ResourceBoardLabels, ResourceBoardLane, ResourceBoardLoadState, ResourceBoardMoveCommand, ResourceBoardMutationResult, ResourceBoardProjection, ResourceBoardProps, ResourceBoardSummaryField, ResourceProjectionReference, ResourceScheduleActionBinding, ResourceScheduleActionCommand, ResourceScheduleDatePair, ResourceScheduleDateSemantics, ResourceScheduleDependency, ResourceScheduleDependencyType, ResourceScheduleInteraction, ResourceScheduleItem, ResourceScheduleItemType, ResourceScheduleLoadState, ResourceScheduleMutationResult, ResourceScheduleProjection, ResourceScheduleProps, ResourceScheduleTimeUnit, ResourceScheduleView, } from './resources/resource-projections';
|
|
22
21
|
export type { DatasetImportConfirmationSummary, NxDatasetExportWorkspaceProps, NxDatasetImportWorkspaceProps, NxInlineResourceCreateProps, NxResourceImportDialogProps, NxResourceTransferActionsProps, } from './resources/resource-transfer';
|
|
23
22
|
export { projectSignatureCapabilityCatalog, signatureCapabilityIdentity, } from './signature';
|
|
@@ -153,6 +152,8 @@ export interface OpenFileOptions {
|
|
|
153
152
|
}
|
|
154
153
|
export interface NexiaAppFrontendHostBindings {
|
|
155
154
|
api: AxiosInstance;
|
|
155
|
+
/** Build-bound services; the host selects the backend before an App entry runs. */
|
|
156
|
+
appServices?: (appKey: string) => NexiaAppRequestServices;
|
|
156
157
|
components: {
|
|
157
158
|
AppRouteFrame: typeof AppRouteFrame;
|
|
158
159
|
InspectorAction: typeof InspectorAction;
|
|
@@ -189,15 +190,13 @@ export interface NexiaAppFrontendHostBindings {
|
|
|
189
190
|
FavoriteButton: ComponentType<FavoriteButtonProps>;
|
|
190
191
|
NxFormField: typeof NxFormField;
|
|
191
192
|
NxFormSection: typeof NxFormSection;
|
|
193
|
+
NxResourceFormLegalEntityField: ComponentType<NxResourceFormLegalEntityFieldProps>;
|
|
192
194
|
NxHelpTooltip: ComponentType<NxHelpTooltipProps>;
|
|
193
195
|
NxInsightFilterBar: typeof NxInsightFilterBar;
|
|
194
196
|
NxInsightSurface: typeof NxInsightSurface;
|
|
195
197
|
NxLineChart: typeof NxLineChart;
|
|
196
198
|
NxResourceScheduler: typeof NxResourceScheduler;
|
|
197
199
|
NxResourceImportDialog: ComponentType<NxResourceImportDialogProps>;
|
|
198
|
-
NxResourceFormLegalEntityField: ComponentType<NxResourceFormLegalEntityFieldProps>;
|
|
199
|
-
NxResourceInformationForm: <TViewContext, TEditContext>(props: NxResourceInformationFormProps<TViewContext, TEditContext>) => ReactNode;
|
|
200
|
-
NxResourceInformationView: <TViewContext, TEditContext>(props: NxResourceInformationViewProps<TViewContext, TEditContext>) => ReactNode;
|
|
201
200
|
NxResourceTransferActions: ComponentType<NxResourceTransferActionsProps>;
|
|
202
201
|
NxDatasetExportWorkspace: ComponentType<NxDatasetExportWorkspaceProps>;
|
|
203
202
|
NxDatasetImportWorkspace: ComponentType<NxDatasetImportWorkspaceProps>;
|
|
@@ -275,6 +274,7 @@ export interface NexiaAppFrontendHostBindings {
|
|
|
275
274
|
useIsActiveWorkTabVisible: () => boolean;
|
|
276
275
|
useMarkTabDirty: (dirty: boolean, snapshot?: string, initialSnapshot?: string) => void;
|
|
277
276
|
useClearTabDirty: () => () => void;
|
|
277
|
+
useReauthenticate: () => () => Promise<void>;
|
|
278
278
|
useMessage: () => MessageApi;
|
|
279
279
|
useOpenResourceWorkTab: (defaultIcon?: string) => OpenResourceWorkTab;
|
|
280
280
|
useRegisterResourceCreateReceiver: (registration: ResourceCreateReceiverRegistration | null) => void;
|
|
@@ -319,6 +319,34 @@ export interface NexiaAppFrontendHostBindings {
|
|
|
319
319
|
resourceInspectorAdapterRegistry: ResourceInspectorAdapterRegistry;
|
|
320
320
|
};
|
|
321
321
|
}
|
|
322
|
+
export interface NexiaAppRequestServices {
|
|
323
|
+
api: AxiosInstance;
|
|
324
|
+
openFile: (href: string, options?: OpenFileOptions) => Promise<void>;
|
|
325
|
+
wrapComponent?: <P extends object>(component: ComponentType<P>) => ComponentType<P>;
|
|
326
|
+
}
|
|
327
|
+
/** Used by the SDK build facade, not by application source. Captures a fixed owner. */
|
|
328
|
+
export declare function bindNexiaAppRequestServices(appKey: string): {
|
|
329
|
+
resourceInspectorAdapterRegistry: ResourceInspectorAdapterRegistrar;
|
|
330
|
+
autoRegisterPackageResourceInspectors(modules: Record<string, unknown>, contracts?: Record<string, unknown>): void;
|
|
331
|
+
autoRegisterPackageSurfaces(options: AutoRegisterPackageSurfacesOptions): void;
|
|
332
|
+
approvalComposerBusinessFormRegistry: ApprovalBusinessFormRegistrar;
|
|
333
|
+
processUserTaskFormRegistry: {
|
|
334
|
+
register(registration: ProcessUserTaskFormRegistration): void;
|
|
335
|
+
};
|
|
336
|
+
dataMigrationRegistry: {
|
|
337
|
+
registerProvider: (registration: DataMigrationProviderRegistration) => void;
|
|
338
|
+
registerTarget: (registration: DataMigrationTargetRegistration) => void;
|
|
339
|
+
registerStage(registration: DataMigrationStageRegistration): void;
|
|
340
|
+
};
|
|
341
|
+
registerAgentComponent(name: string, component: AgentComponentRenderer): void;
|
|
342
|
+
registerLazyAgentComponent(name: string, load: () => Promise<{
|
|
343
|
+
default: AgentComponentRenderer;
|
|
344
|
+
}>): void;
|
|
345
|
+
api: AxiosInstance;
|
|
346
|
+
openFile: (href: string, options?: OpenFileOptions) => Promise<void>;
|
|
347
|
+
sendUserInvitation(payload: UserInvitationPayload): Promise<UserInvitationResponse>;
|
|
348
|
+
useDataMigrationBackgroundOperation(): DataMigrationBackgroundOperationClient;
|
|
349
|
+
};
|
|
322
350
|
/**
|
|
323
351
|
* Installs the host implementation behind the public App frontend contract.
|
|
324
352
|
* Core calls this once before installed App entries execute.
|
|
@@ -356,9 +384,6 @@ export declare function NxDonutChart(props: NxDonutChartProps): ReactNode;
|
|
|
356
384
|
export declare function NxGauge(props: NxGaugeProps): ReactNode;
|
|
357
385
|
export declare function NxHeatmap(props: NxHeatmapProps): ReactNode;
|
|
358
386
|
export declare function NxResourceScheduler(props: NxResourceSchedulerProps): ReactNode;
|
|
359
|
-
export declare function NxResourceFormLegalEntityField(props: NxResourceFormLegalEntityFieldProps): ReactNode;
|
|
360
|
-
export declare function NxResourceInformationForm<TViewContext, TEditContext>(props: NxResourceInformationFormProps<TViewContext, TEditContext>): ReactNode;
|
|
361
|
-
export declare function NxResourceInformationView<TViewContext, TEditContext>(props: NxResourceInformationViewProps<TViewContext, TEditContext>): ReactNode;
|
|
362
387
|
export declare function NxSankey(props: NxSankeyProps): ReactNode;
|
|
363
388
|
export declare function NxDropdownMenu(props: NxDropdownMenuProps): ReactNode;
|
|
364
389
|
export declare function NxCheckbox(props: NxCheckboxProps): ReactNode;
|
|
@@ -381,6 +406,7 @@ export declare function NxFieldset(props: NxFieldsetProps): ReactNode;
|
|
|
381
406
|
export declare function NxFileDropzone(props: NxFileDropzoneProps): ReactNode;
|
|
382
407
|
export declare function NxFormField(props: NxFormFieldProps): ReactNode;
|
|
383
408
|
export declare function NxFormSection(props: NxFormSectionProps): ReactNode;
|
|
409
|
+
export declare function NxResourceFormLegalEntityField(props: NxResourceFormLegalEntityFieldProps): ReactNode;
|
|
384
410
|
export declare function NxHelpTooltip(props: NxHelpTooltipProps): ReactNode;
|
|
385
411
|
export declare function NxLoadingBlock(props: NxLoadingBlockProps): ReactNode;
|
|
386
412
|
export declare function NxModalDialog(props: NxModalDialogProps): ReactNode;
|
|
@@ -586,6 +612,8 @@ export declare function useRegisterResourceCreateReceiver(registration: Resource
|
|
|
586
612
|
export declare function useResourceCreateCompletion(): ResourceCreateCompletion;
|
|
587
613
|
export declare function useMarkTabDirty(dirty: boolean, snapshot?: string, initialSnapshot?: string): void;
|
|
588
614
|
export declare function useClearTabDirty(): () => void;
|
|
615
|
+
/** Core owns authentication navigation and restores the calling App's host route. */
|
|
616
|
+
export declare function useReauthenticate(): () => Promise<void>;
|
|
589
617
|
export declare function useRegisterTabActions(actions: TabContextActionRegistration[] | null): void;
|
|
590
618
|
export declare function useRegisterDraftAction(options: RegisterDraftActionOptions): void;
|
|
591
619
|
export declare function useWorkTabLabel(label: string | null | undefined): void;
|
package/dist/host.js
CHANGED
|
@@ -1,6 +1,76 @@
|
|
|
1
1
|
import { createElement, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
export { projectSignatureCapabilityCatalog, signatureCapabilityIdentity, } from './signature.js';
|
|
4
|
+
/** Used by the SDK build facade, not by application source. Captures a fixed owner. */
|
|
5
|
+
export function bindNexiaAppRequestServices(appKey) {
|
|
6
|
+
if (!/^[a-z][a-z0-9-]*$/.test(appKey))
|
|
7
|
+
throw new Error('Invalid App identity.');
|
|
8
|
+
const resolve = host().appServices;
|
|
9
|
+
if (!resolve)
|
|
10
|
+
throw new Error('This host does not support App-bound frontend services.');
|
|
11
|
+
const services = resolve(appKey);
|
|
12
|
+
const wrap = (component) => services.wrapComponent?.(component) ?? component;
|
|
13
|
+
const loader = (load) => async () => {
|
|
14
|
+
const module = await load();
|
|
15
|
+
return { ...module, default: wrap(module.default) };
|
|
16
|
+
};
|
|
17
|
+
const inspectors = {
|
|
18
|
+
register(type, load) {
|
|
19
|
+
host().registries.resourceInspectorAdapterRegistry.register(type, async () => {
|
|
20
|
+
const module = await load();
|
|
21
|
+
const Component = wrap(module.default);
|
|
22
|
+
return { default: props => createElement(Component, props) };
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const approvals = {
|
|
27
|
+
register(registration, legacyLoader) {
|
|
28
|
+
host().registries.approvalComposerBusinessFormRegistry.register(typeof registration === 'string'
|
|
29
|
+
? { formWidgetKey: registration, loader: loader(legacyLoader) }
|
|
30
|
+
: { ...registration, loader: loader(registration.loader) });
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
resourceInspectorAdapterRegistry: inspectors,
|
|
35
|
+
autoRegisterPackageResourceInspectors(modules, contracts = {}) {
|
|
36
|
+
registerPackageResourceInspectors(modules, contracts, inspectors);
|
|
37
|
+
},
|
|
38
|
+
autoRegisterPackageSurfaces(options) {
|
|
39
|
+
host().runtime.autoRegisterPackageSurfaces({ ...options, appKey,
|
|
40
|
+
overview: options.overview && loader(options.overview),
|
|
41
|
+
surfaces: Object.fromEntries(Object.entries(options.surfaces).map(([key, load]) => [key, loader(load)])),
|
|
42
|
+
overrides: Object.fromEntries(Object.entries(options.overrides ?? {}).map(([key, value]) => [key,
|
|
43
|
+
typeof value === 'function' ? loader(value) : { ...value, load: loader(value.load) }])), });
|
|
44
|
+
},
|
|
45
|
+
approvalComposerBusinessFormRegistry: approvals,
|
|
46
|
+
processUserTaskFormRegistry: {
|
|
47
|
+
register(registration) {
|
|
48
|
+
host().registries.processUserTaskFormRegistry.register({ ...registration, loader: loader(registration.loader) });
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
dataMigrationRegistry: {
|
|
52
|
+
registerProvider: dataMigrationRegistry.registerProvider,
|
|
53
|
+
registerTarget: dataMigrationRegistry.registerTarget,
|
|
54
|
+
registerStage(registration) {
|
|
55
|
+
host().registries.dataMigrationRegistry.registerStage({ ...registration, ownerAppKey: appKey, loader: loader(registration.loader) });
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
registerAgentComponent(name, component) {
|
|
59
|
+
host().runtime.registerAgentComponent(name, wrap(component));
|
|
60
|
+
},
|
|
61
|
+
registerLazyAgentComponent(name, load) {
|
|
62
|
+
host().runtime.registerLazyAgentComponent(name, loader(load));
|
|
63
|
+
},
|
|
64
|
+
api: services.api,
|
|
65
|
+
openFile: services.openFile,
|
|
66
|
+
async sendUserInvitation(payload) {
|
|
67
|
+
return (await services.api.post('/users/invitations', payload)).data;
|
|
68
|
+
},
|
|
69
|
+
useDataMigrationBackgroundOperation() {
|
|
70
|
+
return useBackgroundOperationClient(services.api);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
4
74
|
let activeHost = null;
|
|
5
75
|
/**
|
|
6
76
|
* Installs the host implementation behind the public App frontend contract.
|
|
@@ -72,6 +142,9 @@ function backgroundOperationClientPath(statusUrl) {
|
|
|
72
142
|
* cancels the wait; callers retaining a checkpoint can explicitly keep waiting.
|
|
73
143
|
*/
|
|
74
144
|
export function useDataMigrationBackgroundOperation() {
|
|
145
|
+
return useBackgroundOperationClient(api);
|
|
146
|
+
}
|
|
147
|
+
function useBackgroundOperationClient(client) {
|
|
75
148
|
const activeControllers = useRef(new Set());
|
|
76
149
|
const backgroundControllers = useRef(new Set());
|
|
77
150
|
useEffect(() => () => {
|
|
@@ -101,7 +174,7 @@ export function useDataMigrationBackgroundOperation() {
|
|
|
101
174
|
backgroundControllers.current.add(controller);
|
|
102
175
|
try {
|
|
103
176
|
for (;;) {
|
|
104
|
-
const operation = (await
|
|
177
|
+
const operation = (await client.get(backgroundOperationClientPath(statusUrl), { signal: controller.signal })).data;
|
|
105
178
|
options.onProgress?.(typeof operation.progress === 'number' ? operation.progress : 0, typeof operation.phase === 'string' ? operation.phase : null);
|
|
106
179
|
if (operation.status === 'completed') {
|
|
107
180
|
if (operation.result === undefined) {
|
|
@@ -123,7 +196,7 @@ export function useDataMigrationBackgroundOperation() {
|
|
|
123
196
|
backgroundControllers.current.delete(controller);
|
|
124
197
|
options.signal?.removeEventListener('abort', abortFromCaller);
|
|
125
198
|
}
|
|
126
|
-
}, []);
|
|
199
|
+
}, [client]);
|
|
127
200
|
return useMemo(() => ({ wait, cancelAll }), [cancelAll, wait]);
|
|
128
201
|
}
|
|
129
202
|
function render(component, props) {
|
|
@@ -196,15 +269,6 @@ export function NxHeatmap(props) {
|
|
|
196
269
|
export function NxResourceScheduler(props) {
|
|
197
270
|
return render(host().components.NxResourceScheduler, props);
|
|
198
271
|
}
|
|
199
|
-
export function NxResourceFormLegalEntityField(props) {
|
|
200
|
-
return render(host().components.NxResourceFormLegalEntityField, props);
|
|
201
|
-
}
|
|
202
|
-
export function NxResourceInformationForm(props) {
|
|
203
|
-
return createElement(host().components.NxResourceInformationForm, props);
|
|
204
|
-
}
|
|
205
|
-
export function NxResourceInformationView(props) {
|
|
206
|
-
return createElement(host().components.NxResourceInformationView, props);
|
|
207
|
-
}
|
|
208
272
|
export function NxSankey(props) {
|
|
209
273
|
return render(host().components.NxSankey, props);
|
|
210
274
|
}
|
|
@@ -271,6 +335,9 @@ export function NxFormField(props) {
|
|
|
271
335
|
export function NxFormSection(props) {
|
|
272
336
|
return render(host().components.NxFormSection, props);
|
|
273
337
|
}
|
|
338
|
+
export function NxResourceFormLegalEntityField(props) {
|
|
339
|
+
return render(host().components.NxResourceFormLegalEntityField, props);
|
|
340
|
+
}
|
|
274
341
|
export function NxHelpTooltip(props) {
|
|
275
342
|
return render(host().components.NxHelpTooltip, props);
|
|
276
343
|
}
|
|
@@ -721,6 +788,10 @@ export function useMarkTabDirty(dirty, snapshot, initialSnapshot) {
|
|
|
721
788
|
export function useClearTabDirty() {
|
|
722
789
|
return host().hooks.useClearTabDirty();
|
|
723
790
|
}
|
|
791
|
+
/** Core owns authentication navigation and restores the calling App's host route. */
|
|
792
|
+
export function useReauthenticate() {
|
|
793
|
+
return host().hooks.useReauthenticate();
|
|
794
|
+
}
|
|
724
795
|
export function useRegisterTabActions(actions) {
|
|
725
796
|
host().hooks.useRegisterTabActions(actions);
|
|
726
797
|
}
|
|
@@ -742,14 +813,24 @@ export function autoRegisterPackageSurfaces(options) {
|
|
|
742
813
|
* lightweight metadata; implementations are loaded only by the registry.
|
|
743
814
|
*/
|
|
744
815
|
export function autoRegisterPackageResourceInspectors(modules, resourceContracts = {}) {
|
|
816
|
+
registerPackageResourceInspectors(modules, resourceContracts, host().registries.resourceInspectorAdapterRegistry);
|
|
817
|
+
}
|
|
818
|
+
function registerPackageResourceInspectors(modules, resourceContracts, registry) {
|
|
745
819
|
const pattern = /^\.\/resources\/[^/]+\/inspector\/register-[^/]+-inspector\.ts$/;
|
|
746
|
-
|
|
747
|
-
|
|
820
|
+
const contractPattern = /^\.\/resources\/[^/]+\/[a-zA-Z0-9-]+-resource-contract\.ts$/;
|
|
821
|
+
const contracts = { ...resourceContracts };
|
|
822
|
+
for (const [path, module] of Object.entries(modules)) {
|
|
823
|
+
if (pattern.test(path))
|
|
824
|
+
continue;
|
|
825
|
+
if (!contractPattern.test(path))
|
|
748
826
|
throw new Error(`Invalid package inspector registration path [${path}].`);
|
|
827
|
+
if (Object.hasOwn(contracts, path))
|
|
828
|
+
throw new Error(`Duplicate Inspector resource contract [${path}].`);
|
|
829
|
+
contracts[path] = module;
|
|
749
830
|
}
|
|
750
831
|
const registrations = new Map();
|
|
751
|
-
for (const [path, module] of Object.entries(
|
|
752
|
-
if (
|
|
832
|
+
for (const [path, module] of Object.entries(contracts)) {
|
|
833
|
+
if (!contractPattern.test(path)
|
|
753
834
|
|| module === null || typeof module !== 'object') {
|
|
754
835
|
throw new Error(`Invalid Inspector resource contract [${path}].`);
|
|
755
836
|
}
|
|
@@ -770,7 +851,7 @@ export function autoRegisterPackageResourceInspectors(modules, resourceContracts
|
|
|
770
851
|
}
|
|
771
852
|
// Validate the complete new declaration set before mutating the registry.
|
|
772
853
|
for (const [type, load] of registrations) {
|
|
773
|
-
|
|
854
|
+
registry.register(type, load);
|
|
774
855
|
}
|
|
775
856
|
}
|
|
776
857
|
export function firstFieldError(errors, field) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { ResourceListFilterableEntry, ResourceListSchema, } from "./resources/resource-list";
|
|
2
2
|
export { draftStringField } from './resources/draft-field';
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
3
|
+
export { resourceFieldValue } from './resources/resource-form';
|
|
4
|
+
export type { AppFormSaveBinding, NxResourceFormLegalEntityFieldProps, ResourceFormBinding, ResourceFormSaved, ResourceFieldValue, ResourceFormLegalEntity, } from "./resources/resource-form";
|
|
5
5
|
export type { DatasetImportConfirmationSummary, DatasetImportPlanChoice, DatasetImportPlanSection, ResourceImportPreview, ResourceImportPreviewRow, ResourceImportResponse, ResourceImportRun, ResourceImportRunStatus, ResourceImportSummary, ResourceTransferFormat, ResourceTransferMessage, ResourceTransferMeta, NxResourceImportDialogProps, NxResourceTransferActionsProps, NxDatasetImportWorkspaceProps, NxInlineResourceCreateProps, NxDatasetExportWorkspaceProps, } from "./resources/resource-transfer";
|
|
6
6
|
export type { NxCalendarActionBinding, NxCalendarActionCommand, NxCalendarActionResult, NxCalendarInteraction, NxCalendarOccurrence, NxCalendarProps, NxCalendarRange, NxCalendarSelection, NxCalendarTemporalRange, NxCalendarView, NxResourceSchedulerActionBinding, NxResourceSchedulerActionCommand, NxResourceSchedulerActionResult, NxResourceSchedulerInteraction, NxResourceSchedulerOccurrence, NxResourceSchedulerProps, NxResourceSchedulerResource, NxResourceSchedulerSelection, NxResourceSchedulerView, ResourceBoardCard, ResourceBoardLabels, ResourceBoardLane, ResourceBoardLoadState, ResourceBoardMoveCommand, ResourceBoardMutationResult, ResourceBoardProjection, ResourceBoardProps, ResourceBoardSummaryField, ResourceProjectionReference, ResourceScheduleActionBinding, ResourceScheduleActionCommand, ResourceScheduleDatePair, ResourceScheduleDateSemantics, ResourceScheduleDependency, ResourceScheduleDependencyType, ResourceScheduleInteraction, ResourceScheduleItem, ResourceScheduleItemType, ResourceScheduleLoadState, ResourceScheduleMutationResult, ResourceScheduleProjection, ResourceScheduleProps, ResourceScheduleTimeUnit, ResourceScheduleView, } from "./resources/resource-projections";
|
|
7
7
|
export type { ContextQueryResult, ContextResponse, LegalEntityContext, PermissionsQueryResult, PermissionsResponse, TenantContext, UserContext, WorkspaceContext, } from "./context";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { draftStringField } from './resources/draft-field.js';
|
|
2
|
-
export {
|
|
2
|
+
export { resourceFieldValue } from './resources/resource-form.js';
|
|
3
3
|
export { createDataMigrationSessionCheckpointStore, dataMigrationUploadAccept, dataMigrationRunPublicId, isDataMigrationOperationAccepted, } from "./data-migration.js";
|
|
4
4
|
export { projectSignatureCapabilityCatalog, signatureCapabilityIdentity, } from "./signature.js";
|
|
5
5
|
export { SIGNATURE_DOCUMENT_DATA_CLASSIFICATIONS, SIGNATURE_DOCUMENT_DATA_FIELD_TYPES, SIGNATURE_DOCUMENT_DATA_FORMATTERS, SIGNATURE_DOCUMENT_DATA_LOOKUP_MODES, SIGNATURE_DOCUMENT_DATA_STATUSES, } from "./signature.js";
|
|
@@ -48,7 +48,11 @@ interface OrganizationTargetSelectorBaseProps {
|
|
|
48
48
|
/** A non-ready scope is a status summary, never an implicit "all" selector. */
|
|
49
49
|
status?: 'loading' | 'invalid' | 'unavailable';
|
|
50
50
|
}
|
|
51
|
-
/** Host-localized
|
|
51
|
+
/** Host-localized page-scope controls. A valid axis with only one choice is hidden.
|
|
52
|
+
* Loading, invalid and unavailable states remain visible. A sole Operating Unit
|
|
53
|
+
* does not require a selector, including an unfiltered read across its Legal Entity.
|
|
54
|
+
* Visibility never changes query values or record ownership.
|
|
55
|
+
*/
|
|
52
56
|
export type NxOrganizationTargetSelectorProps = (OrganizationTargetSelectorBaseProps & {
|
|
53
57
|
mode: 'legal-entity-list';
|
|
54
58
|
/** Opt in only when the endpoint supports company-wide and legal-entity records.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { OrganizationTargetSelectorOption } from '../organization-target';
|
|
3
|
+
/** Authorized organization owner supplied by the RecordSurface, never inferred from route scope. */
|
|
4
|
+
export type ResourceFormLegalEntity = {
|
|
5
|
+
kind: 'select';
|
|
6
|
+
value: string | null;
|
|
7
|
+
options: readonly OrganizationTargetSelectorOption[];
|
|
8
|
+
onChange: (value: string) => void;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
error?: ReactNode;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'stored';
|
|
13
|
+
/** Human label from the record or a read-authorized lookup of its owner. */
|
|
14
|
+
label: ReactNode;
|
|
15
|
+
};
|
|
16
|
+
/** Props for the host-owned organization owner field within a composed Record form. */
|
|
17
|
+
export interface NxResourceFormLegalEntityFieldProps {
|
|
18
|
+
target: ResourceFormLegalEntity;
|
|
19
|
+
mode: 'create' | 'edit';
|
|
20
|
+
}
|
|
21
|
+
/** A displayed Resource field value whose emptiness is explicit to its owning surface. */
|
|
22
|
+
export interface ResourceFieldValue {
|
|
23
|
+
value: ReactNode;
|
|
24
|
+
empty?: boolean;
|
|
25
|
+
mono?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Keeps an empty string distinct from a displayed Resource field value. */
|
|
28
|
+
export declare function resourceFieldValue(value: ReactNode, options?: Omit<ResourceFieldValue, 'value'>): ResourceFieldValue;
|
|
29
|
+
export interface ResourceFormSaved {
|
|
30
|
+
action: "create" | "update";
|
|
31
|
+
/** Unmodified business response; decode it using the owning App contract. */
|
|
32
|
+
response: Readonly<Record<string, unknown>>;
|
|
33
|
+
submittedValues: Readonly<Record<string, unknown>>;
|
|
34
|
+
currentValues: Readonly<Record<string, unknown>>;
|
|
35
|
+
}
|
|
36
|
+
/** Explicit App action associated with a page form; grants no execution authority. */
|
|
37
|
+
export interface AppFormSaveBinding {
|
|
38
|
+
key: string;
|
|
39
|
+
/** Fixed record/scope arguments. Form fields must not overwrite these keys. */
|
|
40
|
+
arguments: Readonly<Record<string, unknown>>;
|
|
41
|
+
/** Decode the App response, preserve newer input, and refresh human-owned queries. */
|
|
42
|
+
onSaved: (result: Omit<ResourceFormSaved, "action">) => void | Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Explicit binding for a composed Resource form. Resource fields and controls
|
|
46
|
+
* remain App-owned; the host only uses this identity for draft/save actions.
|
|
47
|
+
*/
|
|
48
|
+
export interface ResourceFormBinding {
|
|
49
|
+
/** Local identity for a form without a Resource. Requires explicit scopeKey; do not combine with resourceKey/resourceId/onSaved. */
|
|
50
|
+
formKey?: string;
|
|
51
|
+
/** Only for a formKey-based page; pairs an explicit server action with this form. */
|
|
52
|
+
saveAction?: AppFormSaveBinding;
|
|
53
|
+
/** Omit identity inside a declared Resource route; the host supplies it. */
|
|
54
|
+
resourceKey?: string;
|
|
55
|
+
resourceId?: string | null;
|
|
56
|
+
/** Additional form-owned scope; otherwise use the pane-local route scope. */
|
|
57
|
+
scopeKey?: string;
|
|
58
|
+
effect: "draft" | "autosave";
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
/** Host-confirmed external save for this mounted form; never performs a write. */
|
|
61
|
+
onSaved?: (result: ResourceFormSaved) => void | Promise<void>;
|
|
62
|
+
/** Pure cross-field preflight; return rejected keys before any value writer runs. */
|
|
63
|
+
validateBatch?: (values: Readonly<Record<string, unknown>>) => readonly string[];
|
|
64
|
+
}
|
package/dist/shell.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { QueryClient, UseQueryResult } from "@tanstack/react-query";
|
|
|
3
3
|
import type { PermissionsResponse } from "./context";
|
|
4
4
|
import type { ResourcePickerRevalidation, ResourceReferenceIdentity } from "./resource-reference";
|
|
5
5
|
import type { ResourceListSchema } from "./resources/resource-list";
|
|
6
|
-
import type { AppFormSaveBinding, ResourceFormBinding, ResourceFormSaved } from "./resources/resource-
|
|
6
|
+
import type { AppFormSaveBinding, ResourceFormBinding, ResourceFormSaved } from "./resources/resource-form";
|
|
7
7
|
import type { ResourceTransferMeta } from "./resources/resource-transfer";
|
|
8
8
|
/** A server-authorized, durable favorite identity. */
|
|
9
9
|
export type FavoriteTarget = {
|
|
@@ -793,6 +793,8 @@ export interface NxFormFieldProps {
|
|
|
793
793
|
export interface NxFormSectionProps {
|
|
794
794
|
/** Explicit unsaved semantics for composed forms; uses published route identity. */
|
|
795
795
|
binding?: ResourceFormBinding;
|
|
796
|
+
/** Restricts route-derived draft identity to the owning RecordSurface mode. */
|
|
797
|
+
mode?: "create" | "edit";
|
|
796
798
|
id?: string;
|
|
797
799
|
children: ReactNode;
|
|
798
800
|
onSubmit?: (event: FormEvent<HTMLFormElement>) => void;
|
package/dist/vite.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const nexiaHostPeers: readonly string[];
|
|
2
|
+
export function nexiaAppConfig(configUrl: string | URL): Record<string, unknown>;
|
|
3
|
+
export function nexiaAppFrontend(apps: { appKey: string; root: string } | Array<{ appKey: string; root: string }>): {
|
|
4
|
+
name: string;
|
|
5
|
+
enforce: 'pre';
|
|
6
|
+
resolveId(source: string, importer?: string): string | undefined;
|
|
7
|
+
load(id: string): string | undefined;
|
|
8
|
+
generateBundle(this: { emitFile(file: { type: 'asset'; fileName: string; source: string }): unknown }, options: unknown, bundle: Record<string, unknown>): void;
|
|
9
|
+
};
|
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
// Only these modules are supplied by Core's import map. Other App dependencies
|
|
6
|
+
// (for example icons or Axios error helpers) stay in the App bundle.
|
|
7
|
+
export const nexiaHostPeers = ['react', 'react/jsx-runtime', 'react/jsx-dev-runtime',
|
|
8
|
+
'@tanstack/react-query', 'react-router-dom', 'react-i18next', '@nexia/sdk', '@nexia/sdk/host'];
|
|
9
|
+
|
|
10
|
+
/** The same standalone build contract for generated and existing Apps. */
|
|
11
|
+
export function nexiaAppConfig(configUrl) {
|
|
12
|
+
const root = fileURLToPath(new URL('.', configUrl));
|
|
13
|
+
const manifest = JSON.parse(readFileSync(new URL('./nexia.json', configUrl), 'utf8'));
|
|
14
|
+
return {
|
|
15
|
+
root, plugins: [nexiaAppFrontend({ appKey: manifest.app.app_key, root })],
|
|
16
|
+
publicDir: false, envDir: false, esbuild: { jsx: 'automatic' },
|
|
17
|
+
resolve: { alias: { '#app': path.join(root, 'resources/js'), '#lang': path.join(root, 'resources/lang') } },
|
|
18
|
+
build: {
|
|
19
|
+
outDir: 'dist/frontend', emptyOutDir: true, sourcemap: false, manifest: true,
|
|
20
|
+
lib: { entry: path.join(root, 'resources/js/index.ts'), formats: ['es'], fileName: () => 'index.js' },
|
|
21
|
+
rollupOptions: {
|
|
22
|
+
external: (id, importer) => nexiaHostPeers.includes(id)
|
|
23
|
+
&& (!['@nexia/sdk', '@nexia/sdk/host'].includes(id) || importer?.startsWith('\0nexia-app-services:')),
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Bind App service imports at build time; App source keeps using the ordinary SDK. */
|
|
30
|
+
export function nexiaAppFrontend(apps) {
|
|
31
|
+
const owners = (Array.isArray(apps) ? apps : [apps]).map(({ appKey, root }) => {
|
|
32
|
+
if (!/^[a-z][a-z0-9-]*$/.test(appKey)) throw new Error('Invalid App frontend owner.');
|
|
33
|
+
return { appKey, root: path.resolve(root).replaceAll('\\', '/') + '/' };
|
|
34
|
+
});
|
|
35
|
+
const prefix = '\0nexia-app-services:';
|
|
36
|
+
return {
|
|
37
|
+
name: 'nexia:app-services',
|
|
38
|
+
enforce: 'pre',
|
|
39
|
+
resolveId(source, importer) {
|
|
40
|
+
if (!['@nexia/sdk', '@nexia/sdk/host'].includes(source) || !importer || importer.startsWith(prefix)) return;
|
|
41
|
+
const owner = owners.find(app => importer.replaceAll('\\', '/').startsWith(app.root));
|
|
42
|
+
if (owner) return prefix + owner.appKey + ':' + source;
|
|
43
|
+
},
|
|
44
|
+
load(id) {
|
|
45
|
+
if (!id.startsWith(prefix)) return;
|
|
46
|
+
const [appKey, source] = id.slice(prefix.length).split(':');
|
|
47
|
+
return `export * from ${JSON.stringify(source)};
|
|
48
|
+
import { bindNexiaAppRequestServices } from '@nexia/sdk/host';
|
|
49
|
+
const services = bindNexiaAppRequestServices(${JSON.stringify(appKey)});
|
|
50
|
+
export const { api, openFile, sendUserInvitation, useDataMigrationBackgroundOperation,
|
|
51
|
+
autoRegisterPackageSurfaces, autoRegisterPackageResourceInspectors,
|
|
52
|
+
resourceInspectorAdapterRegistry, approvalComposerBusinessFormRegistry,
|
|
53
|
+
processUserTaskFormRegistry, dataMigrationRegistry,
|
|
54
|
+
registerAgentComponent, registerLazyAgentComponent } = services;`;
|
|
55
|
+
},
|
|
56
|
+
generateBundle(_options, bundle) {
|
|
57
|
+
// Standalone App builds expose compatibility before executing their entry.
|
|
58
|
+
if (owners.length === 1) this.emitFile({
|
|
59
|
+
type: 'asset', fileName: 'nexia-host.json',
|
|
60
|
+
source: JSON.stringify({ version: 1, app_key: owners[0].appKey,
|
|
61
|
+
styles: Object.keys(bundle).filter(file => file.endsWith('.css')) }),
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexia/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Frontend contracts for Nexia App Packages",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"main": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"exports": {
|
|
14
|
+
"./vite": "./dist/vite.mjs",
|
|
14
15
|
".": {
|
|
15
16
|
"development": "./dist/index.js",
|
|
16
17
|
"types": "./dist/index.d.ts",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"scripts": {
|
|
32
33
|
"build": "node scripts/build.mjs",
|
|
33
34
|
"prepack": "npm run build",
|
|
34
|
-
"test": "npm run build && node tests/WireValuesTest.mjs && node tests/ResourceCompositionFrontendContractsTest.mjs && node scripts/organization-target-contract.mjs && node tests/ResourceInspectorRegistrationTest.mjs && node tests/SettingsPrimitivesTest.mjs",
|
|
35
|
+
"test": "npm run build && node tests/WireValuesTest.mjs && node tests/ResourceCompositionFrontendContractsTest.mjs && node scripts/organization-target-contract.mjs && node tests/ResourceInspectorRegistrationTest.mjs && node tests/SettingsPrimitivesTest.mjs && node tests/AppServicesTest.mjs",
|
|
35
36
|
"test:wire-values": "node tests/WireValuesTest.mjs",
|
|
36
37
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
38
|
"test:resource-composition": "pnpm run build && node tests/ResourceCompositionFrontendContractsTest.mjs",
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import type { OrganizationTargetSelectorOption } from "../organization-target";
|
|
3
|
-
/** Surface-owned, authorized form target. Never a page/list scope. */
|
|
4
|
-
export type ResourceFormLegalEntity = {
|
|
5
|
-
kind: "select";
|
|
6
|
-
value: string | null;
|
|
7
|
-
options: readonly OrganizationTargetSelectorOption[];
|
|
8
|
-
onChange: (value: string) => void;
|
|
9
|
-
disabled?: boolean;
|
|
10
|
-
error?: ReactNode;
|
|
11
|
-
} | {
|
|
12
|
-
kind: "stored";
|
|
13
|
-
/** Human label from the record or a read-authorized lookup of its owner. */
|
|
14
|
-
label: ReactNode;
|
|
15
|
-
};
|
|
16
|
-
/** Why a field matters to the Resource lifecycle. */
|
|
17
|
-
export type ResourceInformationRequirement = "save" | "readiness" | "optional";
|
|
18
|
-
/** The projections in which a field occupies its canonical position. */
|
|
19
|
-
export type ResourceInformationMode = "view" | "create" | "edit";
|
|
20
|
-
/** Responsive width hint for the Form projection. View always uses detail rows. */
|
|
21
|
-
export type ResourceInformationFieldSpan = "half" | "full";
|
|
22
|
-
export interface ResourceInformationValue {
|
|
23
|
-
value: ReactNode;
|
|
24
|
-
empty?: boolean;
|
|
25
|
-
mono?: boolean;
|
|
26
|
-
}
|
|
27
|
-
export interface ResourceInformationControlSlot {
|
|
28
|
-
id: string;
|
|
29
|
-
describedBy?: string;
|
|
30
|
-
invalid: boolean;
|
|
31
|
-
}
|
|
32
|
-
export interface ResourceInformationEditRenderContext<TContext> {
|
|
33
|
-
mode: "create" | "edit";
|
|
34
|
-
context: TContext;
|
|
35
|
-
}
|
|
36
|
-
export interface ResourceInformationControlProjection<TContext> {
|
|
37
|
-
kind: "control";
|
|
38
|
-
render: (context: ResourceInformationEditRenderContext<TContext>, slot: ResourceInformationControlSlot) => ReactNode;
|
|
39
|
-
error?: (context: ResourceInformationEditRenderContext<TContext>) => ReactNode;
|
|
40
|
-
}
|
|
41
|
-
export interface ResourceInformationReadOnlyProjection<TContext> {
|
|
42
|
-
kind: "read-only";
|
|
43
|
-
render: (context: ResourceInformationEditRenderContext<TContext>) => ResourceInformationValue;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Escape hatch for a composite field such as an address editor. The field
|
|
47
|
-
* still has one canonical schema position and one View value, while the App
|
|
48
|
-
* owns the compound Edit control.
|
|
49
|
-
*/
|
|
50
|
-
export interface ResourceInformationCustomProjection<TContext> {
|
|
51
|
-
kind: "custom";
|
|
52
|
-
render: (context: ResourceInformationEditRenderContext<TContext>) => ReactNode;
|
|
53
|
-
}
|
|
54
|
-
export type ResourceInformationEditProjection<TContext> = ResourceInformationControlProjection<TContext> | ResourceInformationReadOnlyProjection<TContext> | ResourceInformationCustomProjection<TContext>;
|
|
55
|
-
export interface ResourceInformationField<TViewContext, TEditContext> {
|
|
56
|
-
key: string;
|
|
57
|
-
labelKey: string;
|
|
58
|
-
/** Persistent entry guidance rendered below an Edit control. */
|
|
59
|
-
helpKey?: string;
|
|
60
|
-
/** Short domain definition rendered from the field label. */
|
|
61
|
-
definitionKey?: string;
|
|
62
|
-
requirement?: ResourceInformationRequirement;
|
|
63
|
-
/** Personal/secret values are excluded from automated form discovery and writes. */
|
|
64
|
-
sensitive?: boolean;
|
|
65
|
-
span?: ResourceInformationFieldSpan;
|
|
66
|
-
/** Defaults to all projections. Omissions must be deliberate and explicit. */
|
|
67
|
-
modes?: readonly ResourceInformationMode[];
|
|
68
|
-
/** Context-dependent visibility evaluated after the static mode contract. */
|
|
69
|
-
visibility?: {
|
|
70
|
-
view?: (context: TViewContext) => boolean;
|
|
71
|
-
create?: (context: TEditContext) => boolean;
|
|
72
|
-
edit?: (context: TEditContext) => boolean;
|
|
73
|
-
};
|
|
74
|
-
view: (context: TViewContext) => ResourceInformationValue;
|
|
75
|
-
edit: ResourceInformationEditProjection<TEditContext>;
|
|
76
|
-
}
|
|
77
|
-
export interface ResourceInformationSection<TViewContext, TEditContext> {
|
|
78
|
-
key: string;
|
|
79
|
-
titleKey: string;
|
|
80
|
-
descriptionKey?: string;
|
|
81
|
-
/** Form layout only. View remains an ordered, compact definition list. */
|
|
82
|
-
formColumns?: 1 | 2;
|
|
83
|
-
/** Optional aggregate or projection owner, for example `resource` or `party`. */
|
|
84
|
-
source?: string;
|
|
85
|
-
fields: readonly ResourceInformationField<TViewContext, TEditContext>[];
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* One ordered Resource information contract projected by both View and Edit.
|
|
89
|
-
* Route loading, mutations, and related-resource actions remain Surface-owned.
|
|
90
|
-
*/
|
|
91
|
-
export interface ResourceInformationSchema<TViewContext, TEditContext> {
|
|
92
|
-
sections: readonly ResourceInformationSection<TViewContext, TEditContext>[];
|
|
93
|
-
}
|
|
94
|
-
export interface ResourceInformationTranslator {
|
|
95
|
-
(key: string): string;
|
|
96
|
-
}
|
|
97
|
-
export interface NxResourceInformationViewProps<TViewContext, TEditContext = never> {
|
|
98
|
-
schema: ResourceInformationSchema<TViewContext, TEditContext>;
|
|
99
|
-
context: TViewContext;
|
|
100
|
-
translate: ResourceInformationTranslator;
|
|
101
|
-
emptyValue: ReactNode;
|
|
102
|
-
visibleEmptyRequirements?: readonly ResourceInformationRequirement[];
|
|
103
|
-
testIdPrefix?: string;
|
|
104
|
-
}
|
|
105
|
-
/** Place inside the first input section of a custom form. */
|
|
106
|
-
export interface NxResourceFormLegalEntityFieldProps {
|
|
107
|
-
target: ResourceFormLegalEntity;
|
|
108
|
-
mode: "create" | "edit";
|
|
109
|
-
}
|
|
110
|
-
export interface NxResourceInformationFormProps<TViewContext, TEditContext> {
|
|
111
|
-
schema: ResourceInformationSchema<TViewContext, TEditContext>;
|
|
112
|
-
context: TEditContext;
|
|
113
|
-
mode: "create" | "edit";
|
|
114
|
-
/** Explicit owner and effect of this form; control writers remain public callbacks. */
|
|
115
|
-
binding?: ResourceFormBinding;
|
|
116
|
-
/** First field of the first schema section, full row width. Omit for tenant-owned forms.
|
|
117
|
-
* Use `stored` on edit; the host never renders an editable owner in edit mode.
|
|
118
|
-
* Do not also declare the Legal Entity field in the form schema.
|
|
119
|
-
*/
|
|
120
|
-
legalEntity?: ResourceFormLegalEntity;
|
|
121
|
-
translate: ResourceInformationTranslator;
|
|
122
|
-
emptyValue: ReactNode;
|
|
123
|
-
testIdPrefix?: string;
|
|
124
|
-
}
|
|
125
|
-
export interface ResourceFormSaved {
|
|
126
|
-
action: "create" | "update";
|
|
127
|
-
/** Unmodified business response; decode it using the owning App contract. */
|
|
128
|
-
response: Readonly<Record<string, unknown>>;
|
|
129
|
-
submittedValues: Readonly<Record<string, unknown>>;
|
|
130
|
-
currentValues: Readonly<Record<string, unknown>>;
|
|
131
|
-
}
|
|
132
|
-
/** Explicit App action associated with a page form; grants no execution authority. */
|
|
133
|
-
export interface AppFormSaveBinding {
|
|
134
|
-
key: string;
|
|
135
|
-
/** Fixed record/scope arguments. Form fields must not overwrite these keys. */
|
|
136
|
-
arguments: Readonly<Record<string, unknown>>;
|
|
137
|
-
/** Decode the App response, preserve newer input, and refresh human-owned queries. */
|
|
138
|
-
onSaved: (result: Omit<ResourceFormSaved, "action">) => void | Promise<void>;
|
|
139
|
-
}
|
|
140
|
-
export interface ResourceFormBinding {
|
|
141
|
-
/** Local identity for a form without a Resource. Requires explicit scopeKey; do not combine with resourceKey/resourceId/onSaved. */
|
|
142
|
-
formKey?: string;
|
|
143
|
-
/** Only for a formKey-based page; pairs an explicit server action with this form. */
|
|
144
|
-
saveAction?: AppFormSaveBinding;
|
|
145
|
-
/** Omit identity inside a declared Resource route; the host supplies it. */
|
|
146
|
-
resourceKey?: string;
|
|
147
|
-
resourceId?: string | null;
|
|
148
|
-
/** Additional form-owned scope; otherwise use the pane-local route scope. */
|
|
149
|
-
scopeKey?: string;
|
|
150
|
-
effect: "draft" | "autosave";
|
|
151
|
-
disabled?: boolean;
|
|
152
|
-
/** Host-confirmed external save for this mounted form; never performs a write. */
|
|
153
|
-
onSaved?: (result: ResourceFormSaved) => void | Promise<void>;
|
|
154
|
-
/** Pure cross-field preflight; return rejected keys before any value writer runs. */
|
|
155
|
-
validateBatch?: (values: Readonly<Record<string, unknown>>) => readonly string[];
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Checks a schema once, then deliberately widens it to the stable host
|
|
159
|
-
* contract. Keeping every App field as one deep literal union makes a
|
|
160
|
-
* workspace-wide typecheck retain the complete product catalog in memory.
|
|
161
|
-
*/
|
|
162
|
-
export declare function defineResourceInformationSchema<TViewContext, TEditContext>(): (schema: ResourceInformationSchema<TViewContext, TEditContext>) => ResourceInformationSchema<TViewContext, TEditContext>;
|
|
163
|
-
/** Explicit value helper so an empty string is never mistaken for a value. */
|
|
164
|
-
export declare function resourceInformationValue(value: ReactNode, options?: Omit<ResourceInformationValue, "value">): ResourceInformationValue;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks a schema once, then deliberately widens it to the stable host
|
|
3
|
-
* contract. Keeping every App field as one deep literal union makes a
|
|
4
|
-
* workspace-wide typecheck retain the complete product catalog in memory.
|
|
5
|
-
*/
|
|
6
|
-
export function defineResourceInformationSchema() {
|
|
7
|
-
return (schema) => schema;
|
|
8
|
-
}
|
|
9
|
-
/** Explicit value helper so an empty string is never mistaken for a value. */
|
|
10
|
-
export function resourceInformationValue(value, options = {}) {
|
|
11
|
-
return { value, ...options };
|
|
12
|
-
}
|