diff --git a/.github/scripts/build.mjs b/.github/scripts/build.mjs index fee3640e..a7144c0c 100644 --- a/.github/scripts/build.mjs +++ b/.github/scripts/build.mjs @@ -2,7 +2,7 @@ import util from 'node:util'; import process from 'node:process'; -import fs from 'node:fs/promises'; +import fs, { readFile } from 'node:fs/promises'; import child_process from 'node:child_process'; import events from 'node:events'; import path from 'node:path'; @@ -83,8 +83,16 @@ async function buildBindings(args, pkg) { if (process.platform === 'darwin' && process.arch === 'arm64') { // The "arm64" build is actually a universal binary - const armTar = `kerberos-v${pkg.version}-napi-v4-darwin-arm64.tar.gz`; - const x64Tar = `kerberos-v${pkg.version}-napi-v4-darwin-x64.tar.gz`; + // @ts-ignore + const { + binary: { + napi_versions: [ + napiVersion + ] + } + } = JSON.parse(await readFile(resolveRoot('package.json'), 'utf-8')); + const armTar = `kerberos-v${pkg.version}-napi-v${napiVersion}-darwin-arm64.tar.gz`; + const x64Tar = `kerberos-v${pkg.version}-napi-v${napiVersion}-darwin-x64.tar.gz`; await fs.copyFile(resolveRoot('prebuilds', armTar), resolveRoot('prebuilds', x64Tar)); } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daaef6bd..0c0f998f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-2022] + fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -40,6 +41,7 @@ jobs: strategy: matrix: linux_arch: [s390x, arm64, amd64] + fail-fast: false steps: - uses: actions/checkout@v4 @@ -69,6 +71,7 @@ jobs: strategy: matrix: freebsd_arch: [aarch64, amd64] + fail-fast: false steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/webpack.yml b/.github/workflows/webpack.yml index 0f493048..046d6e23 100644 --- a/.github/workflows/webpack.yml +++ b/.github/workflows/webpack.yml @@ -21,7 +21,7 @@ jobs: - name: "Install dependencies" shell: bash run: | - npm install + npm install --ignore-scripts - name: "Install dependencies in the Webpack bundle test package" shell: bash diff --git a/lib/index.js b/lib/index.js index 6ba3cbfa..193b460f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -224,6 +224,13 @@ async function initializeServer(service) { return await promisifiedInitializeServer.call(this, service); } +/** + * @private + * + * The NAPI version kerberos is configured to use, defined in kerberos.h. + */ +const definedNapiVersion = kerberos.definedNapiVersion; + module.exports = { initializeClient, initializeServer, @@ -246,5 +253,6 @@ module.exports = { GSS_MECH_OID_KRB5, GSS_MECH_OID_SPNEGO, - version + version, + definedNapiVersion }; diff --git a/package-lock.json b/package-lock.json index 45a4a275..5a290057 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "node-addon-api": "^6.1.0", + "node-addon-api": "^8.5.0", "prebuild-install": "^7.1.3" }, "devDependencies": { @@ -4168,9 +4168,13 @@ } }, "node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } }, "node_modules/node-api-headers": { "version": "1.1.0", diff --git a/package.json b/package.json index bdadc519..716c83bb 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "url": "https://jira.mongodb.org/projects/NODE/issues/" }, "dependencies": { - "node-addon-api": "^6.1.0", + "node-addon-api": "^8.5.0", "prebuild-install": "^7.1.3" }, "devDependencies": { @@ -69,7 +69,7 @@ }, "binary": { "napi_versions": [ - 4 + 9 ] }, "license": "Apache-2.0", diff --git a/src/kerberos.cc b/src/kerberos.cc index a79dfdd4..334f4b48 100644 --- a/src/kerberos.cc +++ b/src/kerberos.cc @@ -1,4 +1,5 @@ #include "kerberos.h" + #include "kerberos_worker.h" /// KerberosClient @@ -13,8 +14,8 @@ struct InstanceData { }; static constexpr napi_property_attributes writable_and_configurable = - static_cast( - static_cast(napi_writable) | static_cast(napi_configurable)); + static_cast(static_cast(napi_writable) | + static_cast(napi_configurable)); inline String NewMaybeWideString(Env env, const char* str) { return String::New(env, str); @@ -22,13 +23,13 @@ inline String NewMaybeWideString(Env env, const char* str) { #ifdef _WIN32 inline String NewMaybeWideString(Env env, const WCHAR* str) { static_assert(sizeof(std::wstring::value_type) == sizeof(std::u16string::value_type), - "wstring and u16string have the same value type on Windows"); + "wstring and u16string have the same value type on Windows"); std::wstring wstr(str); std::u16string u16(wstr.begin(), wstr.end()); return String::New(env, u16); } #endif -} +} // namespace std::string ToStringWithNonStringAsEmpty(Napi::Value value) { if (!value.IsString()) { @@ -38,7 +39,8 @@ std::string ToStringWithNonStringAsEmpty(Napi::Value value) { } int KerberosClient::ParseWrapOptionsProtect(const Napi::Object& options) { - if (!options.Has("protect")) return 0; + if (!options.Has("protect")) + return 0; if (!options.Get("protect").IsBoolean()) { throw TypeError::New(options.Env(), "options.protect must be a boolean."); @@ -49,18 +51,16 @@ int KerberosClient::ParseWrapOptionsProtect(const Napi::Object& options) { } Function KerberosClient::Init(Napi::Env env) { - return - DefineClass(env, - "KerberosClient", - { - InstanceMethod("step", &KerberosClient::Step, writable_and_configurable), - InstanceMethod("wrap", &KerberosClient::WrapData, writable_and_configurable), - InstanceMethod("unwrap", &KerberosClient::UnwrapData, writable_and_configurable), - InstanceAccessor("username", &KerberosClient::UserNameGetter, nullptr), - InstanceAccessor("response", &KerberosClient::ResponseGetter, nullptr), - InstanceAccessor("responseConf", &KerberosClient::ResponseConfGetter, nullptr), - InstanceAccessor("contextComplete", &KerberosClient::ContextCompleteGetter, nullptr) - }); + return DefineClass( + env, + "KerberosClient", + {InstanceMethod("step", &KerberosClient::Step, writable_and_configurable), + InstanceMethod("wrap", &KerberosClient::WrapData, writable_and_configurable), + InstanceMethod("unwrap", &KerberosClient::UnwrapData, writable_and_configurable), + InstanceAccessor("username", &KerberosClient::UserNameGetter, nullptr), + InstanceAccessor("response", &KerberosClient::ResponseGetter, nullptr), + InstanceAccessor("responseConf", &KerberosClient::ResponseConfGetter, nullptr), + InstanceAccessor("contextComplete", &KerberosClient::ContextCompleteGetter, nullptr)}); } Object KerberosClient::NewInstance(Napi::Env env, std::shared_ptr state) { @@ -71,8 +71,7 @@ Object KerberosClient::NewInstance(Napi::Env env, std::shared_ptr KerberosClient::state() const { return _state; @@ -102,16 +101,14 @@ Value KerberosClient::ContextCompleteGetter(const CallbackInfo& info) { /// KerberosServer Function KerberosServer::Init(Napi::Env env) { - return - DefineClass(env, - "KerberosServer", - { - InstanceMethod("step", &KerberosServer::Step, writable_and_configurable), - InstanceAccessor("username", &KerberosServer::UserNameGetter, nullptr), - InstanceAccessor("response", &KerberosServer::ResponseGetter, nullptr), - InstanceAccessor("targetName", &KerberosServer::TargetNameGetter, nullptr), - InstanceAccessor("contextComplete", &KerberosServer::ContextCompleteGetter, nullptr) - }); + return DefineClass( + env, + "KerberosServer", + {InstanceMethod("step", &KerberosServer::Step, writable_and_configurable), + InstanceAccessor("username", &KerberosServer::UserNameGetter, nullptr), + InstanceAccessor("response", &KerberosServer::ResponseGetter, nullptr), + InstanceAccessor("targetName", &KerberosServer::TargetNameGetter, nullptr), + InstanceAccessor("contextComplete", &KerberosServer::ContextCompleteGetter, nullptr)}); } Object KerberosServer::NewInstance(Napi::Env env, std::shared_ptr state) { @@ -122,8 +119,7 @@ Object KerberosServer::NewInstance(Napi::Env env, std::shared_ptr KerberosServer::state() const { return _state; @@ -154,31 +150,8 @@ Value KerberosServer::ContextCompleteGetter(const CallbackInfo& info) { return Boolean::New(Env(), state()->context_complete); } -void TestMethod(const CallbackInfo& info) { - std::string string = info[0].ToString(); - bool shouldError = info[1].ToBoolean(); - - std::string optionalString; - Function callback; - if (info[2].IsFunction()) { - callback = info[2].As(); - } else { - optionalString = info[2].ToString(); - callback = info[3].As(); - } - - KerberosWorker::Run(callback, "kerberos:TestMethod", [=](KerberosWorker::SetOnFinishedHandler onFinished) { - return onFinished([=](KerberosWorker* worker) { - Napi::Env env = worker->Env(); - if (shouldError) { - worker->Call(std::initializer_list - { Error::New(env).Value(), env.Null() }); - } else { - worker->Call(std::initializer_list - { env.Null(), String::New(env, optionalString) }); - } - }); - }); +Value GetDefinedNapiVersion(const CallbackInfo& info) { + return String::New(info.Env(), std::to_string(NAPI_VERSION)); } static Object Init(Env env, Object exports) { @@ -190,18 +163,16 @@ static Object Init(Env env, Object exports) { Function KerberosServerCtor = KerberosServer::Init(env); exports["KerberosClient"] = KerberosClientCtor; exports["KerberosServer"] = KerberosServerCtor; - env.SetInstanceData(new InstanceData { - Reference::New(KerberosClientCtor, 1), - Reference::New(KerberosServerCtor, 1) - }); + env.SetInstanceData(new InstanceData{Reference::New(KerberosClientCtor, 1), + Reference::New(KerberosServerCtor, 1)}); exports["initializeClient"] = Function::New(env, InitializeClient); exports["initializeServer"] = Function::New(env, InitializeServer); exports["principalDetails"] = Function::New(env, PrincipalDetails); exports["checkPassword"] = Function::New(env, CheckPassword); - exports["_testMethod"] = Function::New(env, TestMethod); + exports["definedNapiVersion"] = Function::New(env, GetDefinedNapiVersion); return exports; } NODE_API_MODULE(kerberos, Init) -} +} // namespace node_kerberos diff --git a/src/kerberos.h b/src/kerberos.h index deec6e33..1917de85 100644 --- a/src/kerberos.h +++ b/src/kerberos.h @@ -1,15 +1,10 @@ #ifndef KERBEROS_NATIVE_EXTENSION_H #define KERBEROS_NATIVE_EXTENSION_H -// We generally only target N-API version 4, but the instance data -// feature is only available in N-API version 6. However, it is -// available in all Node.js versions that have N-API version 4 -#define NAPI_VERSION 6 -// as an experimental feature (that has not been changed since then). -#define NAPI_EXPERIMENTAL -#define NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT +#define NAPI_VERSION 9 #include + #include "kerberos_common.h" namespace node_kerberos { @@ -69,11 +64,10 @@ void InitializeClient(const Napi::CallbackInfo& info); void InitializeServer(const Napi::CallbackInfo& info); void CheckPassword(const Napi::CallbackInfo& info); -// NOTE: explicitly used for unit testing `defineOperation`, not meant to be exported -void TestMethod(const Napi::CallbackInfo& info); - std::string ToStringWithNonStringAsEmpty(Napi::Value value); -} +Napi::Value GetDefinedNapiVersion(const Napi::CallbackInfo& info); + +} // namespace node_kerberos #endif // KERBEROS_NATIVE_EXTENSION_H diff --git a/test/bundling/webpack/install_kerberos.cjs b/test/bundling/webpack/install_kerberos.cjs index bf7777b9..825eeded 100644 --- a/test/bundling/webpack/install_kerberos.cjs +++ b/test/bundling/webpack/install_kerberos.cjs @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ 'use strict'; const { execSync } = require('node:child_process'); @@ -19,6 +20,7 @@ console.log(`kerberos Version: ${kerberosVersion}`); xtrace('npm pack --pack-destination test/bundling/webpack', { cwd: kerberosRoot }); -xtrace(`npm install --no-save kerberos-${kerberosVersion}.tgz`); +// --ignore-scripts: don't worry about downloading prebuilt binaries, we're only bundling +xtrace(`npm install --ignore-scripts --no-save kerberos-${kerberosVersion}.tgz`); console.log('kerberos installed!'); diff --git a/test/kerberos_tests.js b/test/kerberos_tests.js index bdbe20df..060c8778 100644 --- a/test/kerberos_tests.js +++ b/test/kerberos_tests.js @@ -221,4 +221,8 @@ describe('Kerberos', function () { }); }); }); + + it('definedNapiVersion() returns 9', function () { + expect(kerberos.definedNapiVersion()).to.equal('9'); + }); });