@kizenapps/engine 1.7.4-2fa1b01 → 1.8.0-acda2a8

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 (42) hide show
  1. package/README.md +74 -0
  2. package/dist/{automation-Bpg6VoKc.d.ts → automation-Dr26TnMo.d.ts} +2 -1
  3. package/dist/{blocks-DuJJdwgj.d.ts → blocks-C0e9BCrR.d.ts} +1 -1
  4. package/dist/{chunk-UQBW6I5K.js → chunk-2F7MTOPU.js} +114 -13
  5. package/dist/chunk-2F7MTOPU.js.map +1 -0
  6. package/dist/{chunk-W37TFKDD.js → chunk-5AVQAIL3.js} +3 -3
  7. package/dist/{chunk-W37TFKDD.js.map → chunk-5AVQAIL3.js.map} +1 -1
  8. package/dist/{chunk-2E5Z7NLE.js → chunk-FAL6AKZI.js} +3 -3
  9. package/dist/{chunk-2E5Z7NLE.js.map → chunk-FAL6AKZI.js.map} +1 -1
  10. package/dist/{chunk-PYZX4ZDW.js → chunk-MOP6TWMH.js} +4 -4
  11. package/dist/{chunk-PYZX4ZDW.js.map → chunk-MOP6TWMH.js.map} +1 -1
  12. package/dist/{chunk-XDXUE4KQ.js → chunk-QGWFQVML.js} +3 -3
  13. package/dist/{chunk-XDXUE4KQ.js.map → chunk-QGWFQVML.js.map} +1 -1
  14. package/dist/{chunk-X3VOYGS6.js → chunk-QWUS5FG5.js} +3 -3
  15. package/dist/{chunk-X3VOYGS6.js.map → chunk-QWUS5FG5.js.map} +1 -1
  16. package/dist/{chunk-UUITD2B5.js → chunk-R347VQ7Y.js} +3 -3
  17. package/dist/{chunk-UUITD2B5.js.map → chunk-R347VQ7Y.js.map} +1 -1
  18. package/dist/{chunk-MRHISAX3.js → chunk-T24XZSEF.js} +3 -3
  19. package/dist/{chunk-MRHISAX3.js.map → chunk-T24XZSEF.js.map} +1 -1
  20. package/dist/{chunk-FDF3DENJ.js → chunk-UVDPA7UL.js} +8 -7
  21. package/dist/chunk-UVDPA7UL.js.map +1 -0
  22. package/dist/communication.js +2 -2
  23. package/dist/contexts/base.d.ts +1 -1
  24. package/dist/contexts/base.js +4 -4
  25. package/dist/contexts/floatingFrame.js +5 -5
  26. package/dist/contexts/recordDetail.js +5 -5
  27. package/dist/index.d.ts +8 -4
  28. package/dist/index.js +4 -4
  29. package/dist/react.d.ts +6 -4
  30. package/dist/react.js +15 -6
  31. package/dist/react.js.map +1 -1
  32. package/dist/types.d.ts +3 -3
  33. package/dist/util.d.ts +2 -2
  34. package/dist/util.js +6 -6
  35. package/dist/{values-B_vFQrTp.d.ts → values-DCW2Il72.d.ts} +1 -1
  36. package/dist/workers/calendarSource.worker.js +6 -6
  37. package/dist/workers/floatingFrame.worker.js +7 -7
  38. package/dist/workers/generic.worker.js +6 -6
  39. package/dist/workers/recordDetail.worker.js +7 -7
  40. package/package.json +1 -1
  41. package/dist/chunk-FDF3DENJ.js.map +0 -1
  42. package/dist/chunk-UQBW6I5K.js.map +0 -1
package/README.md CHANGED
@@ -201,3 +201,77 @@ Some worker calls are coordinated using `@tanstack/react-query`. If your consume
201
201
  ### Script Return Values
202
202
 
203
203
  Scripts can return values from the worker thread. Awaiting the execute function returned from a plugin runner script will yield the value that the worker thread returned.
