@equinor/fusion-framework-module-context 9.0.0-next.0 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/esm/version.js +1 -1
  2. package/dist/esm/version.js.map +1 -1
  3. package/dist/tsconfig.tsbuildinfo +1 -1
  4. package/dist/types/version.d.ts +1 -1
  5. package/package.json +13 -10
  6. package/CHANGELOG.md +0 -1095
  7. package/docs/data-model.md +0 -134
  8. package/docs/lifecycle.md +0 -163
  9. package/docs/recipes.md +0 -89
  10. package/src/ContextModuleConfig.ts +0 -147
  11. package/src/ContextModuleConfigurator.interface.ts +0 -145
  12. package/src/ContextModuleConfigurator.ts +0 -295
  13. package/src/ContextProvider.ts +0 -1158
  14. package/src/__tests__/ContextModuleConfigurator.test.ts +0 -412
  15. package/src/__tests__/mock/context-mock.test.ts +0 -137
  16. package/src/__tests__/mock/create-context-item-factory.test.ts +0 -60
  17. package/src/__tests__/mock/create-context-items.test.ts +0 -58
  18. package/src/client/ContextClient.ts +0 -149
  19. package/src/errors/FusionContextSearchError.ts +0 -56
  20. package/src/errors/index.ts +0 -1
  21. package/src/index.ts +0 -29
  22. package/src/mock/ContextMockConfigurator.ts +0 -244
  23. package/src/mock/fixtures/create-context-item-factory.ts +0 -62
  24. package/src/mock/fixtures/create-context-items.ts +0 -80
  25. package/src/mock/fixtures/index.ts +0 -28
  26. package/src/mock/fixtures/string-to-seed.ts +0 -18
  27. package/src/mock/index.ts +0 -33
  28. package/src/mock/module.ts +0 -54
  29. package/src/module.ts +0 -178
  30. package/src/selectors/get-context-selector.ts +0 -14
  31. package/src/selectors/index.ts +0 -12
  32. package/src/selectors/query-context-selector.ts +0 -15
  33. package/src/selectors/related-context-selector.ts +0 -15
  34. package/src/types.ts +0 -98
  35. package/src/utils/enable-context.ts +0 -40
  36. package/src/utils/extract-context-id-from-path.ts +0 -39
  37. package/src/utils/index.ts +0 -15
  38. package/src/utils/parse-context-item.ts +0 -39
  39. package/src/utils/resolve-context-from-path.ts +0 -118
  40. package/src/utils/resolve-initial-context.ts +0 -58
  41. package/src/version.ts +0 -2
  42. package/tsconfig.json +0 -33
  43. package/vitest.config.ts +0 -11
