From 96a3ab1affadc98e9acadfcf0a4bfd9f96b3cdc6 Mon Sep 17 00:00:00 2001 From: ondraveres Date: Fri, 27 Mar 2026 14:07:43 +0100 Subject: [PATCH] 3.74.0 candidate --- CHANGELOG.md | 8 +- package-lock.json | 4 +- package.json | 2 +- src/BuildRouter.js | 27 +++++- src/graphApi/validateBotApi.js | 7 +- test/buildRouterConfiguration.js | 141 +++++++++++++++++++++++++++++++ 6 files changed, 181 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48c77661..195f47c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [3.73.14] +## [3.74.0] + +### Fixed + +- snapshots now can have a prop called deployedConfiguration and that will be merged into configuration + +## [3.73.15] ### Fixed diff --git a/package-lock.json b/package-lock.json index 9a2cfa84..36066090 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wingbot", - "version": "3.73.15", + "version": "3.74.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wingbot", - "version": "3.73.15", + "version": "3.74.0", "license": "MIT", "dependencies": { "@amplitude/ua-parser-js": "^0.7.33", diff --git a/package.json b/package.json index f47c04c2..3d31310b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wingbot", - "version": "3.73.15", + "version": "3.74.0", "description": "Enterprise Messaging Bot Conversation Engine", "main": "index.js", "type": "commonjs", diff --git a/src/BuildRouter.js b/src/BuildRouter.js index 47a17afa..53ab5d5f 100644 --- a/src/BuildRouter.js +++ b/src/BuildRouter.js @@ -395,7 +395,12 @@ class BuildRouter extends Router { if (!snapshot) { snapshot = await this.loadBot(); } - this.buildWithSnapshot(snapshot.blocks); + this.buildWithSnapshot( + snapshot.blocks, + undefined, + undefined, + snapshot.deployedConfiguration + ); } catch (e) { if (this._configTs > 0 && !snapshot) { // mute @@ -437,7 +442,12 @@ class BuildRouter extends Router { // wait for running request await Promise.all(this._runningReqs); - this.buildWithSnapshot(snapshot.blocks, snapshot.timestamp, snapshot.lastmod); + this.buildWithSnapshot( + snapshot.blocks, + snapshot.timestamp, + snapshot.lastmod, + snapshot.deployedConfiguration + ); } catch (e) { await configStorage.invalidateConfig(); throw e; @@ -528,9 +538,20 @@ class BuildRouter extends Router { blocks.forEach((b) => this._validateBlock(b, action)); } - buildWithSnapshot (blocks, setConfigTimestamp = Number.MAX_SAFE_INTEGER, lastmod = '-') { + buildWithSnapshot (blocks, setConfigTimestamp = Number.MAX_SAFE_INTEGER, lastmod = '-', deployedConfiguration = null) { this._validateBlocks(blocks); + if (deployedConfiguration && typeof deployedConfiguration === 'object') { + if (this._configuration instanceof Promise) { + this._configuration = this._configuration + .then((c) => Object.assign(c || /** @type {C} */ ({}), deployedConfiguration)); + } else { + const cfg = this._configuration || /** @type {C} */ ({}); + Object.assign(cfg, deployedConfiguration); + this._configuration = cfg; + } + } + Object.assign(this._resolvedContext, { blocks, nestedBlocksByStaticId: null diff --git a/src/graphApi/validateBotApi.js b/src/graphApi/validateBotApi.js index b7d26b0e..4703988e 100644 --- a/src/graphApi/validateBotApi.js +++ b/src/graphApi/validateBotApi.js @@ -21,7 +21,12 @@ const apiAuthorizer = require('./apiAuthorizer'); */ async function validate (bot, validationRequestBody, postBackTest = null, textTest = null) { try { - bot.buildWithSnapshot(validationRequestBody.blocks, Number.MAX_SAFE_INTEGER); + bot.buildWithSnapshot( + validationRequestBody.blocks, + Number.MAX_SAFE_INTEGER, + undefined, + validationRequestBody.deployedConfiguration + ); } catch (e) { const error = `Bot build failed: ${e.message}`; // eslint-disable-next-line no-console diff --git a/test/buildRouterConfiguration.js b/test/buildRouterConfiguration.js index 8a4e87fa..4cabe411 100644 --- a/test/buildRouterConfiguration.js +++ b/test/buildRouterConfiguration.js @@ -83,4 +83,145 @@ describe('', () => { }); + describe('deployedConfiguration', () => { + + it('should merge deployedConfiguration into c variables', async () => { + const blocks = [ + { + isRoot: true, + blockName: 'Root', + staticBlockId: 'root-block', + routes: [ + { + id: 1, + path: 'start', + isEntryPoint: true, + isFallback: false, + resolvers: [ + { + type: 'botbuild.message', + params: { + text: [ + 'Hello {{c.brandEmail}}' + ], + replies: [] + } + } + ] + } + ] + } + ]; + + const rootBlock = blocks.find((b) => b.isRoot); + // @ts-ignore + const bot = new BuildRouter(rootBlock, new Plugins(), { + blocks, + configuration: {} + }); + + bot.buildWithSnapshot(blocks, undefined, undefined, { + brandEmail: 'test@example.com' + }); + + const tester = new Tester(bot); + + await tester.postBack('start'); + + tester.any().contains('Hello test@example.com'); + }); + + it('should merge deployedConfiguration with existing configuration', async () => { + const blocks = [ + { + isRoot: true, + blockName: 'Root', + staticBlockId: 'root-block', + routes: [ + { + id: 1, + path: 'start', + isEntryPoint: true, + isFallback: false, + resolvers: [ + { + type: 'botbuild.message', + params: { + text: [ + '{{c.existing}} {{c.brandEmail}}' + ], + replies: [] + } + } + ] + } + ] + } + ]; + + const rootBlock = blocks.find((b) => b.isRoot); + // @ts-ignore + const bot = new BuildRouter(rootBlock, new Plugins(), { + blocks, + configuration: { existing: 'keep' } + }); + + bot.buildWithSnapshot(blocks, undefined, undefined, { + brandEmail: 'hello@brand.com' + }); + + const tester = new Tester(bot); + + await tester.postBack('start'); + + tester.any().contains('keep hello@brand.com'); + }); + + it('should work without deployedConfiguration', async () => { + const blocks = [ + { + isRoot: true, + blockName: 'Root', + staticBlockId: 'root-block', + routes: [ + { + id: 1, + path: 'start', + isEntryPoint: true, + isFallback: false, + resolvers: [ + { + type: 'botbuild.message', + params: { + text: [ + 'Hello world' + ], + replies: [] + } + } + ] + } + ] + } + ]; + + const rootBlock = blocks.find((b) => b.isRoot); + // @ts-ignore + const bot = new BuildRouter(rootBlock, new Plugins(), { + blocks, + configuration: { foo: 'bar' } + }); + + bot.buildWithSnapshot(blocks); + + const tester = new Tester(bot); + + await tester.postBack('start'); + + tester.any().contains('Hello world'); + assert.equal(/** @type {any} */ (bot.configuration).foo, 'bar'); + }); + + }); + });