204
+
205
+ ### Navigation Context
206
+
207
+ A script can hand a JSON payload to the page it navigates to — for example, to open a custom object page with an unsaved filter already applied. The engine stores the payload in `sessionStorage`, appends a `session_data_key` query param to the target URL, and lets the destination page read it back.
208
+
209
+ Context only applies to **in-app** (same-origin, relative) navigations. Both targets are supported:
210
+
211
+ - **`'_self'`** navigates the current tab via the host router.
212
+ - **`'_blank'`** opens a new tab. The browser copies the current tab's `sessionStorage` into the new one at open time, so the payload rides along. (This is why the engine opens context-carrying `_blank` tabs without `noopener`/`noreferrer` — that copy only happens while the opener relationship is intact. It is restricted to same-origin URLs so `window.opener` is never exposed cross-origin.)
213
+
214
+ **External / cross-origin** navigations ignore context entirely and keep the secure `noopener noreferrer` defaults. The reader helpers are **main-thread only** — workers cannot read this state.
215
+
216
+ #### Passing context from a script
217
+
218
+ Pass the payload as the third argument to `openWindow`. It is serialized with `JSON.stringify`: circular references and `BigInt` values throw synchronously, while functions, `undefined`, and symbols are silently dropped (standard `JSON.stringify` behavior).
219
+
220
+ ```js
221
+ // Same tab:
222
+ this.openWindow('/custom-objects/leads/records', '_self', {
223
+ unsavedFilter: {
224
+ /* ...payload */
225
+ },
226
+ });
227
+
228
+ // New tab — same payload, copied into the new tab's sessionStorage:
229
+ this.openWindow('/custom-objects/leads/records', '_blank', {
230
+ unsavedFilter: {
231
+ /* ...payload */
232
+ },
233
+ });
234
+ ```
235
+
236
+ #### Reading context in React
237
+
238
+ `useAppNavigationContext` takes the current URL (feed it from your router) and returns the payload plus a `clear` callback. Clear it once applied so a back-nav or refresh doesn't reapply stale context.
239
+
240
+ ```tsx
241
+ import { useEffect } from 'react';
242
+ import { useLocation } from 'react-router-dom';
243
+ import { useAppNavigationContext } from '@kizenapps/engine/react';
244
+
245
+ const RecordsPage = () => {
246
+ const { pathname, search } = useLocation();
247
+ const [navContext, clearNavContext] = useAppNavigationContext(`${pathname}${search}`);
248
+
249
+ useEffect(() => {
250
+ if (!navContext) return;
251
+
252
+ applyUnsavedFilter(navContext.unsavedFilter);
253
+
254
+ clearNavContext();
255
+ }, [navContext, clearNavContext]);
256
+
257
+ return null;
258
+ };
259
+ ```
260
+
261
+ #### Reading context outside React
262
+
263
+ The package root exports plain helpers that all take an explicit URL. `consumeNavigationContext` reads and clears in one call:
264
+
265
+ ```ts
266
+ import {
267
+ consumeNavigationContext, // read + clear (default choice)
268
+ readNavigationContext, // read only
269
+ clearNavigationContext, // clear only
270
+ } from '@kizenapps/engine';
271
+
272
+ const context = consumeNavigationContext(window.location.href);
273
+
274
+ if (context?.unsavedFilter) {
275
+ applyUnsavedFilter(context.unsavedFilter);
276
+ }
277
+ ```
@@ -117,6 +117,7 @@ interface OpenWindowEvent extends BaseEvent {
117
117
  url: string;
118
118
  target: string;
119
119
  features: string;
120
+ context?: Record<string, unknown>;
120
121
  }
