@equinor/fusion-framework-plugin-context-navigation 0.1.0 → 0.1.2

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 (218) hide show
  1. package/dist/esm/ContextNavigationConfigurator.js +178 -0
  2. package/dist/esm/ContextNavigationConfigurator.js.map +1 -0
  3. package/dist/esm/__tests__/active-app-navigation-events.test.js +115 -0
  4. package/dist/esm/__tests__/active-app-navigation-events.test.js.map +1 -0
  5. package/dist/esm/__tests__/apply-navigation.test.js +152 -0
  6. package/dist/esm/__tests__/apply-navigation.test.js.map +1 -0
  7. package/dist/esm/__tests__/enable.test.js +91 -0
  8. package/dist/esm/__tests__/enable.test.js.map +1 -0
  9. package/dist/esm/__tests__/guard-handlers.test.js +82 -0
  10. package/dist/esm/__tests__/guard-handlers.test.js.map +1 -0
  11. package/dist/esm/__tests__/plugin.test.js +483 -0
  12. package/dist/esm/__tests__/plugin.test.js.map +1 -0
  13. package/dist/esm/__tests__/reconcile.test.js +164 -0
  14. package/dist/esm/__tests__/reconcile.test.js.map +1 -0
  15. package/dist/esm/adapters/create-path-adapter.js +96 -0
  16. package/dist/esm/adapters/create-path-adapter.js.map +1 -0
  17. package/dist/esm/adapters/create-query-adapter.js +83 -0
  18. package/dist/esm/adapters/create-query-adapter.js.map +1 -0
  19. package/dist/esm/adapters/custom-adapter/create-custom-adapter.js +116 -0
  20. package/dist/esm/adapters/custom-adapter/create-custom-adapter.js.map +1 -0
  21. package/dist/esm/adapters/custom-adapter/index.js +5 -0
  22. package/dist/esm/adapters/custom-adapter/index.js.map +1 -0
  23. package/dist/esm/adapters/custom-adapter/normalize-string-result.js +37 -0
  24. package/dist/esm/adapters/custom-adapter/normalize-string-result.js.map +1 -0
  25. package/dist/esm/adapters/custom-adapter/to-app-relative.js +34 -0
  26. package/dist/esm/adapters/custom-adapter/to-app-relative.js.map +1 -0
  27. package/dist/esm/adapters/custom-adapter/to-full-path.js +28 -0
  28. package/dist/esm/adapters/custom-adapter/to-full-path.js.map +1 -0
  29. package/dist/esm/adapters/index.js +4 -0
  30. package/dist/esm/adapters/index.js.map +1 -0
  31. package/dist/esm/adapters/types.js +2 -0
  32. package/dist/esm/adapters/types.js.map +1 -0
  33. package/dist/esm/apply-navigation.js +102 -0
  34. package/dist/esm/apply-navigation.js.map +1 -0
  35. package/dist/esm/constants/context-query-param-key.js +8 -0
  36. package/dist/esm/constants/context-query-param-key.js.map +1 -0
  37. package/dist/esm/constants/index.js +3 -0
  38. package/dist/esm/constants/index.js.map +1 -0
  39. package/dist/esm/constants/uuid-pattern.js +8 -0
  40. package/dist/esm/constants/uuid-pattern.js.map +1 -0
  41. package/dist/esm/create-context-navigation-plugin.js +124 -0
  42. package/dist/esm/create-context-navigation-plugin.js.map +1 -0
  43. package/dist/esm/enable-context-navigation.js +40 -0
  44. package/dist/esm/enable-context-navigation.js.map +1 -0
  45. package/dist/esm/events.js +2 -0
  46. package/dist/esm/events.js.map +1 -0
  47. package/dist/esm/guard-handlers/consume-own-nav-token.js +29 -0
  48. package/dist/esm/guard-handlers/consume-own-nav-token.js.map +1 -0
  49. package/dist/esm/guard-handlers/guard-tick-deps.js +2 -0
  50. package/dist/esm/guard-handlers/guard-tick-deps.js.map +1 -0
  51. package/dist/esm/guard-handlers/guard-tick-payload.js +2 -0
  52. package/dist/esm/guard-handlers/guard-tick-payload.js.map +1 -0
  53. package/dist/esm/guard-handlers/handle-push-mode-guard.js +44 -0
  54. package/dist/esm/guard-handlers/handle-push-mode-guard.js.map +1 -0
  55. package/dist/esm/guard-handlers/handle-replace-mode-guard.js +40 -0
  56. package/dist/esm/guard-handlers/handle-replace-mode-guard.js.map +1 -0
  57. package/dist/esm/guard-handlers/index.js +5 -0
  58. package/dist/esm/guard-handlers/index.js.map +1 -0
  59. package/dist/esm/guard-handlers/is-in-app-scope.js +19 -0
  60. package/dist/esm/guard-handlers/is-in-app-scope.js.map +1 -0
  61. package/dist/esm/helpers/get-current-url.js +11 -0
  62. package/dist/esm/helpers/get-current-url.js.map +1 -0
  63. package/dist/esm/helpers/index.js +6 -0
  64. package/dist/esm/helpers/index.js.map +1 -0
  65. package/dist/esm/helpers/normalize-path-from-url.js +14 -0
  66. package/dist/esm/helpers/normalize-path-from-url.js.map +1 -0
  67. package/dist/esm/helpers/normalize-path.js +30 -0
  68. package/dist/esm/helpers/normalize-path.js.map +1 -0
  69. package/dist/esm/helpers/resolve-adapter.js +23 -0
  70. package/dist/esm/helpers/resolve-adapter.js.map +1 -0
  71. package/dist/esm/helpers/strip-query-params.js +14 -0
  72. package/dist/esm/helpers/strip-query-params.js.map +1 -0
  73. package/dist/esm/index.js +13 -0
  74. package/dist/esm/index.js.map +1 -0
  75. package/dist/esm/operators/active-app-navigation-events.js +52 -0
  76. package/dist/esm/operators/active-app-navigation-events.js.map +1 -0
  77. package/dist/esm/reconcile.js +76 -0
  78. package/dist/esm/reconcile.js.map +1 -0
  79. package/dist/esm/sources/app-first-source.js +41 -0
  80. package/dist/esm/sources/app-first-source.js.map +1 -0
  81. package/dist/esm/sources/context-first-source.js +47 -0
  82. package/dist/esm/sources/context-first-source.js.map +1 -0
  83. package/dist/esm/sources/index.js +4 -0
  84. package/dist/esm/sources/index.js.map +1 -0
  85. package/dist/esm/sources/types.js +16 -0
  86. package/dist/esm/sources/types.js.map +1 -0
  87. package/dist/esm/types.js +2 -0
  88. package/dist/esm/types.js.map +1 -0
  89. package/dist/esm/utils/has-custom-context-generators.js +14 -0
  90. package/dist/esm/utils/has-custom-context-generators.js.map +1 -0
  91. package/dist/esm/utils/legacy-app-navigation-fix.js +45 -0
  92. package/dist/esm/utils/legacy-app-navigation-fix.js.map +1 -0
  93. package/dist/esm/utils/resolve-context-from-url.js +37 -0
  94. package/dist/esm/utils/resolve-context-from-url.js.map +1 -0
  95. package/dist/esm/utils/url/build-app-route.js +20 -0
  96. package/dist/esm/utils/url/build-app-route.js.map +1 -0
  97. package/dist/esm/utils/url/build-context-url-for-strategy.js +43 -0
  98. package/dist/esm/utils/url/build-context-url-for-strategy.js.map +1 -0
  99. package/dist/esm/utils/url/index.js +7 -0
  100. package/dist/esm/utils/url/index.js.map +1 -0
  101. package/dist/esm/utils/url/parse-app-route.js +47 -0
  102. package/dist/esm/utils/url/parse-app-route.js.map +1 -0
  103. package/dist/esm/utils/url/resolve-context-id-from-url.js +29 -0
  104. package/dist/esm/utils/url/resolve-context-id-from-url.js.map +1 -0
  105. package/dist/esm/utils/url/strip-context-query-param.js +20 -0
  106. package/dist/esm/utils/url/strip-context-query-param.js.map +1 -0
  107. package/dist/esm/version.js +3 -0
  108. package/dist/esm/version.js.map +1 -0
  109. package/dist/tsconfig.tsbuildinfo +1 -0
  110. package/dist/types/ContextNavigationConfigurator.d.ts +125 -0
  111. package/dist/types/ContextNavigationConfigurator.d.ts.map +1 -0
  112. package/dist/types/__tests__/active-app-navigation-events.test.d.ts +2 -0
  113. package/dist/types/__tests__/active-app-navigation-events.test.d.ts.map +1 -0
  114. package/dist/types/__tests__/apply-navigation.test.d.ts +2 -0
  115. package/dist/types/__tests__/apply-navigation.test.d.ts.map +1 -0
  116. package/dist/types/__tests__/enable.test.d.ts +2 -0
  117. package/dist/types/__tests__/enable.test.d.ts.map +1 -0
  118. package/dist/types/__tests__/guard-handlers.test.d.ts +2 -0
  119. package/dist/types/__tests__/guard-handlers.test.d.ts.map +1 -0
  120. package/dist/types/__tests__/plugin.test.d.ts +2 -0
  121. package/dist/types/__tests__/plugin.test.d.ts.map +1 -0
  122. package/dist/types/__tests__/reconcile.test.d.ts +2 -0
  123. package/dist/types/__tests__/reconcile.test.d.ts.map +1 -0
  124. package/dist/types/adapters/create-path-adapter.d.ts +27 -0
  125. package/dist/types/adapters/create-path-adapter.d.ts.map +1 -0
  126. package/dist/types/adapters/create-query-adapter.d.ts +34 -0
  127. package/dist/types/adapters/create-query-adapter.d.ts.map +1 -0
  128. package/dist/types/adapters/custom-adapter/create-custom-adapter.d.ts +29 -0
  129. package/dist/types/adapters/custom-adapter/create-custom-adapter.d.ts.map +1 -0
  130. package/dist/types/adapters/custom-adapter/index.d.ts +5 -0
  131. package/dist/types/adapters/custom-adapter/index.d.ts.map +1 -0
  132. package/dist/types/adapters/custom-adapter/normalize-string-result.d.ts +21 -0
  133. package/dist/types/adapters/custom-adapter/normalize-string-result.d.ts.map +1 -0
  134. package/dist/types/adapters/custom-adapter/to-app-relative.d.ts +25 -0
  135. package/dist/types/adapters/custom-adapter/to-app-relative.d.ts.map +1 -0
  136. package/dist/types/adapters/custom-adapter/to-full-path.d.ts +22 -0
  137. package/dist/types/adapters/custom-adapter/to-full-path.d.ts.map +1 -0
  138. package/dist/types/adapters/index.d.ts +5 -0
  139. package/dist/types/adapters/index.d.ts.map +1 -0
  140. package/dist/types/adapters/types.d.ts +73 -0
  141. package/dist/types/adapters/types.d.ts.map +1 -0
  142. package/dist/types/apply-navigation.d.ts +88 -0
  143. package/dist/types/apply-navigation.d.ts.map +1 -0
  144. package/dist/types/constants/context-query-param-key.d.ts +8 -0
  145. package/dist/types/constants/context-query-param-key.d.ts.map +1 -0
  146. package/dist/types/constants/index.d.ts +3 -0
  147. package/dist/types/constants/index.d.ts.map +1 -0
  148. package/dist/types/constants/uuid-pattern.d.ts +8 -0
  149. package/dist/types/constants/uuid-pattern.d.ts.map +1 -0
  150. package/dist/types/create-context-navigation-plugin.d.ts +58 -0
  151. package/dist/types/create-context-navigation-plugin.d.ts.map +1 -0
  152. package/dist/types/enable-context-navigation.d.ts +21 -0
  153. package/dist/types/enable-context-navigation.d.ts.map +1 -0
  154. package/dist/types/events.d.ts +16 -0
  155. package/dist/types/events.d.ts.map +1 -0
  156. package/dist/types/guard-handlers/consume-own-nav-token.d.ts +21 -0
  157. package/dist/types/guard-handlers/consume-own-nav-token.d.ts.map +1 -0
  158. package/dist/types/guard-handlers/guard-tick-deps.d.ts +20 -0
  159. package/dist/types/guard-handlers/guard-tick-deps.d.ts.map +1 -0
  160. package/dist/types/guard-handlers/guard-tick-payload.d.ts +15 -0
  161. package/dist/types/guard-handlers/guard-tick-payload.d.ts.map +1 -0
  162. package/dist/types/guard-handlers/handle-push-mode-guard.d.ts +24 -0
  163. package/dist/types/guard-handlers/handle-push-mode-guard.d.ts.map +1 -0
  164. package/dist/types/guard-handlers/handle-replace-mode-guard.d.ts +19 -0
  165. package/dist/types/guard-handlers/handle-replace-mode-guard.d.ts.map +1 -0
  166. package/dist/types/guard-handlers/index.d.ts +7 -0
  167. package/dist/types/guard-handlers/index.d.ts.map +1 -0
  168. package/dist/types/guard-handlers/is-in-app-scope.d.ts +15 -0
  169. package/dist/types/guard-handlers/is-in-app-scope.d.ts.map +1 -0
  170. package/dist/types/helpers/get-current-url.d.ts +10 -0
  171. package/dist/types/helpers/get-current-url.d.ts.map +1 -0
  172. package/dist/types/helpers/index.d.ts +6 -0
  173. package/dist/types/helpers/index.d.ts.map +1 -0
  174. package/dist/types/helpers/normalize-path-from-url.d.ts +11 -0
  175. package/dist/types/helpers/normalize-path-from-url.d.ts.map +1 -0
  176. package/dist/types/helpers/normalize-path.d.ts +14 -0
  177. package/dist/types/helpers/normalize-path.d.ts.map +1 -0
  178. package/dist/types/helpers/resolve-adapter.d.ts +14 -0
  179. package/dist/types/helpers/resolve-adapter.d.ts.map +1 -0
  180. package/dist/types/helpers/strip-query-params.d.ts +12 -0
  181. package/dist/types/helpers/strip-query-params.d.ts.map +1 -0
  182. package/dist/types/index.d.ts +9 -0
  183. package/dist/types/index.d.ts.map +1 -0
  184. package/dist/types/operators/active-app-navigation-events.d.ts +47 -0
  185. package/dist/types/operators/active-app-navigation-events.d.ts.map +1 -0
  186. package/dist/types/reconcile.d.ts +43 -0
  187. package/dist/types/reconcile.d.ts.map +1 -0
  188. package/dist/types/sources/app-first-source.d.ts +14 -0
  189. package/dist/types/sources/app-first-source.d.ts.map +1 -0
  190. package/dist/types/sources/context-first-source.d.ts +15 -0
  191. package/dist/types/sources/context-first-source.d.ts.map +1 -0
  192. package/dist/types/sources/index.d.ts +4 -0
  193. package/dist/types/sources/index.d.ts.map +1 -0
  194. package/dist/types/sources/types.d.ts +61 -0
  195. package/dist/types/sources/types.d.ts.map +1 -0
  196. package/dist/types/types.d.ts +126 -0
  197. package/dist/types/types.d.ts.map +1 -0
  198. package/dist/types/utils/has-custom-context-generators.d.ts +13 -0
  199. package/dist/types/utils/has-custom-context-generators.d.ts.map +1 -0
  200. package/dist/types/utils/legacy-app-navigation-fix.d.ts +33 -0
  201. package/dist/types/utils/legacy-app-navigation-fix.d.ts.map +1 -0
  202. package/dist/types/utils/resolve-context-from-url.d.ts +20 -0
  203. package/dist/types/utils/resolve-context-from-url.d.ts.map +1 -0
  204. package/dist/types/utils/url/build-app-route.d.ts +11 -0
  205. package/dist/types/utils/url/build-app-route.d.ts.map +1 -0
  206. package/dist/types/utils/url/build-context-url-for-strategy.d.ts +14 -0
  207. package/dist/types/utils/url/build-context-url-for-strategy.d.ts.map +1 -0
  208. package/dist/types/utils/url/index.d.ts +8 -0
  209. package/dist/types/utils/url/index.d.ts.map +1 -0
  210. package/dist/types/utils/url/parse-app-route.d.ts +20 -0
  211. package/dist/types/utils/url/parse-app-route.d.ts.map +1 -0
  212. package/dist/types/utils/url/resolve-context-id-from-url.d.ts +8 -0
  213. package/dist/types/utils/url/resolve-context-id-from-url.d.ts.map +1 -0
  214. package/dist/types/utils/url/strip-context-query-param.d.ts +12 -0
  215. package/dist/types/utils/url/strip-context-query-param.d.ts.map +1 -0
  216. package/dist/types/version.d.ts +2 -0
  217. package/dist/types/version.d.ts.map +1 -0
  218. package/package.json +5 -5
