@nexia/sdk 0.5.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.
Files changed (49) hide show
  1. package/dist/app-availability.d.ts +18 -0
  2. package/dist/app-availability.js +29 -0
  3. package/dist/approval.d.ts +180 -0
  4. package/dist/approval.js +9 -0
  5. package/dist/context.d.ts +49 -0
  6. package/dist/context.js +1 -0
  7. package/dist/data-migration.d.ts +123 -0
  8. package/dist/data-migration.js +70 -0
  9. package/dist/fixtures/approval-contract-negative.d.ts +1 -0
  10. package/dist/fixtures/approval-contract-negative.js +8 -0
  11. package/dist/handoff-result.d.ts +6 -0
  12. package/dist/handoff-result.js +17 -0
  13. package/dist/host.d.ts +602 -0
  14. package/dist/host.js +803 -0
  15. package/dist/index.d.ts +42 -0
  16. package/dist/index.js +21 -0
  17. package/dist/number.d.ts +2 -0
  18. package/dist/number.js +9 -0
  19. package/dist/organization-target.d.ts +101 -0
  20. package/dist/organization-target.js +105 -0
  21. package/dist/permissions.d.ts +3 -0
  22. package/dist/permissions.js +12 -0
  23. package/dist/platform.d.ts +378 -0
  24. package/dist/platform.js +114 -0
  25. package/dist/process.d.ts +98 -0
  26. package/dist/process.js +10 -0
  27. package/dist/resource-composition.d.ts +104 -0
  28. package/dist/resource-composition.js +576 -0
  29. package/dist/resource-create-destination.d.ts +17 -0
  30. package/dist/resource-create-destination.js +1 -0
  31. package/dist/resource-reference.d.ts +122 -0
  32. package/dist/resource-reference.js +203 -0
  33. package/dist/resources/resource-information.d.ts +128 -0
  34. package/dist/resources/resource-information.js +12 -0
  35. package/dist/resources/resource-list.d.ts +23 -0
  36. package/dist/resources/resource-list.js +1 -0
  37. package/dist/resources/resource-projections.d.ts +311 -0
  38. package/dist/resources/resource-projections.js +1 -0
  39. package/dist/resources/resource-transfer.d.ts +208 -0
  40. package/dist/resources/resource-transfer.js +1 -0
  41. package/dist/shell.d.ts +1297 -0
  42. package/dist/shell.js +1 -0
  43. package/dist/signature.d.ts +489 -0
  44. package/dist/signature.js +171 -0
  45. package/dist/spreadsheet.d.ts +42 -0
  46. package/dist/spreadsheet.js +15 -0
  47. package/dist/testing.d.ts +16 -0
  48. package/dist/testing.js +17 -0
  49. package/package.json +53 -0