@@ -1,295 +0,0 @@
1
- import { from, lastValueFrom } from 'rxjs';
2
-
3
- import {
4
- BaseConfigBuilder,
5
- type ModuleInitializerArgs,
6
- type ModulesInstanceType,
7
- type Modules,
8
- type ModuleType,
9
- } from '@equinor/fusion-framework-module';
10
- import type { ServicesModule, IApiProvider } from '@equinor/fusion-framework-module-services';
11
- import type { NavigationModule } from '@equinor/fusion-framework-module-navigation';
12
- import { getContextSelector, queryContextSelector, relatedContextSelector } from './selectors';
13
- import type { QueryCtorOptions, QueryFn } from '@equinor/fusion-query';
14
- import type { ContextItem, QueryContextParameters, RelatedContextParameters } from './types';
15
- import type { GetContextParameters } from './client/ContextClient';
16
- import resolveInitialContext from './utils/resolve-initial-context';
17
- import type { ContextModuleConfig } from './ContextModuleConfig';
18
- import type {
19
- ContextConfigBuilderCallback,
20
- IContextModuleConfigurator,
21
- } from './ContextModuleConfigurator.interface';
22
-
23
- export type { ContextModuleConfig } from './ContextModuleConfig';
24
- export type {
25
- ContextConfigBuilderCallback,
26
- IContextModuleConfigurator,
27
- } from './ContextModuleConfigurator.interface';
28
-
29
- /**
30
- * Default implementation of {@link IContextModuleConfigurator}.
31
- *
32
- * Collects {@link ContextConfigBuilderCallback} registrations and, when
33
- * {@link createConfigAsync} is called, runs them in order — each callback
34
- * receives this configurator itself and populates the config through its
35
- * setter methods, which register into {@link BaseConfigBuilder._set} — to
36
- * produce the final {@link ContextModuleConfig}.
37
- *
38
- * If no custom client is configured, the configurator falls back to
39
- * creating one from the {@link ServicesModule} API provider.
40
- *
41
- * @remarks
42
- * Extends {@link BaseConfigBuilder} and fully reuses its `_set`/`_buildConfig`
43
- * machinery. Setters always pass an `async () => value` callback to `_set`,
44
- * never the raw value directly — `_set` decides whether it received a value
45
- * or a deferred callback by checking `typeof value_or_cb === 'function'`, so
46
- * fields that are themselves functions (e.g. `validateContext`) would
47
- * otherwise be misread as callbacks and invoked instead of stored.
48
- */
49
- export class ContextModuleConfigurator
50
- extends BaseConfigBuilder<ContextModuleConfig>
51
- implements IContextModuleConfigurator
52
- {
53
- /** Default cache TTL (in ms) for context query results. */
54
- defaultExpireTime = 1 * 60 * 1000;
55
-
56
- #configBuilders: Array<ContextConfigBuilderCallback> = [];
57
- #init?: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule, NavigationModule]>;
58
-
59
- /** @inheritdoc */
60
- addConfigBuilder(init: ContextConfigBuilderCallback): void {
61
- this.#configBuilders.push(init);
62
- }
63
-
64
- /** @inheritdoc */
65
- requireInstance<TKey extends string = Extract<keyof Modules, string>>(
66
- module: TKey,
67
- ): Promise<ModuleType<Modules[TKey]>>;
68
- /** @inheritdoc */
69
- requireInstance<T>(module: string): Promise<T>;
70
- /** @inheritdoc */
71
- requireInstance(
72
- module: string,
73
- // biome-ignore lint/suspicious/noExplicitAny: implementation signature must satisfy both overloads above (`Promise<ModuleType<...>>` and `Promise<T>`); `unknown` is not assignable to the generic `Promise<T>` overload
74
- ): Promise<any> {
75
- // requireInstance is only meaningful once module initialization has begun and #init is set
76
- if (!this.#init) {
77
- throw Error('requireInstance can only be called during module configuration');
78
- }
79
- // #init's requireInstance is narrowed to this module's own declared deps; widen for the public any-module overload above
80
- return this.#init.requireInstance(module as never);
81
- }
82
-
83
- /** @inheritdoc */
84
- setContextType(type: ContextModuleConfig['contextType']): void {
85
- this._set('contextType', async () => type);
86
- }
87
-
88
- /** @inheritdoc */
89
- setContextFilter(filter: ContextModuleConfig['contextFilter']): void {
90
- this._set('contextFilter', async () => filter);
91
- }
92
-
93
- /** @inheritdoc */
94
- connectParentContext(connect: ContextModuleConfig['connectParentContext']): void {
95
- this._set('connectParentContext', async () => connect);
96
- }
97
-
98
- /** @inheritdoc */
99
- setContextParameterFn(fn: ContextModuleConfig['contextParameterFn']): void {
100
- this._set('contextParameterFn', async () => fn);
101
- }
102
-
103
- /** @inheritdoc */
104
- setValidateContext(fn: ContextModuleConfig['validateContext']): void {
105
- this._set('validateContext', async () => fn);
106
- }
107
-
108
- /** @inheritdoc */
109
- setResolveContext(fn: ContextModuleConfig['resolveContext']): void {
110
- this._set('resolveContext', async () => fn);
111
- }
112
-
113
- /** @inheritdoc */
114
- setContextPathExtractor(fn: ContextModuleConfig['extractContextIdFromPath']): void {
115
- this._set('extractContextIdFromPath', async () => fn);
116
- }
117
-
118
- /** @inheritdoc */
119
- setContextPathGenerator(fn: ContextModuleConfig['generatePathFromContext']): void {
120
- this._set('generatePathFromContext', async () => fn);
121
- }
122
-
123
- /** @inheritdoc */
124
- setResolveInitialContext(fn: ContextModuleConfig['resolveInitialContext']): void {
125
- this._set('resolveInitialContext', async () => fn);
126
- }
127
-
128
- /** @inheritdoc */
129
- setContextClient(
130
- client: {
131
- get:
132
- | QueryFn<ContextItem, GetContextParameters>
133
- | QueryCtorOptions<ContextItem, GetContextParameters>;
134
- query:
135
- | QueryFn<ContextItem[], QueryContextParameters>
136
- | QueryCtorOptions<ContextItem[], QueryContextParameters>;
137
- related?:
138
- | QueryFn<ContextItem[], RelatedContextParameters>
139
- | QueryCtorOptions<ContextItem[], RelatedContextParameters>;
140
- },
141
- expire = 1 * 60 * 1000,
142
- ): void {
143
- const clientConfig: ContextModuleConfig['client'] = {
144
- get:
145
- typeof client.get === 'function'
146
- ? {
147
- key: ({ id }) => id,
148
- client: {
149
- fn: client.get,
150
- },
151
- expire,
152
- }
153
- : client.get,
154
- query:
155
- typeof client.query === 'function'
156
- ? {
157
- // TODO(#5118) - might cast to checksum
158
- key: (args) => JSON.stringify(args),
159
- client: {
160
- fn: client.query,
161
- },
162
- expire,
163
- }
164
- : client.query,
165
- };
166
- // only override the related-context client config if one was provided
167
- if (client.related) {
168
- clientConfig.related =
169
- typeof client.related === 'function'
170
- ? {
171
- // TODO(#5118) - might cast to checksum
172
- key: (args) => JSON.stringify(args),
173
- client: {
174
- fn: client.related,
175
- },
176
- expire,
177
- }
178
- : client.related;
179
- }
180
- this._set('client', async () => clientConfig);
181
- }
182
-
183
- /**
184
- * Resolves the services API provider, preferring the local module
185
- * instance and falling back to the parent module.
186
- *
187
- * @param init - Module initializer arguments.
188
- * @returns The resolved API provider.
189
- * @throws Error if no services module is available.
190
- */
191
- protected async _getServiceProvider(
192
- init: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule]>,
193
- ): Promise<IApiProvider> {
194
- // prefer the local services module instance if available
195
- if (init.hasModule('services')) {
196
- return init.requireInstance('services');
197
- }
198
- const parentServiceModule = (init.ref as ModulesInstanceType<[ServicesModule]>)?.services;
199
- // fall back to the parent module's services instance
200
- if (!parentServiceModule) {
201
- throw Error('no service services provider configures [ServicesModule]');
202
- }
203
- return parentServiceModule;
204
- }
205
-
206
- /**
207
- * Runs all registered config builders, then resolves the accumulated
208
- * `_set` registrations into the final {@link ContextModuleConfig}.
209
- *
210
- * @param init - Module initializer arguments including dependency instances.
211
- * @param initial - Optional partial config inherited from a parent module.
212
- * @returns The fully resolved context module configuration.
213
- */
214
- protected async _createConfig(
215
- init: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule, NavigationModule]>,
216
- initial?: Partial<ContextModuleConfig>,
217
- ): Promise<ContextModuleConfig> {
218
- // requireInstance resolves lazily against this init for the remainder of config building
219
- this.#init = init;
220
-
221
- // run each registered config builder in sequence; each calls setXxx(), registering into _set
222
- await this.#configBuilders.reduce((prev, cb) => prev.then(() => cb(this)), Promise.resolve());
223
-
224
- // resolve every registered _set callback into the actual config object
225
- const config = await lastValueFrom(from(this._buildConfig(init, initial)));
226
-
227
- // route through _processConfig, so a subclass overriding it (e.g. ContextMockConfigurator) still runs
228
- return lastValueFrom(from(this._processConfig(config, init)));
229
- }
230
-
231
- /**
232
- * Defaults `resolveInitialContext` and `client` when a builder callback
233
- * didn't set them.
234
- *
235
- * If no `resolveInitialContext` was set, the default path + parent
236
- * resolver is used. If no `client` was set, one is created from the
237
- * {@link ServicesModule} API provider.
238
- *
239
- * @param config - The config accumulated from registered builder callbacks.
240
- * @param init - Module initializer arguments including dependency instances.
241
- * @returns The fully resolved context module configuration.
242
- */
243
- protected async _processConfig(
244
- config: Partial<ContextModuleConfig>,
245
- init: ModuleInitializerArgs<IContextModuleConfigurator, [ServicesModule, NavigationModule]>,
246
- ): Promise<ContextModuleConfig> {
247
- config.resolveInitialContext ??= resolveInitialContext({
248
- path: {
249
- extract: config.extractContextIdFromPath,
250
- validate: config.extractContextIdFromPath ? () => true : undefined,
251
- },
252
- });
253
-
254
- // TODO(#5119) - make less lazy
255
- config.client ??= await (async (): Promise<ContextModuleConfig['client']> => {
256
- const apiProvider = await this._getServiceProvider(init);
257
- const contextClient = await apiProvider.createContextClient('json$');
258
- return {
259
- get: {
260
- client: {
261
- fn: (args) => contextClient.get('v1', args, { selector: getContextSelector }),
262
- },
263
- key: ({ id }) => id,
264
- expire: this.defaultExpireTime,
265
- },
266
- query: {
267
- client: {
268
- fn: (query) => contextClient.query('v1', { query }, { selector: queryContextSelector }),
269
- },
270
- // TODO(#5118) - might cast to checksum
271
- key: (args) => JSON.stringify(args),
272
- expire: this.defaultExpireTime,
273
- },
274
- related: {
275
- client: {
276
- fn: (args) => {
277
- return contextClient.related(
278
- 'v1',
279
- { id: args.item.id, query: { filter: args.filter } },
280
- { selector: relatedContextSelector },
281
- );
282
- },
283
- },
284
- // TODO(#5118) - might cast to checksum
285
- key: (args) => JSON.stringify(args),
286
- expire: this.defaultExpireTime,
287
- },
288
- };
289
- })();
290
-
291
- return config as ContextModuleConfig;
292
- }
293
- }
294
-
295
- export default ContextModuleConfigurator;