121
122
  interface RecipientConfig {
122
123
  frame?: string;
@@ -363,4 +364,4 @@ interface AutomationStepConfig<T = unknown> {
363
364
  plugin_api_name?: string;
364
365
  }
365
366
 
366
- export type { SchemaValidation as $, AutomationStepConfig as A, BaseEvent as B, CalendarSourceConfig as C, DataAdornmentConfig as D, ErrorEvent as E, FloatingFrameConfig as F, GetPendingCacheCountFn as G, HideEvent as H, IframeOutputEvent as I, OnShowToastFn as J, KizenFile as K, OpenCreateRecordModalRequestEvent as L, MessageEventData as M, OpenCreateRelatedRecordModalRequestEvent as N, OnClearToastsFn as O, OpenWindowEvent as P, PerformKizenFileUploadFn as Q, RoutablePageConfig as R, PostFormDataRequestEvent as S, ToolbarItemConfig as T, PromptRequestEvent as U, QueryRequestEvent as V, RecipientConfig as W, RefreshEntityEvent as X, RefreshTimelineEvent as Y, RequestableQueryMethods as Z, RunEventScriptEvent as _, RouteScriptConfig as a, SetStateEvent as a0, ShowEvent as a1, ShowToastEvent as a2, ShowViewInModalRequestEvent as a3, TerminatorContent as a4, Terminators as a5, UIOutputEvent as a6, UpdateSessionDataEvent as a7, UploadFilePayload as a8, UploadFileRequestEvent as a9, WindowPosition as aa, RunScriptOptions as b, AuthorizeEvent as c, CalendarDefinition as d, CalendarScriptReturnData as e, CalendarSourceMap as f, CalendarSources as g, CloseModalRequestEvent as h, CommonExecutionPlugin as i, CommonPluginDefinition as j, CommunicateEvent as k, ConsoleLogEvent as l, CopyToClipboardEvent as m, CreateFileIdFn as n, DoneEvent as o, DynamicPromptRequestEvent as p, ExecuteCalendarSourceScript as q, ExecuteFloatingFrameScript as r, FloatingFrameEmployeeConfig as s, FrameQuadrant as t, InstallThirdPartyScriptRequestEvent as u, InvalidateCacheFn as v, MinimizedConfig as w, OnConsoleLogFn as x, OnNetworkRequestFn as y, OnRunEventScriptFn as z };
367
+ export type { SchemaValidation as $, AutomationStepConfig as A, BaseEvent as B, CalendarSourceConfig as C, DataAdornmentConfig as D, ErrorEvent as E, FloatingFrameConfig as F, GetPendingCacheCountFn as G, HideEvent as H, IframeOutputEvent as I, OnShowToastFn as J, KizenFile as K, OpenCreateRecordModalRequestEvent as L, MessageEventData as M, OpenCreateRelatedRecordModalRequestEvent as N, OnClearToastsFn as O, OpenWindowEvent as P, PerformKizenFileUploadFn as Q, RoutablePageConfig as R, PostFormDataRequestEvent as S, ToolbarItemConfig as T, PromptRequestEvent as U, QueryRequestEvent as V, RecipientConfig as W, RefreshEntityEvent as X, RefreshTimelineEvent as Y, RequestableQueryMethods as Z, RunEventScriptEvent as _, RouteScriptConfig as a, SetStateEvent as a0, ShowEvent as a1, ShowToastEvent as a2, ShowViewInModalRequestEvent as a3, TerminatorContent as a4, Terminators as a5, UIOutputEvent as a6, UpdateSessionDataEvent as a7, UploadFilePayload as a8, UploadFileRequestEvent as a9, WindowPosition as aa, CommonExecutionPlugin as b, CommonPluginDefinition as c, RunScriptOptions as d, AuthorizeEvent as e, CalendarDefinition as f, CalendarScriptReturnData as g, CalendarSourceMap as h, CalendarSources as i, CloseModalRequestEvent as j, CommunicateEvent as k, ConsoleLogEvent as l, CopyToClipboardEvent as m, CreateFileIdFn as n, DoneEvent as o, DynamicPromptRequestEvent as p, ExecuteCalendarSourceScript as q, ExecuteFloatingFrameScript as r, FloatingFrameEmployeeConfig as s, FrameQuadrant as t, InstallThirdPartyScriptRequestEvent as u, InvalidateCacheFn as v, MinimizedConfig as w, OnConsoleLogFn as x, OnNetworkRequestFn as y, OnRunEventScriptFn as z };
@@ -1,4 +1,4 @@
1
- import { i as CommonExecutionPlugin, j as CommonPluginDefinition } from './automation-Bpg6VoKc.js';
1
+ import { b as CommonExecutionPlugin, c as CommonPluginDefinition } from './automation-Dr26TnMo.js';
2
2
  import { U as UnknownJSON } from './ThirdPartyScript-DauYx3B5.js';
3
3
 
4
4
  interface GenericPluginConfig extends CommonPluginDefinition {
@@ -1,6 +1,6 @@
1
- import { getPartialLocation, generateUUIDV4 } from './chunk-UUITD2B5.js';
2
- import { getAllNestedInputsFromConfig, buildIframeURLWithProxy, getParentFrameAllowParam, deserializeConsoleArg, KizenRequestError, filterSandboxList, filterAllowList } from './chunk-MRHISAX3.js';
3
- import { IFRAME_PREFIX, ACTIONS, RESPONSES, COMMUNICATIONS, thirdPartyGlobalNames, getScriptIntegrationType, thirdPartySetupScripts, thirdPartyReadyPredicates } from './chunk-W37TFKDD.js';
1
+ import { getPartialLocation, generateUUIDV4 } from './chunk-R347VQ7Y.js';
2
+ import { getAllNestedInputsFromConfig, buildIframeURLWithProxy, getParentFrameAllowParam, deserializeConsoleArg, KizenRequestError, filterSandboxList, filterAllowList } from './chunk-T24XZSEF.js';
3
+ import { IFRAME_PREFIX, ACTIONS, RESPONSES, COMMUNICATIONS, thirdPartyGlobalNames, getScriptIntegrationType, thirdPartySetupScripts, thirdPartyReadyPredicates } from './chunk-5AVQAIL3.js';
4
4
  import { __commonJS, __toESM } from './chunk-5WRI5ZAA.js';
5
5
  import DOMPurify from 'dompurify';
6
6
 
@@ -1796,10 +1796,66 @@ var getPluginSafeHTML = (html, pluginApiName, options) => {
1796
1796
  }
1797
1797
  };
1798
1798
 
1799
+ // src/communication/storage.ts
1800
+ var STORAGE_KEY_PREFIX = "kizen-app-context";
1801
+ var SESSION_DATA_PARAM = "session_data_key";
1802
+ var getStorageKey = () => `${STORAGE_KEY_PREFIX}-${generateUUIDV4()}`;
1803
+ var getStorageKeyFromUrl = (url) => {
1804
+ try {
1805
+ const key = new URL(url, window.location.origin).searchParams.get(SESSION_DATA_PARAM);
1806
+ return key?.startsWith(`${STORAGE_KEY_PREFIX}-`) ? key : null;
1807
+ } catch {
1808
+ return null;
1809
+ }
1810
+ };
1811
+ var storeNavigationContext = (context) => {
1812
+ const storageKey = getStorageKey();
1813
+ sessionStorage.setItem(storageKey, JSON.stringify(context));
1814
+ return storageKey;
1815
+ };
1816
+ var transformNavigationUrl = (url, key) => {
1817
+ const urlObj = new URL(url, window.location.origin);
1818
+ urlObj.searchParams.set(SESSION_DATA_PARAM, key);
1819
+ return `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;
1820
+ };
1821
+ var readNavigationContext = (url) => {
1822
+ const storageKey = getStorageKeyFromUrl(url);
1823
+ if (!storageKey) {
1824
+ return void 0;
1825
+ }
1826
+ try {
1827
+ const contextString = sessionStorage.getItem(storageKey);
1828
+ if (!contextString) {
1829
+ return void 0;
1830
+ }
1831
+ return JSON.parse(contextString);
1832
+ } catch {
1833
+ return void 0;
1834
+ }
1835
+ };
1836
+ var clearNavigationContext = (url) => {
1837
+ const storageKey = getStorageKeyFromUrl(url);
1838
+ if (storageKey) {
1839
+ sessionStorage.removeItem(storageKey);
1840
+ }
1841
+ };
1842
+ var consumeNavigationContext = (url) => {
1843
+ const context = readNavigationContext(url);
1844
+ clearNavigationContext(url);
1845
+ return context;
1846
+ };
1847
+
1799
1848
  // src/WorkerManager.ts
1800
1849
  var isRelative = (url) => {
1801
1850
  return url.startsWith("/");
1802
1851
  };
1852
+ var isSameOrigin = (url) => {
1853
+ try {
1854
+ return new URL(url, window.location.origin).origin === window.location.origin;
1855
+ } catch {
1856
+ return false;
1857
+ }
1858
+ };
1803
1859
  var refreshTimeout = 3e4;
1804
1860
  var refreshInterval = 100;
1805
1861
  var WorkerManager = class {
@@ -1948,7 +2004,8 @@ var WorkerManager = class {
1948
2004
  this.handleOpenWindow(
1949
2005
  consideredEvent.url,
1950
2006
  consideredEvent.target,
1951
- consideredEvent.features
2007
+ consideredEvent.features,
2008
+ consideredEvent.context
1952
2009
  );
1953
2010
  return;
1954
2011
  }
@@ -2460,12 +2517,56 @@ var WorkerManager = class {
2460
2517
  });
2461
2518
  }
2462
2519
  };
2463
- handleOpenWindow = (url, target, features) => {
2464
- if (!isRelative(url) || target === "_blank" || !this.pushHistory) {
2465
- window.open(url, target, features);
2466
- } else {
2467
- this.pushHistory(url);
2520
+ applyNavigationContext = (url, context) => {
2521
+ let storageKey;
2522
+ try {
2523
+ storageKey = storeNavigationContext(context);
2524
+ } catch {
2525
+ this.onError?.({
2526
+ message: "Failed to store context in sessionStorage."
2527
+ });
2528
+ return url;
2529
+ }
2530
+ try {
2531
+ return transformNavigationUrl(url, storageKey);
2532
+ } catch {
2533
+ try {
2534
+ sessionStorage.removeItem(storageKey);
2535
+ } catch {
2536
+ }
2537
+ this.onError?.({
2538
+ message: "Failed to append the context key to the navigation URL."
2539
+ });
2540
+ return url;
2541
+ }
2542
+ };
2543
+ handleOpenWindow = (url, target, features, context) => {
2544
+ const { pushHistory } = this;
2545
+ if (isRelative(url) && target !== "_blank") {
2546
+ const finalUrl = context ? this.applyNavigationContext(url, context) : url;
2547
+ if (pushHistory) {
2548
+ pushHistory(finalUrl);
2549
+ } else {
2550
+ window.open(finalUrl, target, features);
2551
+ }
2552
+ return;
2553
+ }
2554
+ if (isRelative(url) && target === "_blank" && context && isSameOrigin(url)) {
2555
+ let storageKey;
2556
+ try {
2557
+ storageKey = storeNavigationContext(context);
2558
+ } catch {
2559
+ this.onError?.({
2560
+ message: "Failed to store context in sessionStorage."
2561
+ });
2562
+ window.open(url, target, features);
2563
+ return;
2564
+ }
2565
+ window.open(transformNavigationUrl(url, storageKey), "_blank");
2566
+ sessionStorage.removeItem(storageKey);
2567
+ return;
2468
2568
  }
2569
+ window.open(url, target, features);
2469
2570
  };
2470
2571
  handleAuthorize = (serviceName, config = {}) => {
2471
2572
  const params = new URLSearchParams();
@@ -2682,8 +2783,8 @@ var modalSize = {
2682
2783
  };
2683
2784
 
2684
2785
  // src/index.ts
2685
- var version = "1.7.4-2fa1b01";
2786
+ var version = "1.8.0-acda2a8";
2686
2787
 
2687
- export { forceQualifiedUrl, getDisabledValue, getEnabledState, getHash, getLinkValue, getPluginSafeHTML, getQrCodeValue, getStableHash, isFlagEnabled, mergeConfig, modalSize, pluginMapper, reduceEnabledResults, replaceConfigValues, runExpression, runObjectExpression, runOptionExpression, runScript, runStringExpression, version };
2688
- //# sourceMappingURL=chunk-UQBW6I5K.js.map
2689
- //# sourceMappingURL=chunk-UQBW6I5K.js.map
2788
+ export { clearNavigationContext, consumeNavigationContext, forceQualifiedUrl, getDisabledValue, getEnabledState, getHash, getLinkValue, getPluginSafeHTML, getQrCodeValue, getStableHash, isFlagEnabled, mergeConfig, modalSize, pluginMapper, readNavigationContext, reduceEnabledResults, replaceConfigValues, runExpression, runObjectExpression, runOptionExpression, runScript, runStringExpression, version };
2789
+ //# sourceMappingURL=chunk-2F7MTOPU.js.map
2790
+ //# sourceMappingURL=chunk-2F7MTOPU.js.map