Skip to content

Commit

Permalink
Add shell.lazyEvaluator (#255)
Browse files Browse the repository at this point in the history
* Add shell.lazyEvaluator

* fix testkit
  • Loading branch information
ShirShintel authored Aug 25, 2024
1 parent 8517f95 commit aa65f90
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ export interface ObservableState<TSelectorAPI> {
export type AnyFunction = (...args: any[]) => any
export type FunctionWithSameArgs<F extends AnyFunction> = (...args: Parameters<F>) => any

export interface Lazy<T> {
get(): T
}

/**
* An scoped communication terminal provided for an {EntryPoint}
* in order to contribute its application content to the {AppHost}
Expand Down Expand Up @@ -474,6 +478,15 @@ export interface Shell extends Pick<AppHost, Exclude<keyof AppHost, 'getStore' |
* @param {(Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>)} memoizedFunction
*/
clearCache(memoizedFunction: Partial<_.MemoizedFunction> & Partial<MemoizeMissHit>): void
/**
* Creates a lazy-evaluated value. The function `func` is only executed once when `get` is called for the first time,
* and the result is cached for subsequent calls.
*
* @template T
* @param {F} func - The function that will be lazily evaluated. It should not take any arguments.
* @returns {Lazy<T>} An object with a `get` method that returns the lazily evaluated value of type `T`.
*/
lazyEvaluator<F extends AnyFunction, T extends ReturnType<F>>(func: F): Lazy<T>
}

export interface PrivateShell extends Shell {
Expand Down
20 changes: 19 additions & 1 deletion src/appHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
EntryPointsInfo,
ExtensionItem,
ExtensionSlot,
Lazy,
LazyEntryPointDescriptor,
LazyEntryPointFactory,
PrivateShell,
Expand Down Expand Up @@ -237,6 +238,22 @@ export function createAppHost(initialEntryPointsOrPackages: EntryPointOrPackage[
return enrichedMemoization
}

function lazyEvaluator<F extends AnyFunction, T extends ReturnType<F>>(fn: F): Lazy<T> {
let _value: T
let _resolved: boolean = false

return {
get: () => {
if (!_resolved) {
_value = fn()
_resolved = true
}

return _value
}
}
}

// we know that addShells completes synchronously
addShells(initialEntryPointsOrPackages)

Expand Down Expand Up @@ -1092,7 +1109,8 @@ miss: ${memoizedWithMissHit.miss}

wrapWithShellRenderer(component): JSX.Element {
return <ShellRenderer shell={shell} component={component} host={host} />
}
},
lazyEvaluator
}

return shell
Expand Down
12 changes: 12 additions & 0 deletions test/appHost.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,18 @@ describe('App Host', () => {
}
})
})

describe('lazyEvaluator', () => {
it('should return a getter that is evaluated only once', () => {
const { helperShell } = createHostWithDependantPackages(MockAPI)
const func = jest.fn(() => 42)
const lazyEval = helperShell.lazyEvaluator(func)

expect(lazyEval.get()).toBe(42)
expect(lazyEval.get()).toBe(42)
expect(func).toHaveBeenCalledTimes(1)
})
})
})

describe('Entry Point Shell Scoping', () => {
Expand Down
3 changes: 2 additions & 1 deletion testKit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ function createShell(host: AppHost): PrivateShell {
clearCache: _.noop,
getHostOptions: () => host.options,
log: createShellLogger(host, entryPoint),
wrapWithShellRenderer: (component: JSX.Element) => component
wrapWithShellRenderer: (component: JSX.Element) => component,
lazyEvaluator: func => ({ get: func })
}
}

Expand Down

0 comments on commit aa65f90

Please sign in to comment.