Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for Node 22 #4808

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/depcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: yarn
run: yarn --frozen-lockfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: yarn
run: yarn --frozen-lockfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: yarn
run: yarn --frozen-lockfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-consumer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: yarn
run: yarn --frozen-lockfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-repoutils.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: yarn
run: yarn --frozen-lockfile
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-schemas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: use node 20.x
- name: use node 22.x
uses: actions/setup-node@v2-beta
with:
node-version: 20.x
node-version: 22.x

- name: yarn cache dir
id: yarn-cache-dir
Expand All @@ -33,7 +33,7 @@ jobs:
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node20.x-yarn-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-node22.x-yarn-${{ hashFiles('**/yarn.lock') }}

- name: npm install @microsoft/botframework-cli@next --global
run: npm install @microsoft/botframework-cli@next --global
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
strategy:
matrix:
os: [ubuntu, windows]
node-version: [18.x, 20.x]
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
run: yarn test:github

- name: coveralls
if: matrix.node-version == '20.x'
if: matrix.node-version == '22.x'
uses: coverallsapp/[email protected]
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion build/yaml/botbuilder-js-daily.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pool:
vmImage: 'ubuntu-latest'

variables:
NodeVersion: 20.x
NodeVersion: 22.x
Packaging.EnableSBOMSigning: true
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
# SDK_JS_org_registry_Url: define this in Azure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async function runCommand(command, envObject) {
// We need to combine our process.env with envObject so,
// 1) We can use existing env vars (like from CI), and
// 2) npx doesn't like to install without the existing APPDATA windows env var.
const env = { ...process.env, ...envObject };
const env = { ...process.env, ...envObject, NODE_NO_WARNINGS: 1 };
const { stdout, stderr } = await exec(command, { env });

if (stderr) {
Expand Down
9 changes: 5 additions & 4 deletions libraries/botbuilder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"filenamify": "^6.0.0",
"fs-extra": "^11.2.0",
"htmlparser2": "^9.0.1",
"import-sync": "^2.2.2",
"uuid": "^10.0.0",
"zod": "^3.23.8"
},
Expand All @@ -54,9 +53,10 @@
"build": "tsc -b",
"build-docs": "typedoc --theme markdown --entryPoint botbuilder --excludePrivate --includeDeclarations --ignoreCompilerErrors --module amd --out ..\\..\\doc\\botbuilder .\\lib\\index.d.ts ..\\botbuilder-core\\lib\\index.d.ts ..\\botframework-schema\\lib\\index.d.ts --hideGenerator --name \"Bot Builder SDK\" --readme none",
"build:rollup": "yarn clean && yarn build && api-extractor run --verbose --local",
"clean": "rimraf _ts3.4 lib tsconfig.tsbuildinfo",
"clean": "rimraf _ts3.4 lib vendors tsconfig.tsbuildinfo",
"depcheck": "depcheck --config ../../.depcheckrc",
"lint": "eslint .",
"prebuild": "tsup ./node_modules/filenamify/*.js --format cjs --dts --out-dir vendors/filenamify --clean --sourcemap",
"postbuild": "downlevel-dts lib _ts3.4/lib --checksum",
"test": "npm-run-all build test:mocha",
"test:compat": "api-extractor run --verbose",
Expand All @@ -70,6 +70,7 @@
"files": [
"_ts3.4",
"lib",
"src"
"src",
"vendors"
]
}
}
4 changes: 1 addition & 3 deletions libraries/botbuilder/src/fileTranscriptStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import { join, parse } from 'path';
import { mkdirp, pathExists, readdir, readFile, remove, writeFile } from 'fs-extra';
import { Activity, PagedResult, TranscriptInfo, TranscriptStore } from 'botbuilder-core';
import importSync from 'import-sync';

const filenamify = importSync('filenamify').default;
import filenamify from '../vendors/filenamify/index';

/**
* @private
Expand Down
5 changes: 4 additions & 1 deletion libraries/botframework-config/src/botConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,10 @@ export class BotConfiguration extends BotConfigurationBase {
}
}
}
} catch {
} catch (legacyErr) {
if (legacyErr.message.includes('Node.js versions')) {
throw legacyErr;
}
throw err;
}
}
Expand Down
27 changes: 22 additions & 5 deletions libraries/botframework-config/src/encrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import crypto from 'crypto';
import { version as nodeVersion } from 'process';

/**
* @private
Expand Down Expand Up @@ -100,10 +101,26 @@ export function decryptString(encryptedValue: string, secret: string): string {
* @param secret
*/
export function legacyDecrypt(encryptedValue: string, secret: string): string {
// LEGACY for pre standardized SHA256 encryption, this uses some undocumented nodejs MD5 hash internally and is deprecated
const decipher: crypto.Decipher = crypto.createDecipher('aes192', secret);
let value: string = decipher.update(encryptedValue, 'hex', 'utf8');
value += decipher.final('utf8');
const UNSUPPORTED_VERSION = 'v22.0.0';
if (!isNodeCompatible(nodeVersion, UNSUPPORTED_VERSION)) {
throw new Error(`This method is not available for Node.js versions over ${UNSUPPORTED_VERSION}.`);
} else {
// LEGACY for pre standardized SHA256 encryption, this uses some undocumented nodejs MD5 hash internally and is deprecated
const decipher: crypto.Decipher = crypto.createDecipher('aes192', secret);
let value: string = decipher.update(encryptedValue, 'hex', 'utf8');
value += decipher.final('utf8');

return value;
}
}