@@ -0,0 +1,164 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { reconcile } from '../reconcile';
3
+ function makeContext(id) {
4
+ // Test double — only id and title are read by the code under test
5
+ return { id, title: `Context ${id}` };
6
+ }
7
+ function makeAdapter(overrides = {}) {
8
+ return {
9
+ id: 'test-adapter',
10
+ canHandle: () => true,
11
+ encode: ({ context, currentURL }) => {
12
+ // Guard — adapter cannot encode without a context item
13
+ if (!context)
14
+ return null;
15
+ return new URL(`/apps/my-app/${context.id}`, currentURL.origin);
16
+ },
17
+ decode: () => null,
18
+ ...overrides,
19
+ };
20
+ }
21
+ function makeDeps(overrides = {}) {
22
+ // Test doubles — only the methods exercised by reconcile are provided
23
+ return {
24
+ event: {
25
+ dispatchEvent: vi.fn(async () => ({ canceled: false })),
26
+ },
27
+ navigation: {
28
+ path: { pathname: '/apps/my-app', search: '' },
29
+ navigate: vi.fn(),
30
+ },
31
+ config: {
32
+ portalName: 'Test',
33
+ origin: 'https://example.com',
34
+ adapters: [makeAdapter()],
35
+ enableUrlGuard: false,
36
+ debug: false,
37
+ sourceFactory: () => ({ subscribe: vi.fn() }),
38
+ navigationOptions: { replace: true },
39
+ },
40
+ eventSource: { name: 'contextNavigation', version: '0.0.0' },
41
+ ownNavTokens: new Set(),
42
+ log: vi.fn(),
43
+ ...overrides,
44
+ };
45
+ }
46
+ describe('reconcile', () => {
47
+ // Test double — only the context property is accessed by the code under test
48
+ const appModules = {
49
+ context: { currentContext: null },
50
+ };
51
+ let deps;
52
+ beforeEach(() => {
53
+ deps = makeDeps();
54
+ });
55
+ it('dispatches no-context skip when contextState is undefined', () => {
56
+ const entry = { appKey: 'my-app', appModules, contextState: undefined };
57
+ reconcile(entry, deps);
58
+ expect(deps.event.dispatchEvent).toHaveBeenCalledWith('onContextNavigationSkipped', expect.objectContaining({ detail: { appKey: 'my-app', reason: 'no-context' } }));
59
+ });
60
+ it('navigates to nullContextUrl when contextState is null and config provides it', () => {
61
+ const nullContextUrl = vi.fn(() => '/apps/my-app');
62
+ deps = makeDeps();
63
+ deps.config = { ...deps.config, nullContextUrl };
64
+ Object.assign(deps.navigation, {
65
+ path: { pathname: '/apps/my-app/old-ctx', search: '' },
66
+ });
67
+ const entry = { appKey: 'my-app', appModules, contextState: null };
68
+ reconcile(entry, deps);
69
+ expect(nullContextUrl).toHaveBeenCalledWith(expect.objectContaining({ appKey: 'my-app' }));
70
+ expect(deps.navigation.navigate).toHaveBeenCalledWith(expect.objectContaining({ pathname: '/apps/my-app' }), expect.anything());
71
+ expect(deps.ownNavTokens.has('/apps/my-app')).toBe(true);
72
+ });
73
+ it('does not navigate when nullContextUrl produces the same path', () => {
74
+ const nullContextUrl = vi.fn(() => '/apps/my-app');
75
+ deps = makeDeps();
76
+ deps.config = { ...deps.config, nullContextUrl };
77
+ const entry = { appKey: 'my-app', appModules, contextState: null };
78
+ reconcile(entry, deps);
79
+ expect(deps.navigation.navigate).not.toHaveBeenCalled();
80
+ });
81
+ it('dispatches no-adapter skip when no adapter matches', () => {
82
+ const noMatchAdapter = makeAdapter({ canHandle: () => false });
83
+ deps = makeDeps();
84
+ deps.config = { ...deps.config, adapters: [noMatchAdapter] };
85
+ const entry = {
86
+ appKey: 'my-app',
87
+ appModules,
88
+ contextState: makeContext('ctx-1'),
89
+ };
90
+ reconcile(entry, deps);
91
+ expect(deps.event.dispatchEvent).toHaveBeenCalledWith('onContextNavigationSkipped', expect.objectContaining({ detail: { appKey: 'my-app', reason: 'no-adapter' } }));
92
+ });
93
+ it('dispatches adapter-resolved event and triggers navigation', async () => {
94
+ const entry = {
95
+ appKey: 'my-app',
96
+ appModules,
97
+ contextState: makeContext('ctx-1'),
98
+ };
99
+ reconcile(entry, deps);
100
+ await vi.waitFor(() => {
101
+ expect(deps.event.dispatchEvent).toHaveBeenCalledWith('onContextNavigationAdapterResolved', expect.objectContaining({ detail: { appKey: 'my-app', adapterId: 'test-adapter' } }));
102
+ expect(deps.navigation.navigate).toHaveBeenCalledWith(expect.objectContaining({ pathname: '/apps/my-app/ctx-1' }), { replace: true });
103
+ });
104
+ });
105
+ it('strips all query params on app switch', async () => {
106
+ // Adapter that carries currentURL.search through to its output
107
+ const adapter = makeAdapter({
108
+ encode: ({ context, currentURL }) => {
109
+ // Guard — adapter cannot encode without a context item
110
+ if (!context)
111
+ return null;
112
+ const url = new URL(`/apps/new-app/${context.id}`, currentURL.origin);
113
+ url.search = currentURL.search;
114
+ return url;
115
+ },
116
+ });
117
+ deps = makeDeps();
118
+ deps.config = { ...deps.config, adapters: [adapter] };
119
+ Object.assign(deps.navigation, {
120
+ path: { pathname: '/apps/old-app/ctx-1', search: '?tab=settings&$contextId=ctx-1' },
121
+ });
122
+ const entry = {
123
+ appKey: 'new-app',
124
+ appModules,
125
+ contextState: makeContext('ctx-2'),
126
+ };
127
+ reconcile(entry, deps, { isAppSwitch: true });
128
+ await vi.waitFor(() => {
129
+ const navigatedURL = vi.mocked(deps.navigation.navigate).mock.calls[0]?.[0];
130
+ // All query params from the previous app should be gone
131
+ expect(navigatedURL.search).toBe('');
132
+ });
133
+ });
134
+ it('preserves query params on context change within the same app', async () => {
135
+ const adapter = makeAdapter({
136
+ encode: ({ context, currentURL }) => {
137
+ // Guard — adapter cannot encode without a context item
138
+ if (!context)
139
+ return null;
140
+ const url = new URL(`/apps/my-app/${context.id}`, currentURL.origin);
141
+ url.search = currentURL.search;
142
+ return url;
143
+ },
144
+ });
145
+ deps = makeDeps();
146
+ deps.config = { ...deps.config, adapters: [adapter] };
147
+ Object.assign(deps.navigation, {
148
+ path: { pathname: '/apps/my-app/ctx-1', search: '?tab=settings' },
149
+ });
150
+ const entry = {
151
+ appKey: 'my-app',
152
+ appModules,
153
+ contextState: makeContext('ctx-2'),
154
+ };
155
+ // Context change within the same app — query params should survive
156
+ reconcile(entry, deps);
157
+ await vi.waitFor(() => {
158
+ const navigatedURL = vi.mocked(deps.navigation.navigate).mock.calls[0]?.[0];
159
+ // App-specific param should survive on context change
160
+ expect(navigatedURL.searchParams.get('tab')).toBe('settings');
161
+ });
162
+ });
163
+ });
164
+ //# sourceMappingURL=reconcile.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.test.js","sourceRoot":"","sources":["../../../src/__tests__/reconcile.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { hasCustomContextGenerators } from '../utils/has-custom-context-generators';
2
+ import { stripContextQueryParam } from '../utils/url/strip-context-query-param';
3
+ import { parseAppRoute } from '../utils/url/parse-app-route';
4
+ import { UUID_PATTERN } from '../constants';
5
+ import { buildAppRoute } from '../utils/url/build-app-route';
6
+ /**
7
+ * Path adapter — encodes context identity as the first path segment after
8
+ * the app basename.
9
+ *
10
+ * **Intent:** This is the legacy/default strategy for Fusion apps. It places
11
+ * the context UUID immediately after `/apps/{appKey}/` as a path segment,
12
+ * making context visible in the URL structure. This convention predates the
13
+ * query strategy and remains the fallback for apps that don't declare a
14
+ * routing strategy.
15
+ *
16
+ * **URL shape:** `/apps/{appKey}/{contextId}/...`
17
+ *
18
+ * **Selection logic:**
19
+ * 1. Immediately bails if the app has custom generators registered
20
+ * (those apps are owned by the custom adapter).
21
+ * 2. Matches when `routingStrategy === 'path'` (explicit opt-in).
22
+ * 3. Matches when no strategy is declared (default fallback).
23
+ *
24
+ * **Context detection:** Uses `parseAppRoute` (URLPattern-based) to parse
25
+ * the path into named segments, and UUID pattern matching to distinguish
26
+ * context ids from route names.
27
+ *
28
+ * @returns A static adapter object
29
+ */
30
+ export function createPathAdapter() {
31
+ return {
32
+ id: 'path',
33
+ /**
34
+ * Self-selection predicate.
35
+ *
36
+ * Rejects apps with custom generators (they belong to the custom adapter).
37
+ * Accepts apps with explicit `'path'` strategy or no declared strategy
38
+ * (the path adapter serves as the system-wide default fallback).
39
+ */
40
+ canHandle({ appContext, routingStrategy, currentURL }) {
41
+ // Custom generators mean the app owns its URL shape — the custom adapter handles it, not us
42
+ if (hasCustomContextGenerators(appContext)) {
43
+ return false;
44
+ }
45
+ // Not an app route (e.g. portal chrome) — nothing for this adapter to encode context into
46
+ if (!parseAppRoute(currentURL.pathname)) {
47
+ return false;
48
+ }
49
+ const declared = routingStrategy;
50
+ // App explicitly opted into path-segment routing — take ownership
51
+ if (declared === 'path') {
52
+ return true;
53
+ }
54
+ // No strategy declared — path adapter is the system-wide default for legacy apps
55
+ if (declared === undefined || declared === null) {
56
+ return true;
57
+ }
58
+ return false;
59
+ },
60
+ /**
61
+ * Encode context into the URL as a path segment.
62
+ *
63
+ * - **Null context:** removes the context segment to produce a bare app route.
64
+ * - **Active context:** places/replaces the context id as the segment after the app key.
65
+ *
66
+ * Sub-routes after the context segment are intentionally dropped — a context
67
+ * change resets the app to its root view to avoid landing in an invalid state.
68
+ */
69
+ encode({ context, currentURL }) {
70
+ const match = parseAppRoute(currentURL.pathname);
71
+ // Pathname doesn't match the /apps/{key}/... shape — not a Fusion app route, bail out
72
+ if (!match)
73
+ return null;
74
+ const targetPath = context === null ? buildAppRoute(match.appKey) : buildAppRoute(match.appKey, context.id);
75
+ const url = new URL(targetPath, currentURL.origin);
76
+ url.search = currentURL.search;
77
+ stripContextQueryParam(url);
78
+ // Hash is intentionally not preserved — context changes reset app to root view
79
+ return url;
80
+ },
81
+ /**
82
+ * Extract context id from the path segment after the app key, if it matches a UUID.
83
+ *
84
+ * Returns `null` for non-UUID segments (route names, missing segments).
85
+ */
86
+ decode(url) {
87
+ const match = parseAppRoute(url.pathname);
88
+ // Only treat the segment as a context id if it's a valid UUID — route names can occupy the same slot
89
+ if (match?.contextId && UUID_PATTERN.test(match.contextId)) {
90
+ return match.contextId;
91
+ }
92
+ return null;
93
+ },
94
+ };
95
+ }
96
+ //# sourceMappingURL=create-path-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-path-adapter.js","sourceRoot":"","sources":["../../../src/adapters/create-path-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,EAAE,EAAE,MAAM;QAEV;;;;;;WAMG;QACH,SAAS,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAA4B;YAC7E,4FAA4F;YAC5F,IAAI,0BAA0B,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3C,OAAO,KAAK,CAAC;YACf,CAAC;YAED,0FAA0F;YAC1F,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,QAAQ,GAAG,eAAe,CAAC;YACjC,kEAAkE;YAClE,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,iFAAiF;YACjF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAChD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAED;;;;;;;;WAQG;QACH,MAAM,CAAC,EAAE,OAAO,EAAE,UAAU,EAAoD;YAC9E,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACjD,sFAAsF;YACtF,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YAExB,MAAM,UAAU,GACd,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAE3F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;YACnD,GAAG,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;YAC/B,sBAAsB,CAAC,GAAG,CAAC,CAAC;YAC5B,+EAA+E;YAC/E,OAAO,GAAG,CAAC;QACb,CAAC;QAED;;;;WAIG;QACH,MAAM,CAAC,GAAQ;YACb,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,qGAAqG;YACrG,IAAI,KAAK,EAAE,SAAS,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3D,OAAO,KAAK,CAAC,SAAS,CAAC;YACzB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { CONTEXT_QUERY_PARAM_KEY } from '../constants';
2
+ /**
3
+ * Query adapter — encodes context identity as a URL query parameter.
4
+ *
5
+ * **Intent:** This is the preferred strategy for new apps. It keeps the
6
+ * pathname clean for app routing while storing context in a predictable
7
+ * query param (`?$contextId={uuid}`). This avoids conflicts with
8
+ * React Router path segments and makes deep-links copy-pasteable without
9
+ * affecting route matching.
10
+ *
11
+ * **URL shape:** `/apps/{appKey}/route?$contextId={id}`
12
+ *
13
+ * **Selection:** Matches only when the app explicitly declares
14
+ * `routingStrategy: 'query'` on its context provider. Does not
15
+ * fall through as a default — that role belongs to the path adapter.
16
+ *
17
+ * **Query string handling:** Clones the full current URL (`currentURL.href`)
18
+ * so all existing query parameters are preserved. Only the context param
19
+ * is added/removed/replaced.
20
+ *
21
+ * @param paramName - Query parameter name to use (default `$contextId`)
22
+ * @returns A static adapter object (not a factory — no runtime binding needed)
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * // Default param name
27
+ * const adapter = createQueryAdapter();
28
+ *
29
+ * // Custom param name for portal-specific needs
30
+ * const adapter = createQueryAdapter('contextId');
31
+ * ```
32
+ */
33
+ export function createQueryAdapter(paramName = CONTEXT_QUERY_PARAM_KEY) {
34
+ return {
35
+ id: 'query',
36
+ /**
37
+ * Matches apps that explicitly opted into query-parameter context routing.
38
+ *
39
+ * Only returns `true` when `routingStrategy === 'query'` — there is no
40
+ * implicit fallback. Apps without a declared strategy use the path adapter.
41
+ */
42
+ canHandle({ routingStrategy }) {
43
+ return routingStrategy === 'query';
44
+ },
45
+ /**
46
+ * Encode context into the URL's query string.
47
+ *
48
+ * - **Null context:** removes the context param (clears deep-link).
49
+ * - **Active context:** sets the param to the context id.
50
+ *
51
+ * After mutation, the `$` character is restored from `%24` encoding
52
+ * because `URLSearchParams` percent-encodes `$` but we want it
53
+ * human-readable in the address bar as a namespace marker.
54
+ *
55
+ * Hash fragment is intentionally cleared — context changes reset the app
56
+ * to its root view, so any hash pointing to sub-route sections would be invalid.
57
+ */
58
+ encode({ context, currentURL }) {
59
+ const url = new URL(currentURL.href);
60
+ // Null context means the user deselected context — remove the param to produce a clean URL
61
+ if (context === null) {
62
+ url.searchParams.delete(paramName);
63
+ }
64
+ else {
65
+ url.searchParams.set(paramName, context.id);
66
+ }
67
+ // Restore $ from %24 — $ is a reserved namespace prefix we want visible in URLs
68
+ url.search = url.search.replace(/%24/gi, '$');
69
+ // Clear hash — context change resets app to root view
70
+ url.hash = '';
71
+ return url;
72
+ },
73
+ /**
74
+ * Extract the context id from the query parameter.
75
+ *
76
+ * @returns The context id string, or `null` if the param is absent.
77
+ */
78
+ decode(url) {
79
+ return url.searchParams.get(paramName) ?? null;
80
+ },
81
+ };
82
+ }
83
+ //# sourceMappingURL=create-query-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-query-adapter.js","sourceRoot":"","sources":["../../../src/adapters/create-query-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAS,GAAG,uBAAuB;IACpE,OAAO;QACL,EAAE,EAAE,OAAO;QAEX;;;;;WAKG;QACH,SAAS,CAAC,EAAE,eAAe,EAA4B;YACrD,OAAO,eAAe,KAAK,OAAO,CAAC;QACrC,CAAC;QAED;;;;;;;;;;;;WAYG;QACH,MAAM,CAAC,EAAE,OAAO,EAAE,UAAU,EAAoD;YAC9E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAErC,2FAA2F;YAC3F,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9C,CAAC;YAED,gFAAgF;YAChF,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAE9C,sDAAsD;YACtD,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;YAEd,OAAO,GAAG,CAAC;QACb,CAAC;QAED;;;;WAIG;QACH,MAAM,CAAC,GAAQ;YACb,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { hasCustomContextGenerators } from '../../utils/has-custom-context-generators';
2
+ import { stripContextQueryParam } from '../../utils/url/strip-context-query-param';
3
+ import { normalizeStringResult } from './normalize-string-result';
4
+ import { toAppRelative } from './to-app-relative';
5
+ import { toFullPath } from './to-full-path';
6
+ /**
7
+ * Custom adapter factory — delegates URL encoding/decoding to app-provided hooks.
8
+ *
9
+ * **Intent:** Some apps define their own URL shape for context (e.g.
10
+ * `/route-a/{contextId}` instead of the standard `/{contextId}/route-a`).
11
+ * These apps register `extractContextIdFromPath` and `generatePathFromContext`
12
+ * on their context provider. This adapter bridges those app hooks into the
13
+ * navigation handler's adapter contract so the reconciler can drive navigation
14
+ * without knowing the app's specific URL layout.
15
+ *
16
+ * **Selection:** The factory returns a bound adapter only when the app has
17
+ * both generator hooks registered (checked via {@link hasCustomContextGenerators}).
18
+ * Otherwise it returns `null`, letting lower-priority adapters (query, path) match.
19
+ *
20
+ * **Coordinate system:** All app hooks receive/return app-relative paths.
21
+ * The adapter handles stripping and prepending the `/apps/{appKey}` prefix
22
+ * transparently via {@link toAppRelative} and {@link toFullPath}.
23
+ *
24
+ * **Query string preservation:** The adapter always carries forward
25
+ * `currentURL.search` to the output URL, ensuring query parameters
26
+ * (e.g. `?routingStrategy=custom`) survive navigation.
27
+ *
28
+ * @returns A {@link ContextNavigationAdapterFactory} that produces a custom adapter when the
29
+ * app context exposes both `extractContextIdFromPath` and `generatePathFromContext`,
30
+ * or `null` to fall through to the next adapter in the resolution chain.
31
+ */
32
+ export function createCustomAdapter() {
33
+ return ({ appContext, appKey }) => {
34
+ // This app hasn't registered custom context hooks — let a lower-priority adapter handle it
35
+ if (!hasCustomContextGenerators(appContext)) {
36
+ return null;
37
+ }
38
+ const appBasename = `/apps/${appKey}`;
39
+ const rawExtract = appContext.extractContextIdFromPath;
40
+ const rawGenerate = appContext.generatePathFromContext;
41
+ // Both hooks must be present; if one is missing the custom URL contract can't be fulfilled
42
+ if (!rawExtract || !rawGenerate) {
43
+ return null;
44
+ }
45
+ // Capture narrowed references — TypeScript can't narrow across the closure boundary
46
+ const extract = rawExtract;
47
+ const generate = rawGenerate;
48
+ return {
49
+ id: 'custom',
50
+ /** Always true — selection already happened in the factory guard above. */
51
+ canHandle() {
52
+ return true;
53
+ },
54
+ /**
55
+ * Encode a context into the URL using the app's path generator.
56
+ *
57
+ * - **Null context:** navigates to the app root (clears context from URL).
58
+ * - **Existing context in URL:** replaces it with the new context id,
59
+ * preferring the app generator's output, falling back to string replacement.
60
+ * - **No existing context:** delegates entirely to the app generator.
61
+ *
62
+ * Returns `null` when the generator cannot produce a path (signals the
63
+ * reconciler to skip navigation).
64
+ */
65
+ encode({ context, currentURL, }) {
66
+ // Null context means the user deselected context — navigate to the app root
67
+ if (context === null) {
68
+ const url = new URL(appBasename, currentURL.origin);
69
+ url.search = currentURL.search;
70
+ // Remove query-adapter param — custom apps encode context in the path
71
+ stripContextQueryParam(url);
72
+ // Hash is intentionally not preserved — returning to root app view
73
+ return url;
74
+ }
75
+ const appRelativePath = toAppRelative(currentURL.pathname, appBasename);
76
+ const existingContextId = normalizeStringResult(extract(appRelativePath)) ?? undefined;
77
+ let generatedPath;
78
+ // Context already lives in the URL — prefer the generator's output, but substitute the
79
+ // id directly as a last resort to avoid a no-op navigation
80
+ if (existingContextId) {
81
+ // Context already embedded in the URL — let the generator rewrite it, or fall back to
82
+ // a simple string replacement of the old id with the new one
83
+ generatedPath =
84
+ normalizeStringResult(generate(context, appRelativePath)) ??
85
+ appRelativePath.replace(existingContextId, context.id);
86
+ }
87
+ else {
88
+ // No context in the current URL — ask the generator where to place the new context id
89
+ generatedPath = normalizeStringResult(generate(context, appRelativePath));
90
+ }
91
+ // Generator returned nothing — can't produce a valid URL; skip navigation
92
+ if (!generatedPath) {
93
+ return null;
94
+ }
95
+ const fullPath = toFullPath(generatedPath, appBasename);
96
+ const url = new URL(fullPath, currentURL.origin);
97
+ url.search = currentURL.search;
98
+ // Remove query-adapter param — custom apps encode context in the path
99
+ stripContextQueryParam(url);
100
+ // Hash is intentionally not preserved — context changes reset app to root view
101
+ return url;
102
+ },
103
+ /**
104
+ * Decode a context id from the URL using the app's path extractor.
105
+ *
106
+ * Converts the browser URL to an app-relative path, then delegates
107
+ * to the app's extract hook. Returns `null` when no context is present.
108
+ */
109
+ decode(url) {
110
+ const appRelativePath = toAppRelative(url.pathname, appBasename);
111
+ return normalizeStringResult(extract(appRelativePath)) ?? null;
112
+ },
113
+ };
114
+ };
115
+ }
116
+ //# sourceMappingURL=create-custom-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-custom-adapter.js","sourceRoot":"","sources":["../../../../src/adapters/custom-adapter/create-custom-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { createCustomAdapter } from './create-custom-adapter';
2
+ export { normalizeStringResult } from './normalize-string-result';
3
+ export { toAppRelative } from './to-app-relative';
4
+ export { toFullPath } from './to-full-path';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/custom-adapter/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Normalize legacy app generator outputs to a plain string.
3
+ *
4
+ * Legacy apps may return their path values as either a bare string or
5
+ * wrapped in an array (e.g. `['path']` or `[]`). This function unifies
6
+ * both shapes into `string | undefined` so downstream code doesn't need
7
+ * to branch on format.
8
+ *
9
+ * @param value - Raw return value from an app generator hook
10
+ * @returns The resolved string, or `undefined` if the value is empty/invalid
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * normalizeStringResult('/foo/bar'); // '/foo/bar'
15
+ * normalizeStringResult(['/foo/bar']); // '/foo/bar'
16
+ * normalizeStringResult([]); // undefined
17
+ * normalizeStringResult(''); // undefined
18
+ * ```
19
+ */
20
+ export function normalizeStringResult(value) {
21
+ // A non-empty string can be returned directly — the most common case for modern apps
22
+ if (typeof value === 'string' && value.length > 0) {
23
+ return value;
24
+ }
25
+ // Legacy apps may wrap their return value in an array; unwrap the first element if present
26
+ if (Array.isArray(value)) {
27
+ const first = value[0];
28
+ // Non-empty string at index 0 is the only valid array payload
29
+ if (typeof first === 'string' && first.length > 0) {
30
+ return first;
31
+ }
32
+ // Array was empty or held a non-string — treat as no result
33
+ return undefined;
34
+ }
35
+ return undefined;
36
+ }
37
+ //# sourceMappingURL=normalize-string-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-string-result.js","sourceRoot":"","sources":["../../../../src/adapters/custom-adapter/normalize-string-result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,qFAAqF;IACrF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2FAA2F;IAC3F,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,8DAA8D;QAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,4DAA4D;QAC5D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Strips the app basename prefix from a full pathname to produce an
3
+ * app-relative path.
4
+ *
5
+ * App-provided hooks (`extractContextIdFromPath`, `generatePathFromContext`)
6
+ * operate on app-relative paths — they don't know about the portal's
7
+ * `/apps/{appKey}` prefix. This function converts a browser-absolute
8
+ * pathname into the app's local coordinate system before calling those hooks.
9
+ *
10
+ * Always returns a path starting with `/` so app hooks receive consistent input.
11
+ *
12
+ * @param fullPathname - Absolute browser pathname (e.g. `/apps/my-app/route-a`)
13
+ * @param appBasename - The app's base path (e.g. `/apps/my-app`)
14
+ * @returns App-relative path (e.g. `/route-a`), or the input unchanged if
15
+ * the basename doesn't match (defensive fallback)
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * toAppRelative('/apps/my-app/route-a/ctx', '/apps/my-app'); // '/route-a/ctx'
20
+ * toAppRelative('/apps/my-app', '/apps/my-app'); // '/'
21
+ * toAppRelative('/other/path', '/apps/my-app'); // '/other/path'
22
+ * ```
23
+ */
24
+ export function toAppRelative(fullPathname, appBasename) {
25
+ // Basename matches the pathname — the app is at its root, return '/' as the relative path
26
+ if (fullPathname === appBasename || fullPathname.startsWith(`${appBasename}/`)) {
27
+ const relative = fullPathname.slice(appBasename.length);
28
+ // Ensure the relative path always starts with '/' for consistent input to app hooks
29
+ return relative.startsWith('/') ? relative : `/${relative}`;
30
+ }
31
+ // Basename not found in pathname — return as-is; the app hook will see the full path
32
+ return fullPathname;
33
+ }
34
+ //# sourceMappingURL=to-app-relative.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-app-relative.js","sourceRoot":"","sources":["../../../../src/adapters/custom-adapter/to-app-relative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,YAAoB,EAAE,WAAmB;IACrE,0FAA0F;IAC1F,IAAI,YAAY,KAAK,WAAW,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;QAC/E,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACxD,oFAAoF;QACpF,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;IAC9D,CAAC;IACD,qFAAqF;IACrF,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Prepends the app basename to an app-relative path to produce a full
3
+ * browser-absolute pathname.
4
+ *
5
+ * Inverse of {@link toAppRelative}. After an app hook generates a new
6
+ * app-relative path (with context encoded), this function converts it
7
+ * back into a full pathname suitable for browser navigation.
8
+ *
9
+ * Handles edge cases where either side may or may not have a leading/trailing slash.
10
+ *
11
+ * @param appRelativePath - App-relative path (e.g. `/route-a/ctx-id`)
12
+ * @param appBasename - The app's base path (e.g. `/apps/my-app`)
13
+ * @returns Full browser pathname (e.g. `/apps/my-app/route-a/ctx-id`)
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * toFullPath('/route-a/ctx-id', '/apps/my-app'); // '/apps/my-app/route-a/ctx-id'
18
+ * toFullPath('route-a/ctx-id', '/apps/my-app/'); // '/apps/my-app/route-a/ctx-id'
19
+ * ```
20
+ */
21
+ export function toFullPath(appRelativePath, appBasename) {
22
+ // Strip trailing slash from base so we can unconditionally prepend a leading slash from rel
23
+ const base = appBasename.endsWith('/') ? appBasename.slice(0, -1) : appBasename;
24
+ // Ensure rel always starts with '/' before concatenation to avoid double- or missing-slash
25
+ const rel = appRelativePath.startsWith('/') ? appRelativePath : `/${appRelativePath}`;
26
+ return `${base}${rel}`;
27
+ }
28
+ //# sourceMappingURL=to-full-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-full-path.js","sourceRoot":"","sources":["../../../../src/adapters/custom-adapter/to-full-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,eAAuB,EAAE,WAAmB;IACrE,4FAA4F;IAC5F,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAChF,2FAA2F;IAC3F,MAAM,GAAG,GAAG,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;IACtF,OAAO,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { createPathAdapter } from './create-path-adapter';
2
+ export { createQueryAdapter } from './create-query-adapter';
3
+ export { createCustomAdapter } from './custom-adapter';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":""}