package/dist/host.js ADDED
@@ -0,0 +1,803 @@
1
+ import { createElement, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
2
+ import axios from 'axios';
3
+ export { projectSignatureCapabilityCatalog, signatureCapabilityIdentity, } from './signature.js';
4
+ let activeHost = null;
5
+ /**
6
+ * Installs the host implementation behind the public App frontend contract.
7
+ * Core calls this once before installed App entries execute.
8
+ */
9
+ export function configureNexiaAppFrontendHost(bindings) {
10
+ activeHost = bindings;
11
+ }
12
+ function host() {
13
+ if (activeHost === null) {
14
+ throw new Error('Nexia App frontend host is not configured. Core must configure the SDK before loading App entries.');
15
+ }
16
+ return activeHost;
17
+ }
18
+ const apiProxyTarget = axios.create();
19
+ /** Axios-compatible host client carrying the active shell CSRF configuration. */
20
+ export const api = new Proxy(apiProxyTarget, {
21
+ get(_target, property) {
22
+ const client = host().api;
23
+ const value = Reflect.get(client, property, client);
24
+ return typeof value === 'function' ? value.bind(client) : value;
25
+ },
26
+ });
27
+ function operationFailureMessage(operation) {
28
+ const validationMessage = operation.validation_errors
29
+ ? Object.values(operation.validation_errors)
30
+ .flat()
31
+ .find((value) => typeof value === 'string' && value.trim() !== '')
32
+ : undefined;
33
+ // `errors` contains stable translation keys for Core-owned displays. The
34
+ // SDK cannot translate those on an App's behalf, so only surface the
35
+ // server-localized validation detail here; an empty message lets the
36
+ // owning stage use its domain-specific fallback instead of exposing a key.
37
+ return validationMessage ?? '';
38
+ }
39
+ function waitForOperationPoll(signal) {
40
+ if (signal.aborted) {
41
+ return Promise.reject(signal.reason ?? new DOMException('Aborted', 'AbortError'));
42
+ }
43
+ const delay = typeof document !== 'undefined'
44
+ && document.visibilityState === 'hidden'
45
+ ? 3000
46
+ : 1200;
47
+ return new Promise((resolve, reject) => {
48
+ const aborted = () => {
49
+ globalThis.clearTimeout(timer);
50
+ reject(signal.reason ?? new DOMException('Aborted', 'AbortError'));
51
+ };
52
+ const timer = globalThis.setTimeout(() => {
53
+ signal.removeEventListener('abort', aborted);
54
+ resolve();
55
+ }, delay);
56
+ signal.addEventListener('abort', aborted, { once: true });
57
+ });
58
+ }
59
+ function backgroundOperationClientPath(statusUrl) {
60
+ const path = statusUrl.startsWith('/api/') ? statusUrl.slice(4) : statusUrl;
61
+ if (!path.startsWith('/') || path.startsWith('//')) {
62
+ throw new Error('Data migration operation status URL must be root-relative.');
63
+ }
64
+ return path;
65
+ }
66
+ /**
67
+ * Polls Core's standard background-operation endpoint and cancels outstanding
68
+ * waits when the owning surface unmounts.
69
+ */
70
+ export function useDataMigrationBackgroundOperation() {
71
+ const activeControllers = useRef(new Set());
72
+ useEffect(() => () => {
73
+ for (const controller of activeControllers.current)
74
+ controller.abort();
75
+ activeControllers.current.clear();
76
+ }, []);
77
+ const cancelAll = useCallback(() => {
78
+ for (const controller of activeControllers.current)
79
+ controller.abort();
80
+ activeControllers.current.clear();
81
+ }, []);
82
+ const wait = useCallback(async (accepted, options = {}) => {
83
+ const ticket = typeof accepted === 'string' ? accepted : accepted.ticket;
84
+ const statusUrl = options.statusUrl
85
+ ?? (typeof accepted === 'string' ? undefined : accepted.status_url)
86
+ ?? `/resource-import/tickets/${encodeURIComponent(ticket)}`;
87
+ const controller = new AbortController();
88
+ const abortFromCaller = () => controller.abort(options.signal?.reason);
89
+ if (options.signal?.aborted)
90
+ abortFromCaller();
91
+ else
92
+ options.signal?.addEventListener('abort', abortFromCaller, { once: true });
93
+ activeControllers.current.add(controller);
94
+ try {
95
+ for (;;) {
96
+ const operation = (await api.get(backgroundOperationClientPath(statusUrl), { signal: controller.signal })).data;
97
+ options.onProgress?.(typeof operation.progress === 'number' ? operation.progress : 0, typeof operation.phase === 'string' ? operation.phase : null);
98
+ if (operation.status === 'completed') {
99
+ if (operation.result === undefined) {
100
+ throw new Error('Completed data migration operation has no result.');
101
+ }
102
+ return operation.result;
103
+ }
104
+ if (operation.status === 'failed' || operation.status === 'unknown') {
105
+ throw new Error(operationFailureMessage(operation));
106
+ }
107
+ await waitForOperationPoll(controller.signal);
108
+ }
109
+ }
110
+ finally {
111
+ activeControllers.current.delete(controller);
112
+ options.signal?.removeEventListener('abort', abortFromCaller);
113
+ }
114
+ }, []);
115
+ return useMemo(() => ({ wait, cancelAll }), [cancelAll, wait]);
116
+ }
117
+ function render(component, props) {
118
+ return createElement(component, props);
119
+ }
120
+ export function AppRouteFrame(props) {
121
+ return render(host().components.AppRouteFrame, props);
122
+ }
123
+ export function InspectorAction(props) {
124
+ return render(host().components.InspectorAction, props);
125
+ }
126
+ export function InspectorResourceActions(props) {
127
+ return render(host().components.InspectorResourceActions, props);
128
+ }
129
+ export function ResourceLink(props) {
130
+ return render(host().components.ResourceLink, props);
131
+ }
132
+ export function NxAdaptiveSplit(props) {
133
+ return render(host().components.NxAdaptiveSplit, props);
134
+ }
135
+ export function NxActionButton(props) {
136
+ return render(host().components.NxActionButton, props);
137
+ }
138
+ export function NxAlert(props) {
139
+ return render(host().components.NxAlert, props);
140
+ }
141
+ export function NxButton(props) {
142
+ return render(host().components.NxButton, props);
143
+ }
144
+ export function NxLinkButton(props) {
145
+ return render(host().components.NxLinkButton, props);
146
+ }
147
+ export function NxIconButton(props) {
148
+ return render(host().components.NxIconButton, props);
149
+ }
150
+ export function NxIconLink(props) {
151
+ return render(host().components.NxIconLink, props);
152
+ }
153
+ /** Host-rendered action; Apps supply only a stable target. */
154
+ export function FavoriteButton(props) {
155
+ return render(host().components.FavoriteButton, props);
156
+ }
157
+ export function NxCalendar(props) {
158
+ return render(host().components.NxCalendar, props);
159
+ }
160
+ export function NxBarChart(props) {
161
+ return render(host().components.NxBarChart, props);
162
+ }
163
+ export function NxLineChart(props) {
164
+ return render(host().components.NxLineChart, props);
165
+ }
166
+ export function NxInsightFilterBar(props) {
167
+ return render(host().components.NxInsightFilterBar, props);
168
+ }
169
+ export function NxInsightSurface(props) {
170
+ return render(host().components.NxInsightSurface, props);
171
+ }
172
+ export function NxOverviewBand(props) {
173
+ return render(host().components.NxOverviewBand, props);
174
+ }
175
+ export function NxDonutChart(props) {
176
+ return render(host().components.NxDonutChart, props);
177
+ }
178
+ export function NxGauge(props) {
179
+ return render(host().components.NxGauge, props);
180
+ }
181
+ export function NxHeatmap(props) {
182
+ return render(host().components.NxHeatmap, props);
183
+ }
184
+ export function NxResourceScheduler(props) {
185
+ return render(host().components.NxResourceScheduler, props);
186
+ }
187
+ export function NxResourceFormLegalEntityField(props) {
188
+ return render(host().components.NxResourceFormLegalEntityField, props);
189
+ }
190
+ export function NxResourceInformationForm(props) {
191
+ return createElement(host().components.NxResourceInformationForm, props);
192
+ }
193
+ export function NxResourceInformationView(props) {
194
+ return createElement(host().components.NxResourceInformationView, props);
195
+ }
196
+ export function NxSankey(props) {
197
+ return render(host().components.NxSankey, props);
198
+ }
199
+ export function NxDropdownMenu(props) {
200
+ return render(host().components.NxDropdownMenu, props);
201
+ }
202
+ export function NxCheckbox(props) {
203
+ return render(host().components.NxCheckbox, props);
204
+ }
205
+ export function NxRadio(props) {
206
+ return render(host().components.NxRadio, props);
207
+ }
208
+ export function NxRadioGroup(props) {
209
+ return render(host().components.NxRadioGroup, props);
210
+ }
211
+ export function NxRefreshControl(props) {
212
+ return render(host().components.NxRefreshControl, props);
213
+ }
214
+ export function NxColumnBrowser(props) {
215
+ return render(host().components.NxColumnBrowser, props);
216
+ }
217
+ export function NxColumnPicker(props) {
218
+ return render(host().components.NxColumnPicker, props);
219
+ }
220
+ export function NxCombobox(props) {
221
+ return createElement((host().components.NxCombobox), props);
222
+ }
223
+ export function NxOperatingUnitSelector(props) {
224
+ return render(host().components.NxOperatingUnitSelector, props);
225
+ }
226
+ export function NxOrganizationTargetSelector(props) {
227
+ return render(host().components.NxOrganizationTargetSelector, props);
228
+ }
229
+ export function NxDatePicker(props) {
230
+ return render(host().components.NxDatePicker, props);
231
+ }
232
+ export function NxDateRangePicker(props) {
233
+ return render(host().components.NxDateRangePicker, props);
234
+ }
235
+ export function NxDetailRow(props) {
236
+ return render(host().components.NxDetailRow, props);
237
+ }
238
+ export function NxEmptyView(props) {
239
+ return render(host().components.NxEmptyView, props);
240
+ }
241
+ export function NxFieldGroup(props) {
242
+ return render(host().components.NxFieldGroup, props);
243
+ }
244
+ export function NxFieldLegend(props) {
245
+ return render(host().components.NxFieldLegend, props);
246
+ }
247
+ export function NxFieldset(props) {
248
+ return render(host().components.NxFieldset, props);
249
+ }
250
+ export function NxFileDropzone(props) {
251
+ return render(host().components.NxFileDropzone, props);
252
+ }
253
+ export function NxFormField(props) {
254
+ return render(host().components.NxFormField, props);
255
+ }
256
+ export function NxFormSection(props) {
257
+ return render(host().components.NxFormSection, props);
258
+ }
259
+ export function NxHelpTooltip(props) {
260
+ return render(host().components.NxHelpTooltip, props);
261
+ }
262
+ export function NxLoadingBlock(props) {
263
+ return render(host().components.NxLoadingBlock, props);
264
+ }
265
+ export function NxModalDialog(props) {
266
+ return render(host().components.NxModalDialog, props);
267
+ }
268
+ export function SignatureInvitationChannelSelector(props) {
269
+ return render(host().components.SignatureInvitationChannelSelector, props);
270
+ }
271
+ export function SignatureAuthenticationMethodSelector(props) {
272
+ return render(host().components.SignatureAuthenticationMethodSelector, props);
273
+ }
274
+ /** Renders Core's request-local editor through the public App host boundary. */
275
+ export function SignatureRequestPreparationEditor(props) {
276
+ return render(host().components.SignatureRequestPreparationEditor, props);
277
+ }
278
+ /** Renders the protected exact-PDF review through the public App host boundary. */
279
+ export function SignatureRequestPreparationExactPreview(props) {
280
+ return render(host().components.SignatureRequestPreparationExactPreview, props);
281
+ }
282
+ /** Renders the placement-only request editor through the public App host boundary. */
283
+ export function SignatureRequestPreparationPlacementEditor(props) {
284
+ return render(host().components.SignatureRequestPreparationPlacementEditor, props);
285
+ }
286
+ /** Renders Core's app-neutral single-request flow through the public host boundary. */
287
+ export function SignatureSingleRequestDialog(props) {
288
+ return render(host().components.SignatureSingleRequestDialog, props);
289
+ }
290
+ export function NxCanonicalRoutePane(props) {
291
+ return render(host().components.NxCanonicalRoutePane, props);
292
+ }
293
+ export function NxOrgChart(props) {
294
+ return render(host().components.NxOrgChart, props);
295
+ }
296
+ export function NxResourceImportDialog(props) {
297
+ return render(host().components.NxResourceImportDialog, props);
298
+ }
299
+ export function NxResourceTransferActions(props) {
300
+ return render(host().components.NxResourceTransferActions, props);
301
+ }
302
+ export function NxDatasetImportWorkspace(props) {
303
+ return render(host().components.NxDatasetImportWorkspace, props);
304
+ }
305
+ export function NxDatasetExportWorkspace(props) {
306
+ return render(host().components.NxDatasetExportWorkspace, props);
307
+ }
308
+ export function NxMissingRequiredReferencesAlert(props) {
309
+ return render(host().components.NxMissingRequiredReferencesAlert, props);
310
+ }
311
+ export function NxPageFrame(props) {
312
+ return render(host().components.NxPageFrame, props);
313
+ }
314
+ export function NxResponsiveRegion(props) {
315
+ return render(host().components.NxResponsiveRegion, props);
316
+ }
317
+ export function NxPagination(props) {
318
+ return render(host().components.NxPagination, props);
319
+ }
320
+ export function NxSearchField(props) {
321
+ return render(host().components.NxSearchField, props);
322
+ }
323
+ export function NxSectionCard(props) {
324
+ return render(host().components.NxSectionCard, props);
325
+ }
326
+ export function NxSectionStack(props) {
327
+ return render(host().components.NxSectionStack, props);
328
+ }
329
+ export function NxSelect(props) {
330
+ return createElement((host().components.NxSelect), props);
331
+ }
332
+ export function NxStatCard(props) {
333
+ return render(host().components.NxStatCard, props);
334
+ }
335
+ export function NxStatusBadge(props) {
336
+ return render(host().components.NxStatusBadge, props);
337
+ }
338
+ export function NxTabNav(props) {
339
+ return render(host().components.NxTabNav, props);
340
+ }
341
+ export function NxTextArea(props) {
342
+ return render(host().components.NxTextArea, props);
343
+ }
344
+ export function NxTextInput(props) {
345
+ return render(host().components.NxTextInput, props);
346
+ }
347
+ export function NxTooltip(props) {
348
+ return render(host().components.NxTooltip, props);
349
+ }
350
+ export function OperatingUnitScopeField(props) {
351
+ return render(host().components.OperatingUnitScopeField, props);
352
+ }
353
+ export function OperatingUnitManagementSurface(props) {
354
+ return render(host().components.OperatingUnitManagementSurface, props);
355
+ }
356
+ export function ResourceInspectorPanel(props) {
357
+ return render(host().components.ResourceInspectorPanel, props);
358
+ }
359
+ export function ResourceInspectorStackHost(props) {
360
+ return render(host().components.ResourceInspectorStackHost, props);
361
+ }
362
+ export function ResourceInspectorStackProvider(props) {
363
+ return render(host().components.ResourceInspectorStackProvider, props);
364
+ }
365
+ export function ResourceInspectorState(props) {
366
+ return render(host().components.ResourceInspectorState, props);
367
+ }
368
+ export function ResourceBoard(props) {
369
+ return render(host().components.ResourceBoard, props);
370
+ }
371
+ export function ResourcePrimaryCell(props) {
372
+ return render(host().components.ResourcePrimaryCell, props);
373
+ }
374
+ export function ResourceListToolbarMoreMenu(props) {
375
+ return createElement((host().components.ResourceListToolbarMoreMenu), props);
376
+ }
377
+ export function ResourceRowActionsMenu(props) {
378
+ return render(host().components.ResourceRowActionsMenu, props);
379
+ }
380
+ export function ResourceStatusBadge(props) {
381
+ return render(host().components.ResourceStatusBadge, props);
382
+ }
383
+ export function ResourceSchedule(props) {
384
+ return render(host().components.ResourceSchedule, props);
385
+ }
386
+ export function ResourceTable(props) {
387
+ return createElement((host().components.ResourceTable), props);
388
+ }
389
+ export function ResourceTextCell(props) {
390
+ return render(host().components.ResourceTextCell, props);
391
+ }
392
+ export function WorkSection(props) {
393
+ return render(host().components.WorkSection, props);
394
+ }
395
+ export function WorkSurface(props) {
396
+ return render(host().components.WorkSurface, props);
397
+ }
398
+ export function useContextQuery() {
399
+ return host().hooks.useContextQuery();
400
+ }
401
+ export function useAffiliatedOperatingUnits(tenantId, legalEntityPublicId, permission, enabled = true) {
402
+ return host().hooks.useAffiliatedOperatingUnits(tenantId, legalEntityPublicId, permission, enabled);
403
+ }
404
+ export function useAgentToolDataInvalidation(enabled = true) {
405
+ host().hooks.useAgentToolDataInvalidation(enabled);
406
+ }
407
+ /**
408
+ * The freshness half of a widget's useQuery options, resolved by the host.
409
+ * Polling pauses while the surrounding Work Tab is parked, the host enforces
410
+ * its dashboard-wide minimum cadence, and slower refresh hints are honored.
411
+ * Realtime invalidation is a shell-owned accelerator, not the cadence contract.
412
+ */
413
+ export function useAgentToolDataFreshness(options) {
414
+ return host().hooks.useAgentToolDataFreshness(options);
415
+ }
416
+ /**
417
+ * Stable identifier of the Work Tab that owns the surrounding App surface.
418
+ * Apps can use it to isolate session-only drafts that must survive a route-tree
419
+ * remount without leaking those drafts into durable browser storage.
420
+ */
421
+ export function useActiveWorkTabId() {
422
+ return host().hooks.useActiveWorkTabId();
423
+ }
424
+ /**
425
+ * Whether the surrounding Work Tab is the visible pane rather than parked
426
+ * in the surface pool. Gate steady refetchInterval timers with this.
427
+ */
428
+ export function useIsActiveWorkTabVisible() {
429
+ return host().hooks.useIsActiveWorkTabVisible();
430
+ }
431
+ export function useAssignableOperatingUnits(tenantId, legalEntityPublicId, permission, enabled = true) {
432
+ return host().hooks.useAssignableOperatingUnits(tenantId, legalEntityPublicId, permission, enabled);
433
+ }
434
+ export function useAttachments(tenantId, attachableType, attachablePublicId) {
435
+ return host().hooks.useAttachments(tenantId, attachableType, attachablePublicId);
436
+ }
437
+ /** Active-context Approval route-policy catalog for App-owned reference fields. */
438
+ export function useApprovalRoutePoliciesQuery(tenantId, legalEntityPublicId, enabled = true) {
439
+ return host().hooks.useApprovalRoutePoliciesQuery(tenantId, legalEntityPublicId, enabled);
440
+ }
441
+ /** Shared approval lines always resolve from the stored record Legal Entity. */
442
+ export function useApprovalSharedLinesQuery(tenantId, legalEntityPublicId, enabled = true) {
443
+ return host().hooks.useApprovalSharedLinesQuery(tenantId, legalEntityPublicId, enabled);
444
+ }
445
+ export function useDashboardWidgetAutoHeight(widgetId) {
446
+ return host().hooks.useDashboardWidgetAutoHeight(widgetId);
447
+ }
448
+ export function useDebouncedValue(value, delayMs = 300) {
449
+ return host().hooks.useDebouncedValue(value, delayMs);
450
+ }
451
+ export function useDeleteAttachment(tenantId, attachableType, attachablePublicId) {
452
+ return host().hooks.useDeleteAttachment(tenantId, attachableType, attachablePublicId);
453
+ }
454
+ export function useLegalEntitiesQuery(tenantId) {
455
+ return host().hooks.useLegalEntitiesQuery(tenantId);
456
+ }
457
+ /** Active tenant catalog for tenant-owned record applicability; never a Shell switcher source. */
458
+ export function useLegalEntityApplicabilityQuery(tenantId, permission, enabled = true) {
459
+ return host().hooks.useLegalEntityApplicabilityQuery(tenantId, permission, enabled);
460
+ }
461
+ /** Exact permission-authorized Legal Entity and Operating Unit targets for an App surface. */
462
+ export function useOrganizationTargetsQuery(tenantId, permission, query = {}, enabled = true) {
463
+ return host().hooks.useOrganizationTargetsQuery(tenantId, permission, query, enabled);
464
+ }
465
+ /** Page-owned read scope. Invalid or unavailable scope never supplies request parameters. */
466
+ export function useOrganizationListScope(tenantId, permission, mode = 'legal-entity-list', enabled = true) {
467
+ return host().hooks.useOrganizationListScope(tenantId, permission, mode, enabled);
468
+ }
469
+ /** Legal Entity-bounded member options for App-owned assignment fields. */
470
+ export function useLegalEntityMembersQuery(tenantId, legalEntityPublicId, params = {}, enabled = true) {
471
+ return host().hooks.useLegalEntityMembersQuery(tenantId, legalEntityPublicId, params, enabled);
472
+ }
473
+ export function useOperatingUnitScope(tenantId, legalEntityPublicId, permission, enabled = true) {
474
+ return host().hooks.useOperatingUnitScope(tenantId, legalEntityPublicId, permission, enabled);
475
+ }
476
+ export function useOperatingUnitSelection(tenantId, legalEntityPublicId, permission, enabled = true) {
477
+ return host().hooks.useOperatingUnitSelection(tenantId, legalEntityPublicId, permission, enabled);
478
+ }
479
+ export function useOperatingUnitsQuery(tenantId, legalEntityPublicId, scope = 'memberships', permission, enabled = true) {
480
+ return host().hooks.useOperatingUnitsQuery(tenantId, legalEntityPublicId, scope, permission, enabled);
481
+ }
482
+ export function useParties(tenantId, params, enabled = true) {
483
+ return host().hooks.useParties(tenantId, params, enabled);
484
+ }
485
+ export function useUploadAttachment(tenantId, attachableType, attachablePublicId, options) {
486
+ return host().hooks.useUploadAttachment(tenantId, attachableType, attachablePublicId, options);
487
+ }
488
+ /**
489
+ * Starts a host-issued upload intent. The host may proxy the bytes or send
490
+ * them directly to object storage; App code never selects the transport.
491
+ */
492
+ export function useUploadFile() {
493
+ return host().hooks.useUploadFile();
494
+ }
495
+ /** Lists metadata for assets that the host can safely apply to a bound resource. */
496
+ export function useTrustedAssetsQuery(tenantId, legalEntityPublicId, params, enabled = true) {
497
+ return host().hooks.useTrustedAssetsQuery(tenantId, legalEntityPublicId, params, enabled);
498
+ }
499
+ /** Uploads a standalone Media resource through the configured Nexia host. */
500
+ export function useUploadMedia(tenantId) {
501
+ return host().hooks.useUploadMedia(tenantId);
502
+ }
503
+ /** Sends a host-owned login invitation without exposing Core internals to an App. */
504
+ export async function sendUserInvitation(payload) {
505
+ const { data } = await host().api.post('/users/invitations', payload);
506
+ return data;
507
+ }
508
+ export function usePermissionsQuery(tenantId, legalEntityPublicId, operatingUnitPublicId = null, enabled = true) {
509
+ return host().hooks.usePermissionsQuery(tenantId, legalEntityPublicId, operatingUnitPublicId, enabled);
510
+ }
511
+ /** Refreshes App-owned state when its committed resource projection changes. */
512
+ export function useResourceProjectionChange(subscription) {
513
+ host().hooks.useResourceProjectionChange(subscription);
514
+ }
515
+ export function useResourceListParams(options = {}) {
516
+ return host().hooks.useResourceListParams(options);
517
+ }
518
+ /** URL-backed date range for an Insights destination. */
519
+ export function useInsightFilterState(options = {}) {
520
+ return host().hooks.useInsightFilterState(options);
521
+ }
522
+ export function useDateTimeFormatter(options) {
523
+ return host().hooks.useDateTimeFormatter(options);
524
+ }
525
+ export function useMessage() {
526
+ return host().hooks.useMessage();
527
+ }
528
+ let nextFeedbackActionId = 1;
529
+ /**
530
+ * Adds standard pending, duplicate-submission, and result feedback behavior to
531
+ * an App operation without exposing the Shell message store.
532
+ *
533
+ * @example
534
+ * const save = useFeedbackAction(saveEmployee, {
535
+ * success: 'Saved.',
536
+ * error: 'Could not save.',
537
+ * dedupeKey: 'employees:save',
538
+ * undo: {
539
+ * label: 'Undo',
540
+ * operation: (saved, [input]) => restoreEmployee(saved.id, input),
541
+ * success: 'Save undone.',
542
+ * error: 'Could not undo the save.',
543
+ * },
544
+ * });
545
+ *
546
+ * <NxActionButton
547
+ * kind="save"
548
+ * label="Save"
549
+ * loading={save.pending}
550
+ * onClick={() => void save.run(values)}
551
+ * />
552
+ */
553
+ export function useFeedbackAction(operation, options) {
554
+ const message = useMessage();
555
+ const [generatedId] = useState(() => `feedback-${nextFeedbackActionId++}`);
556
+ const [pending, setPending] = useState(false);
557
+ const mounted = useRef(false);
558
+ const inFlight = useRef(null);
559
+ const messageRef = useRef(message);
560
+ const operationRef = useRef(operation);
561
+ const optionsRef = useRef(options);
562
+ messageRef.current = message;
563
+ operationRef.current = operation;
564
+ optionsRef.current = options;
565
+ useEffect(() => {
566
+ mounted.current = true;
567
+ return () => {
568
+ mounted.current = false;
569
+ };
570
+ }, []);
571
+ const runOrThrow = useCallback((...arguments_) => {
572
+ if (inFlight.current)
573
+ return inFlight.current;
574
+ if (mounted.current)
575
+ setPending(true);
576
+ const activeOperation = operationRef.current;
577
+ const activeOptions = optionsRef.current;
578
+ const dedupeKey = activeOptions.dedupeKey ?? `operation:${generatedId}`;
579
+ const operationPromise = Promise.resolve()
580
+ .then(() => activeOperation(...arguments_))
581
+ .then((result) => {
582
+ const undoArguments = Object.assign([], arguments_);
583
+ try {
584
+ showFeedbackToast(messageRef.current, 'success', activeOptions.success, result, arguments_, dedupeKey, () => createFeedbackUndoAction(messageRef.current, activeOptions.undo, result, undoArguments, dedupeKey));
585
+ }
586
+ catch {
587
+ // Presentation must not turn a completed operation into
588
+ // a rejected workflow. The successful result remains
589
+ // authoritative even if an App supplied faulty copy.
590
+ }
591
+ return result;
592
+ }, (error) => {
593
+ try {
594
+ showFeedbackToast(messageRef.current, 'error', activeOptions.error, error, arguments_, dedupeKey);
595
+ }
596
+ catch {
597
+ // Feedback copy is presentation code. A faulty resolver
598
+ // must not replace the operation error promised by
599
+ // runOrThrow(); the caller still receives the original
600
+ // rejection and can recover at its own boundary.
601
+ }
602
+ throw error;
603
+ })
604
+ .finally(() => {
605
+ if (inFlight.current !== operationPromise)
606
+ return;
607
+ inFlight.current = null;
608
+ if (mounted.current)
609
+ setPending(false);
610
+ });
611
+ inFlight.current = operationPromise;
612
+ return operationPromise;
613
+ }, [generatedId]);
614
+ const run = useCallback((...arguments_) => runOrThrow(...arguments_).catch(() => undefined), [runOrThrow]);
615
+ return { run, runOrThrow, pending };
616
+ }
617
+ function showFeedbackToast(message, variant, resolver, value, arguments_, dedupeKey, fallbackAction) {
618
+ const resolved = typeof resolver === 'function'
619
+ ? resolver(value, arguments_)
620
+ : resolver;
621
+ const presentation = typeof resolved === 'string'
622
+ ? { title: resolved }
623
+ : resolved;
624
+ const { title, ...toastOptions } = presentation;
625
+ let action = toastOptions.action;
626
+ if (!action && fallbackAction) {
627
+ try {
628
+ action = fallbackAction();
629
+ }
630
+ catch {
631
+ // Invalid optional action configuration must not suppress the
632
+ // successful operation's ordinary feedback.
633
+ }
634
+ }
635
+ message.toast[variant](title, {
636
+ ...toastOptions,
637
+ ...(action ? { action } : {}),
638
+ dedupeKey,
639
+ source: 'operation',
640
+ });
641
+ }
642
+ function createFeedbackUndoAction(message, undo, result, arguments_, dedupeKey) {
643
+ if (!undo)
644
+ return undefined;
645
+ const { label, operation, success, error } = undo;
646
+ if (typeof label !== 'string' || label.trim() === '' || typeof operation !== 'function') {
647
+ return undefined;
648
+ }
649
+ const capturedArguments = arguments_;
650
+ let invoked = false;
651
+ return {
652
+ label,
653
+ onAction: () => {
654
+ if (invoked)
655
+ return;
656
+ invoked = true;
657
+ void Promise.resolve()
658
+ .then(() => operation(result, capturedArguments))
659
+ .then((undoResult) => {
660
+ try {
661
+ showFeedbackToast(message, 'success', success, undoResult, capturedArguments, `${dedupeKey}:undo`);
662
+ }
663
+ catch {
664
+ // Undo feedback is presentation-only. A broken
665
+ // resolver cannot rewrite the completed inverse.
666
+ }
667
+ }, (undoError) => {
668
+ try {
669
+ showFeedbackToast(message, 'error', error, undoError, capturedArguments, `${dedupeKey}:undo`);
670
+ }
671
+ catch {
672
+ // The inverse rejection is already contained by the
673
+ // action boundary; faulty feedback stays isolated.
674
+ }
675
+ });
676
+ },
677
+ };
678
+ }
679
+ export function useRegisterListLocateAction(options) {
680
+ host().hooks.useRegisterListLocateAction(options);
681
+ }
682
+ export function useOpenResourceWorkTab(defaultIcon = 'document') {
683
+ return host().hooks.useOpenResourceWorkTab(defaultIcon);
684
+ }
685
+ export function useRegisterResourceCreateReceiver(registration) {
686
+ host().hooks.useRegisterResourceCreateReceiver(registration);
687
+ }
688
+ export function useResourceCreateCompletion() {
689
+ return host().hooks.useResourceCreateCompletion();
690
+ }
691
+ export function useMarkTabDirty(dirty) {
692
+ host().hooks.useMarkTabDirty(dirty);
693
+ }
694
+ export function useRegisterTabActions(actions) {
695
+ host().hooks.useRegisterTabActions(actions);
696
+ }
697
+ export function useWorkTabLabel(label) {
698
+ host().hooks.useWorkTabLabel(label);
699
+ }
700
+ export function useWorkSurfaceLabels(input) {
701
+ return host().hooks.useWorkSurfaceLabels(input);
702
+ }
703
+ export function autoRegisterPackageSurfaces(options) {
704
+ host().runtime.autoRegisterPackageSurfaces(options);
705
+ }
706
+ /**
707
+ * Declares the filesystem-owned inspector registration set for an App entry.
708
+ *
709
+ * Vite evaluates an eager `import.meta.glob` before passing the modules here;
710
+ * each generated registration module then registers its lazy inspector loader.
711
+ * Keeping the convention in the SDK means an App never needs to maintain a
712
+ * growing list of side-effect imports in its entry point.
713
+ */
714
+ export function autoRegisterPackageResourceInspectors(modules) {
715
+ const pattern = /^\.\/resources\/[^/]+\/inspector\/register-[^/]+-inspector\.ts$/;
716
+ for (const path of Object.keys(modules)) {
717
+ if (!pattern.test(path)) {
718
+ throw new Error(`Invalid package inspector registration path [${path}].`);
719
+ }
720
+ }
721
+ }
722
+ export function firstFieldError(errors, field) {
723
+ return host().runtime.firstFieldError(errors, field);
724
+ }
725
+ export function withoutFieldError(errors, field) {
726
+ return host().runtime.withoutFieldError(errors, field);
727
+ }
728
+ export function parseMutationFormError(input) {
729
+ return host().runtime.parseMutationFormError(input);
730
+ }
731
+ export function keepPreviousResourceListData(queryScope) {
732
+ return host().runtime.keepPreviousResourceListData(queryScope);
733
+ }
734
+ export function readResourceListParams(searchParams, options = {}) {
735
+ return host().runtime.readResourceListParams(searchParams, options);
736
+ }
737
+ export function registerAgentComponent(name, renderer) {
738
+ host().runtime.registerAgentComponent(name, renderer);
739
+ }
740
+ /** Register an App-owned Agent renderer without placing it in the App entry chunk. */
741
+ export function registerLazyAgentComponent(name, loader) {
742
+ host().runtime.registerLazyAgentComponent(name, loader);
743
+ }
744
+ export function can(permissions, permission) {
745
+ if (permissions.includes(permission))
746
+ return true;
747
+ return permissions.some((pattern) => {
748
+ if (!pattern.endsWith('.*'))
749
+ return false;
750
+ const prefix = pattern.slice(0, -1);
751
+ return permission.startsWith(prefix);
752
+ });
753
+ }
754
+ export function serializeResourceTableSort(sort) {
755
+ if (!sort)
756
+ return undefined;
757
+ return sort.dir === 'desc' ? `-${sort.key}` : sort.key;
758
+ }
759
+ function registerApprovalBusinessForm(registrationOrKey, legacyLoader) {
760
+ if (typeof registrationOrKey === 'string') {
761
+ host().registries.approvalComposerBusinessFormRegistry.register(registrationOrKey, legacyLoader);
762
+ return;
763
+ }
764
+ host().registries.approvalComposerBusinessFormRegistry.register(registrationOrKey);
765
+ }
766
+ export const approvalComposerBusinessFormRegistry = {
767
+ register: registerApprovalBusinessForm,
768
+ };
769
+ export const dataMigrationRegistry = {
770
+ registerProvider(registration) {
771
+ host().registries.dataMigrationRegistry.registerProvider(registration);
772
+ },
773
+ registerTarget(registration) {
774
+ host().registries.dataMigrationRegistry.registerTarget(registration);
775
+ },
776
+ registerStage(registration) {
777
+ host().registries.dataMigrationRegistry.registerStage(registration);
778
+ },
779
+ };
780
+ export const processUserTaskFormRegistry = {
781
+ register(registration) {
782
+ host().registries.processUserTaskFormRegistry.register(registration);
783
+ },
784
+ };
785
+ /** Stable Resource-key resolver for cross-App contextual create flows. */
786
+ export const resourceCreateDestinationRegistry = {
787
+ register(registration) {
788
+ host().registries.resourceCreateDestinationRegistry.register(registration);
789
+ },
790
+ resolve(resourceKey, query) {
791
+ return host().registries.resourceCreateDestinationRegistry.resolve(resourceKey, query);
792
+ },
793
+ };
794
+ function registerResourceInspectorAdapter(type, loader) {
795
+ host().registries.resourceInspectorAdapterRegistry.register(type, loader);
796
+ }
797
+ export const resourceInspectorAdapterRegistry = {
798
+ register: registerResourceInspectorAdapter,
799
+ };
800
+ /** Shared spreadsheet editor; the caller owns document persistence. */
801
+ export function NxSpreadsheetEditor(props) {
802
+ return render(host().components.NxSpreadsheetEditor, props);
803
+ }