repluggable-core 1.302.63 → 1.302.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/API.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import * as Redux from 'redux'
2
+
1
3
  export interface AnySlotKey {
2
4
  readonly name: string
3
5
  readonly public?: boolean // TODO: Move to new interface - APIKey
@@ -28,4 +30,498 @@ export interface SlotKey<T> extends AnySlotKey {
28
30
  * Version of the API that will be part of the API key unique identification
29
31
  */
30
32
  readonly version?: number // TODO: Move to new interface - APIKey
31
- }
33
+ }
34
+
35
+ export type ReactComponentContributor<TProps = {}> = (props?: TProps) => React.ReactNode
36
+ export type ReducersMapObjectContributor<TState = {}, TAction extends Redux.AnyAction = Redux.AnyAction> = () => Redux.ReducersMapObject<
37
+ TState,
38
+ TAction
39
+ >
40
+ export type ContributionPredicate = () => boolean
41
+ export interface EntryPointTags {
42
+ [name: string]: string
43
+ }
44
+ export type LazyEntryPointFactory = () => Promise<EntryPoint> //TODO: get rid of these
45
+ export type ShellsChangedCallback = (shellNames: string[]) => void
46
+ export type DeclarationsChangedCallback = () => void
47
+ export type UnsubscribeFromDeclarationsChanged = () => void
48
+ export type ShellBoundaryAspect = React.FunctionComponent<React.PropsWithChildren<unknown>>
49
+
50
+ export interface LazyEntryPointDescriptor {
51
+ readonly name: string
52
+ readonly factory: LazyEntryPointFactory
53
+ }
54
+
55
+
56
+
57
+ /**
58
+ * Application part that will receive a {Shell} when loaded into the {AppHost}
59
+ * @export
60
+ * @interface EntryPoint
61
+ */
62
+ export interface EntryPoint {
63
+ /**
64
+ * Unique name that will represent this entry point in the host
65
+ */
66
+ readonly name: string
67
+ readonly tags?: EntryPointTags
68
+ /**
69
+ * Application layer / layers that will restrict usage of APIs contributed by this entry point.
70
+ * Layers hierarchy is defined in the host options
71
+ * See {AppHostOptions.layers}
72
+ */
73
+ readonly layer?: string | string[]
74
+ /**
75
+ * Define which API keys (a.k.a. contracts) are mandatory for this entry point to be executed
76
+ * @return {SlotKey<any>[]} API keys to wait for implementation
77
+ */
78
+ getDependencyAPIs?(): SlotKey<any>[]
79
+ /**
80
+ * Define which API keys (a.k.a. contracts) this entry point is going to implement and contribute
81
+ * @return {SlotKey<any>[]} API keys that will be contributed
82
+ */
83
+ declareAPIs?(): SlotKey<any>[]
84
+ /**
85
+ * Execute logic that is independent from other entry points
86
+ * Most commonly - contribute APIs and state
87
+ * @param {Shell} shell
88
+ */
89
+ attach?(shell: Shell): void
90
+ /**
91
+ * Execute logic that is dependent on other entry points
92
+ * @param {Shell} shell
93
+ */
94
+ extend?(shell: Shell): void
95
+ /**
96
+ * Clean side effects
97
+ * @param {Shell} shell
98
+ */
99
+ detach?(shell: Shell): void
100
+ }
101
+
102
+ export type AnyEntryPoint = EntryPoint | LazyEntryPointDescriptor
103
+ export type EntryPointOrPackage = AnyEntryPoint | AnyEntryPoint[]
104
+ export interface EntryPointOrPackagesMap {
105
+ [name: string]: EntryPointOrPackage
106
+ }
107
+
108
+ export type ExtensionItemFilter<T> = (extensionItem: ExtensionItem<T>) => boolean
109
+ /**
110
+ * A slot/container for holding any contribution of shape T
111
+ * Access to the slot is scoped to the {Shell}
112
+ *
113
+ * @export
114
+ * @interface ExtensionSlot
115
+ * @template T
116
+ */
117
+ export interface ExtensionSlot<T> {
118
+ /**
119
+ * a unique identifier for the slot
120
+ */
121
+ readonly name: string
122
+ readonly host: AppHost
123
+ /**
124
+ * Which {Shell} owns this slot
125
+ */
126
+ readonly declaringShell?: Shell
127
+ /**
128
+ * Add an item to the slot
129
+ *
130
+ * @param {Shell} shell Who owns the contributed item
131
+ * @param {T} item Extension item to be added to the slot
132
+ * @param {ContributionPredicate} [condition] A predicate to condition the retrieval of the item when slot items are requested with {ExtensionSlot<T>.getItems}
133
+ */
134
+ contribute(shell: Shell, item: T, condition?: ContributionPredicate): void
135
+ /**
136
+ * Get all items contributed to the slot
137
+ *
138
+ * @param {boolean} [forceAll] Ignore items' contribution predicates and get all anyway
139
+ * @return {ExtensionItem<T>[]} All items contributed to the slot
140
+ */
141
+ getItems(forceAll?: boolean): ExtensionItem<T>[]
142
+ /**
143
+ * Get the first item in the slot
144
+ *
145
+ * @return {ExtensionItem<T>} The first item in the slot
146
+ */
147
+ getSingleItem(): ExtensionItem<T> | undefined
148
+ /**
149
+ * Get a specific item in the slot
150
+ *
151
+ * @param {string} name Extension item name
152
+ * @return {ExtensionItem<T> | undefined} Extension item
153
+ */
154
+ getItemByName(name: string): ExtensionItem<T> | undefined
155
+ /**
156
+ * Remove items from the slot by predicate
157
+ *
158
+ * @param {ExtensionItemFilter<T> | undefined} predicate Remove all items matching this predicate
159
+ */
160
+ discardBy(predicate: ExtensionItemFilter<T>): void
161
+ }
162
+
163
+ export interface PrivateExtensionSlot<T> extends ExtensionSlot<T> {
164
+ subscribe(callback: () => void): () => void
165
+ }
166
+
167
+ export interface CustomExtensionSlotHandler<T> {
168
+ contribute(fromShell: Shell, item: T, condition?: ContributionPredicate): void
169
+ discardBy(predicate: ExtensionItemFilter<T>): void
170
+ }
171
+
172
+ export interface CustomExtensionSlot<T> extends CustomExtensionSlotHandler<T> {
173
+ readonly name: string
174
+ readonly host: AppHost
175
+ readonly declaringShell?: Shell
176
+ }
177
+
178
+ /**
179
+ * Item of shape T that is contributed to a slot of shape T
180
+ *
181
+ * @export
182
+ * @interface ExtensionItem
183
+ * @template T
184
+ */
185
+ export interface ExtensionItem<T> {
186
+ readonly name?: string
187
+ /**
188
+ * Which {Shell} owns this item
189
+ */
190
+ readonly shell: Shell
191
+ /**
192
+ * Contribution content
193
+ */
194
+ readonly contribution: T
195
+ /**
196
+ * Condition for the retrieval of this item by {ExtensionSlot<T>.getItems}
197
+ */
198
+ readonly condition: ContributionPredicate
199
+ readonly uniqueId: string
200
+ }
201
+
202
+ // addEntryPoints(entryPoints: EntryPoint[])
203
+ // addPackages(packages: EntryPointOrPackage[])
204
+ //
205
+
206
+ /**
207
+ * An application content container that will accept {EntryPoint} and provide registry for contracts
208
+ *
209
+ * @export
210
+ * @interface AppHost
211
+ */
212
+ export interface AppHost {
213
+ /**
214
+ * Get an implementation of API previously contributed to the {AppHost}
215
+ *
216
+ * @template TAPI
217
+ * @param {SlotKey<TAPI>} key API Key
218
+ * @return {*} {TAPI}
219
+ */
220
+ getAPI<TAPI>(key: SlotKey<TAPI>): TAPI
221
+ /**
222
+ * Get an extension slot defined on the host
223
+ *
224
+ * @template TItem
225
+ * @param {SlotKey<TItem>} key
226
+ * @return {ExtensionSlot<TItem>}
227
+ */
228
+ getSlot<TItem>(key: SlotKey<TItem>): ExtensionSlot<TItem>
229
+ /**
230
+ * Get all the extension slots defined on the host
231
+ *
232
+ * @return {*} {AnySlotKey[]}
233
+ */
234
+ getAllSlotKeys(): AnySlotKey[]
235
+ /**
236
+ * Get all {EntryPoint}s addded to the {AppHost}
237
+ *
238
+ * @return {EntryPointsInfo[]}
239
+ */
240
+ getAllEntryPoints(): EntryPointsInfo[]
241
+ /**
242
+ * Does the {AppHost} contain a specific {Shell}
243
+ *
244
+ * @param {string} name
245
+ * @return {boolean}
246
+ */
247
+ hasShell(name: string): boolean
248
+ // TODO: Deprecate
249
+ isLazyEntryPoint(name: string): boolean
250
+ /**
251
+ * Dynamically add {Shell}s after the host is created
252
+ *
253
+ * @param {EntryPointOrPackage[]} entryPointsOrPackages New packages or entry points to be added to the {AppHost}
254
+ * @return {Promise<void>}
255
+ */
256
+ addShells(entryPointsOrPackages: EntryPointOrPackage[]): Promise<void>
257
+ /**
258
+ * Dynamically remove {Shell}s after the host is created
259
+ *
260
+ * @param {string[]} names {Shell} names to be removed
261
+ * @return {Promise<void>}
262
+ */
263
+ removeShells(names: string[]): Promise<void>
264
+ /**
265
+ * Subscribe to changes in host declarations. This includes:
266
+ * - API additions and removals
267
+ * - Extension slot additions and removals
268
+ *
269
+ * @param {DeclarationsChangedCallback} callback Function to be called when host declarations change
270
+ * @return {UnsubscribeFromDeclarationsChanged} Function to unsubscribe from host declarations changes
271
+ */
272
+
273
+ onDeclarationsChanged(callback: DeclarationsChangedCallback): UnsubscribeFromDeclarationsChanged
274
+ onShellsChanged(callback: ShellsChangedCallback): string
275
+ removeShellsChangedCallback(callbackId: string): void
276
+ readonly log: HostLogger
277
+ readonly options: AppHostOptions
278
+ }
279
+
280
+ export interface PrivateAppHost extends AppHost {
281
+ executeWhenFree(identifier: string, callback: () => void): void
282
+ }
283
+
284
+ export interface MonitoringOptions {
285
+ enablePerformance?: boolean
286
+ readonly disableMonitoring?: boolean
287
+ readonly disableMemoization?: boolean
288
+ readonly debugMemoization?: boolean
289
+ }
290
+
291
+ export interface Trace {
292
+ name: string
293
+ duration: number
294
+ startTime: number
295
+ res: any
296
+ args: any[]
297
+ }
298
+
299
+ export interface APILayer {
300
+ level: number
301
+ name: string
302
+ }
303
+
304
+ export interface AppHostOptions {
305
+ readonly logger?: HostLogger
306
+ readonly monitoring: MonitoringOptions
307
+ readonly layers?: APILayer[] | APILayer[][]
308
+ readonly disableLayersValidation?: boolean
309
+ readonly disableCheckCircularDependencies?: boolean
310
+ readonly enableStickyErrorBoundaries?: boolean
311
+ readonly enableReduxDevtoolsExtension?: boolean
312
+ readonly experimentalCyclicMode?: boolean
313
+ readonly shouldScopeReducers?: boolean
314
+ }
315
+
316
+ export interface MemoizeMissHit {
317
+ miss: number
318
+ calls: number
319
+ hit: number
320
+ printHitMiss(): void
321
+ }
322
+
323
+ export type enrichedMemoizationFunction = MemoizeMissHit & AnyFunction & _.MemoizedFunction
324
+
325
+ export interface StatisticsMemoization {
326
+ func: enrichedMemoizationFunction
327
+ name: string
328
+ }
329
+
330
+ export interface ContributeAPIOptions<TAPI> {
331
+ includesNamespaces?: boolean
332
+ disableMonitoring?: boolean | (keyof TAPI)[]
333
+ }
334
+
335
+ export type StateObserverUnsubscribe = () => void
336
+ export type StateObserver<TSelectorAPI> = (next: TSelectorAPI) => void
337
+ export interface ObservableState<TSelectorAPI> {
338
+ subscribe(fromShell: Shell, callback: StateObserver<TSelectorAPI>): StateObserverUnsubscribe
339
+ current(allowUnsafeReading?: boolean): TSelectorAPI
340
+ }
341
+
342
+ export type AnyFunction = (...args: any[]) => any
343
+ export type FunctionWithSameArgs<F extends AnyFunction> = (...args: Parameters<F>) => any
344
+
345
+ export interface Lazy<T> {
346
+ get(): T
347
+ }
348
+
349
+ /**
350
+ * An scoped communication terminal provided for an {EntryPoint}
351
+ * in order to contribute its application content to the {AppHost}
352
+ *
353
+ * @export
354
+ * @interface Shell
355
+ * @extends {(Pick<AppHost, Exclude<keyof AppHost, 'getStore' | 'log' | 'options'>>)}
356
+ */
357
+ export interface Shell extends Pick<AppHost, Exclude<keyof AppHost, 'getStore' | 'log' | 'options'>> {
358
+ /**
359
+ * Are APIs ready to be requested
360
+ *
361
+ * @return {*} {boolean}
362
+ */
363
+ canUseAPIs(): boolean
364
+ /**
365
+ * Is store ready to be requested
366
+ *
367
+ * @return {*} {boolean}
368
+ */
369
+ canUseStore(): boolean
370
+ /**
371
+ * Did the execution of {EntryPoint}s' lifecycle phases (attach, detach) are done
372
+ *
373
+ * @return {*} {boolean}
374
+ */
375
+ wasInitializationCompleted(): boolean
376
+ runLateInitializer<T>(initializer: () => T): T
377
+ /**
378
+ * Create an {ExtensionSlot}
379
+ *
380
+ * @template TItem
381
+ * @param {SlotKey<TItem>} key Key that will represent the slot (an will be used for retrieval)
382
+ * @return {ExtensionSlot<TItem>} Actual slot
383
+ */
384
+ declareSlot<TItem>(key: SlotKey<TItem>): ExtensionSlot<TItem>
385
+ declareCustomSlot<TItem>(key: SlotKey<TItem>, handler: CustomExtensionSlotHandler<TItem>): CustomExtensionSlot<TItem>
386
+
387
+ // TODO: Fix contributeAPI factory type not to resort to lowest common
388
+ /**
389
+ * Contribute an implementation of an API (a.k.a contract)
390
+ *
391
+ * @template TAPI
392
+ * @param {SlotKey<TAPI>} key API Key that represents an interface TAPI
393
+ * @param {() => TAPI} factory Create an implementation of TAPI
394
+ * @param {ContributeAPIOptions<TAPI>} [options] Contribution options {ContributeAPIOptions}
395
+ * @return {TAPI} Result of the factory execution
396
+ */
397
+ contributeAPI<TAPI>(key: SlotKey<TAPI>, factory: () => TAPI, options?: ContributeAPIOptions<TAPI>): TAPI
398
+ /**
399
+ * Contribute a Redux reducer that will be added to the host store.
400
+ * Use it for slowly changing state (e.g. not changing because of mouse movement)
401
+ *
402
+ * @template TState
403
+ * @param {ReducersMapObjectContributor<TState>} contributor
404
+ */
405
+ contributeState<TState, TAction extends Redux.AnyAction = Redux.AnyAction>(
406
+ contributor: ReducersMapObjectContributor<TState, TAction>
407
+ ): void
408
+
409
+ /**
410
+ * Contribute a Redux reducer that will be added to the host store
411
+ * Use it for rapidly changing state (e.g. changing on every mouse movement event)
412
+ * Changes to this state won't trigger the usual subscribers.
413
+ * In order to subscribe to changes in this state, use the observer object returned by this function.
414
+ *
415
+ * @template TState
416
+ * @param {ReducersMapObjectContributor<TState>} contributor
417
+ * @return {TAPI} Observer object for subscribing to state changes. The observer can also be passed to {connectWithShell}.
418
+ */
419
+ contributeObservableState<TState, TSelector, TAction extends Redux.AnyAction = Redux.AnyAction>(
420
+ contributor: ReducersMapObjectContributor<TState, TAction>,
421
+ selectorFactory: (state: TState) => TSelector
422
+ ): ObservableState<TSelector>
423
+
424
+ /**
425
+ * Contribute the main view (root) of the application
426
+ * Intended to be used by a single {Shell} in an application
427
+ *
428
+ * @param {Shell} fromShell Who owns the main view
429
+ * @param {ReactComponentContributor} contributor Create the main view component
430
+ */
431
+ contributeMainView(fromShell: Shell, contributor: ReactComponentContributor): void
432
+ contributeBoundaryAspect(component: ShellBoundaryAspect): void
433
+ /**
434
+ * Create a function with internal cache until any state change in the {AppHost} store
435
+ *
436
+ * @template T
437
+ * @param {T} func Function to build cache for
438
+ * @param {FunctionWithSameArgs<T>} resolver Key creator to index results by
439
+ * @param {() => boolean} [shouldClear] Custom clear condition (if not provided, behaves like () => true)
440
+ * @return {*} {(((...args: Parameters<T>) => ReturnType<T>) & Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>)}
441
+ */
442
+ memoizeForState<T extends AnyFunction>(
443
+ func: T,
444
+ resolver: FunctionWithSameArgs<T>,
445
+ shouldClear?: () => boolean
446
+ ): ((...args: Parameters<T>) => ReturnType<T>) & Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>
447
+ /**
448
+ * Manually trigger clear condition for function memoized with {Shell.memoizeForState}
449
+ */
450
+ flushMemoizedForState(): void
451
+ /**
452
+ * Create a function with internal cache
453
+ *
454
+ * @template T
455
+ * @param {T} func Function to build cache for
456
+ * @param {FunctionWithSameArgs<T>} resolver Key creator to index results by
457
+ * @return {*} {(((...args: Parameters<T>) => ReturnType<T>) & Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>)}
458
+ */
459
+ memoize<T extends AnyFunction>(
460
+ func: T,
461
+ resolver: FunctionWithSameArgs<T>
462
+ ): ((...args: Parameters<T>) => ReturnType<T>) & Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>
463
+ /**
464
+ * Clear cache of a memoized function
465
+ *
466
+ * @param {(Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>)} memoizedFunction
467
+ */
468
+ clearCache(memoizedFunction: Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>): void
469
+ /**
470
+ * Creates a lazy-evaluated value. The function `func` is only executed once when `get` is called for the first time,
471
+ * and the result is cached for subsequent calls.
472
+ *
473
+ * @template T
474
+ * @param {F} func - The function that will be lazily evaluated. It should not take any arguments.
475
+ * @returns {Lazy<T>} An object with a `get` method that returns the lazily evaluated value of type `T`.
476
+ */
477
+ lazyEvaluator<F extends AnyFunction, T extends ReturnType<F>>(func: F): Lazy<T>
478
+ }
479
+
480
+ export interface PrivateShell extends Shell {
481
+ readonly entryPoint: EntryPoint
482
+ setDependencyAPIs(APIs: AnySlotKey[]): void
483
+ setLifecycleState(enableStore: boolean, enableAPIs: boolean, initCompleted: boolean): void
484
+ getBoundaryAspects(): ShellBoundaryAspect[]
485
+ getHostOptions(): AppHostOptions
486
+ wrapWithShellRenderer(component: JSX.Element): JSX.Element
487
+ }
488
+
489
+ export interface EntryPointsInfo {
490
+ readonly name: string
491
+ readonly lazy: boolean
492
+ readonly attached: boolean
493
+ }
494
+
495
+ export interface EntryPointInterceptor {
496
+ interceptName?(innerName: string): string
497
+ interceptTags?(innerTags?: EntryPointTags): EntryPointTags
498
+ interceptGetDependencyAPIs?(innerGetDependencyAPIs?: EntryPoint['getDependencyAPIs']): EntryPoint['getDependencyAPIs']
499
+ interceptDeclareAPIs?(innerDeclareAPIs?: EntryPoint['declareAPIs']): EntryPoint['declareAPIs']
500
+ interceptAttach?(innerAttach?: EntryPoint['attach']): EntryPoint['attach']
501
+ interceptDetach?(innerDetach?: EntryPoint['detach']): EntryPoint['detach']
502
+ interceptExtend?(innerExtend?: EntryPoint['extend']): EntryPoint['extend']
503
+ }
504
+
505
+ export type LogSeverity = 'debug' | 'info' | 'event' | 'warning' | 'error' | 'critical'
506
+ export type LogSpanFlag = 'begin' | 'end' //TODO:deprecated-kept-for-backward-compat
507
+
508
+ export interface HostLogger {
509
+ log(severity: LogSeverity, id: string, error?: Error, keyValuePairs?: Object): void
510
+ spanChild(messageId: string, keyValuePairs?: Object): ShellLoggerSpan
511
+ spanRoot(messageId: string, keyValuePairs?: Object): ShellLoggerSpan
512
+ }
513
+
514
+ export interface ShellLogger extends HostLogger {
515
+ debug(messageId: string, keyValuePairs?: Object): void
516
+ info(messageId: string, keyValuePairs?: Object): void
517
+ warning(messageId: string, keyValuePairs?: Object): void
518
+ error(messageId: string, error?: Error, keyValuePairs?: Object): void
519
+ critical(messageId: string, error?: Error, keyValuePairs?: Object): void
520
+ spanChild(messageId: string, keyValuePairs?: Object): ShellLoggerSpan
521
+ spanRoot(messageId: string, keyValuePairs?: Object): ShellLoggerSpan
522
+ monitor<T>(messageId: string, keyValuePairs: Object, monitoredCode: () => T): T
523
+ }
524
+
525
+ export interface ShellLoggerSpan {
526
+ end(success: boolean, error?: Error, keyValuePairs?: Object): void
527
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * This symbol is only for internal use of repluggable mono-repo.
3
+ */
4
+ export const INTERNAL_DONT_USE_SHELL_GET_APP_HOST: unique symbol = Symbol('SHELL_GET_APP_HOST')
package/src/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export {
2
2
  AnySlotKey,
3
3
  SlotKey
4
- } from './API'
4
+ } from './API'
5
+
6
+ export * from './__internal'