From 23df709829ed4016007ecf5d00384c54f48aadb6 Mon Sep 17 00:00:00 2001 From: pwrmiller Date: Sat, 7 Oct 2023 08:41:03 -0400 Subject: [PATCH] feat: add a mechanism to retrieve all context (with defaults) (#1751) Previously, all users of constructs would have to know beforehand the keys in the context to expect, and use either `tryGetContext` or `getContext` to retrieve a specific key from context. This provides a mechanism to get the full context of a node in the construct tree, with overridable defaults. The `getAllContext` method allows users to retrieve all context. The interface for `getContext` and `tryGetContext` remains unchanged. I have also fixed a small typo in the library. --- API.md | 15 +++++++++++++++ src/construct.ts | 21 ++++++++++++++++++++- test/construct.test.ts | 16 ++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index c8c7e995..734bdb79 100644 --- a/API.md +++ b/API.md @@ -344,6 +344,21 @@ findChild(id: string): IConstruct __Returns__: * [IConstruct](#constructs-iconstruct) +#### getAllContext(defaults?) + +Retrieves the all context of a node from tree context. + +Context is usually initialized at the root, but can be overridden at any point in the tree. + +```ts +getAllContext(defaults?: json): any +``` + +* **defaults** (json) Any keys to override the retrieved context. + +__Returns__: +* any + #### getContext(key) Retrieves a value from tree context if present. Otherwise, would throw an error. diff --git a/src/construct.ts b/src/construct.ts index 1888384b..1dc25ce8 100644 --- a/src/construct.ts +++ b/src/construct.ts @@ -44,7 +44,7 @@ export class Node { /** * The id of this construct within the current scope. * - * This is a a scope-unique id. To obtain an app-unique id for this construct, use `addr`. + * This is a scope-unique id. To obtain an app-unique id for this construct, use `addr`. */ public readonly id: string; @@ -236,6 +236,25 @@ export class Node { return this.scope && this.scope.node.getContext(key); } + /** + * Retrieves the all context of a node from tree context. + * + * Context is usually initialized at the root, but can be overridden at any point in the tree. + * + * @param defaults Any keys to override the retrieved context + * @returns The context object or an empty object if there is discovered context + */ + public getAllContext(defaults?: object): any { + if (typeof defaults === 'undefined') { + defaults = {}; + } + + if (this.scope === undefined) { return defaults; } + + const value = { ...this._context, ...defaults }; + return this.scope && this.scope.node.getAllContext(value); + } + /** * Retrieves a value from tree context. * diff --git a/test/construct.test.ts b/test/construct.test.ts index d46f0a79..ecfee0da 100644 --- a/test/construct.test.ts +++ b/test/construct.test.ts @@ -150,6 +150,22 @@ test('construct.getContext(key) throws if context is not defined', () => { }).toThrowError(`No context value present for ${key} key`); }); +test('construct.getAllContext can be used to read the full context of a node', () => { + // GIVEN + const context = { + ctx1: 12, + ctx2: 'hello', + }; + + // WHEN + const t = createTree(context); + t.child1_1_1.node.setContext('ctx1', 13); + + // THEN + expect(t.child1_2.node.getAllContext()).toStrictEqual(context); + expect(t.child1_1_1.node.getAllContext()).toStrictEqual({ ctx1: 13, ctx2: 'hello' }); +}); + test('construct.tryGetContext(key) can be used to read a value from context defined at the root level', () => { const context = { ctx1: 12,