return value;
/**
* private
*
* @param currentVersion The current version of Node.js.
* @param minVersion The minimum unsupported version.
* @returns true if the current version of Node is lower than the unsupported version.
*/
function isNodeCompatible(currentVersion: string, minVersion: string): boolean {
return minVersion.localeCompare(currentVersion) > 0;
}
51 changes: 33 additions & 18 deletions libraries/botframework-config/tests/loadAndSave.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const testBotPath = require.resolve('./test.bot');
const govTestBotPath = require.resolve('./govTest.bot');
const legacyBotPath = require.resolve('./legacy.bot');
const saveBotPath = testBotPath.replace('test.bot', 'save.bot');
const UNSUPPORTED_VERSION = 'v22.0.0';

describe('LoadAndSaveTests', function () {
it('DeserializeBotFile', async function () {
Expand Down Expand Up @@ -89,12 +90,19 @@ describe('LoadAndSaveTests', function () {
const config = await bf.BotConfiguration.load(testBotPath);
await config.saveAs(saveBotPath, secret);

await assert.rejects(
bf.BotConfiguration.load(saveBotPath),
new Error(
'You are attempting to perform an operation which needs access to the secret and --secret is missing'
)
);
if (UNSUPPORTED_VERSION.localeCompare(process.version) < 1) {
await assert.rejects(
bf.BotConfiguration.load(saveBotPath),
new Error(`This method is not available for Node.js versions over ${UNSUPPORTED_VERSION}.`),
);
} else {
await assert.rejects(
bf.BotConfiguration.load(saveBotPath),
new Error(
'You are attempting to perform an operation which needs access to the secret and --secret is missing'
),
);
}
});

it('LoadAndVerifyChannelServiceSync', async function () {
Expand Down Expand Up @@ -354,17 +362,24 @@ describe('LoadAndSaveTests', function () {
});

it('LegacyEncryption', async function () {
let config = await bf.BotConfiguration.load(legacyBotPath, 'password');
assert.equal(config.services[0].appPassword, 'xyzpdq', 'value should be unencrypted');
assert.ok(config.padlock != null, 'padlock should exist');
assert.ok(!config.secretKey, 'secretKey should not exist');

const secret = bf.BotConfiguration.generateKey();
await config.saveAs(saveBotPath, secret);
config = await bf.BotConfiguration.load(saveBotPath, secret);
fs.unlinkSync(saveBotPath);
assert.ok(config.padlock != null, 'padlock should exist');
assert.ok(config.padlock.length > 0, 'padlock should not be empty');
assert.ok(!config.secretKey, 'secretKey should not exist');
if (UNSUPPORTED_VERSION.localeCompare(process.version) < 1) {
await assert.rejects(
bf.BotConfiguration.load(legacyBotPath, 'password'),
new Error(`This method is not available for Node.js versions over ${UNSUPPORTED_VERSION}.`),
);
} else {
let config = await bf.BotConfiguration.load(legacyBotPath, 'password');
assert.equal(config.services[0].appPassword, 'xyzpdq', 'value should be unencrypted');
assert.ok(config.padlock != null, 'padlock should exist');
assert.ok(!config.secretKey, 'secretKey should not exist');

const secret = bf.BotConfiguration.generateKey();
await config.saveAs(saveBotPath, secret);
config = await bf.BotConfiguration.load(saveBotPath, secret);
fs.unlinkSync(saveBotPath);
assert.ok(config.padlock != null, 'padlock should exist');
assert.ok(config.padlock.length > 0, 'padlock should not be empty');
assert.ok(!config.secretKey, 'secretKey should not exist');
}
});
});
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
"generators/generator-botbuilder/generators/app/templates/*"
],
"nohoist": [
"**/@types/selenium-webdriver"
"**/@types/selenium-webdriver",
"botbuilder/filenamify"
],
"nohoistComments": {
"**/@types/selenium-webdriver": "This package is excluded from the root @types folder as it requires ES2015+, whereas some BotBuilder libraries support ES5+."
"**/@types/selenium-webdriver": "This package is excluded from the root @types folder as it requires ES2015+, whereas some BotBuilder libraries support ES5+.",
"botbuilder/filenamify": "This package is excluded because it's compiled as CJS by tsup as it's ESM-only."
}
},
"scripts": {
Expand Down
Loading
Loading