UNPKG

node-darts

Version:

Node.js Native Addon for Darts (Double-ARray Trie System)

270 lines 10.9 kB
import bindings from 'bindings'; import * as fs from 'fs'; import * as path from 'path'; import { DartsError, FileNotFoundError, InvalidDictionaryError, BuildError } from './errors'; // Load native module let native; try { // Try standard bindings approach first native = bindings('node_darts'); } catch (originalError) { // Only attempt fallback in Windows CI environment const isWindows = process.platform === 'win32'; const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true'; if (isWindows && isCI) { console.warn(`WARNING: Failed to load native module using standard bindings in Windows CI environment: ${originalError}`); console.warn('Attempting to use fallback mechanism to locate the module...'); // Try to find the module in common locations const possiblePaths = [ // Standard build paths path.join(process.cwd(), 'build', 'Release', 'node_darts.node'), path.join(process.cwd(), 'build', 'Debug', 'node_darts.node'), path.join(process.cwd(), 'build', 'node_darts.node'), path.join(process.cwd(), 'build', 'default', 'node_darts.node'), // Output paths path.join(process.cwd(), 'out', 'Release', 'node_darts.node'), path.join(process.cwd(), 'out', 'Debug', 'node_darts.node'), // Direct paths path.join(process.cwd(), 'Release', 'node_darts.node'), path.join(process.cwd(), 'Debug', 'node_darts.node'), // Addon build paths path.join(process.cwd(), 'addon-build', 'release', 'install-root', 'node_darts.node'), path.join(process.cwd(), 'addon-build', 'debug', 'install-root', 'node_darts.node'), path.join(process.cwd(), 'addon-build', 'default', 'install-root', 'node_darts.node'), // Node version specific paths path.join(process.cwd(), 'lib', 'binding', `node-v${process.versions.modules}-${process.platform}-${process.arch}`, 'node_darts.node'), path.join(process.cwd(), 'compiled', process.version.slice(1), process.platform, process.arch, 'node_darts.node'), // Legacy paths path.join(process.cwd(), 'build', 'lib', 'binding', 'node_darts.node'), path.join(process.cwd(), 'lib', 'binding', 'node-v115-win32-x64', 'node_darts.node'), ]; // Log all paths we're checking console.warn('Checking the following paths:'); possiblePaths.forEach((p) => console.warn(` - ${p}`)); // Initialize a variable to track if we found the module let foundModule = false; // Use forEach instead of for...of to satisfy ESLint possiblePaths.forEach((modulePath) => { if (!foundModule && fs.existsSync(modulePath)) { console.warn(`Found native module at: ${modulePath}`); try { // We need to use dynamic require here, but ESLint doesn't like it // So we'll disable the relevant rules for this specific line // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require const dynamicModule = require(modulePath); native = dynamicModule; foundModule = true; console.warn('Successfully loaded native module using fallback mechanism'); } catch (requireError) { console.warn(`Failed to require module at ${modulePath}: ${requireError}`); } } }); if (!foundModule) { console.error('ERROR: Native module not found in any alternative paths'); throw new Error(`Failed to load native module using fallback mechanism. Original error: ${originalError}`); } } else { // In non-Windows or non-CI environments, just throw the original error throw originalError; } } /** * Wrapper class for native module * Adds error handling and provides a TypeScript-friendly interface */ export class DartsNativeWrapper { /** * Creates a dictionary object * @returns dictionary handle */ // eslint-disable-next-line class-methods-use-this createDictionary() { try { const handle = native.createDictionary(); if (handle === null || handle === undefined) { throw new DartsError('Failed to create dictionary'); } return handle; } catch (error) { if (error instanceof DartsError) { throw error; } throw new DartsError(`Failed to create dictionary: ${error instanceof Error ? error.message : String(error)}`); } } /** * Destroys a dictionary object * @param handle dictionary handle */ // eslint-disable-next-line class-methods-use-this destroyDictionary(handle) { try { native.destroyDictionary(handle); } catch (error) { throw new DartsError(`Failed to destroy dictionary: ${error instanceof Error ? error.message : String(error)}`); } } /** * Loads a dictionary file * @param handle dictionary handle * @param filePath path to the dictionary file * @returns true if successful, false otherwise */ // eslint-disable-next-line class-methods-use-this loadDictionary(handle, filePath) { // Check if the file exists if (!fs.existsSync(filePath)) { throw new FileNotFoundError(filePath); } try { const result = native.loadDictionary(handle, filePath); if (result === false) { throw new InvalidDictionaryError(`Failed to load dictionary from ${filePath}`); } return result; } catch (error) { if (error instanceof DartsError) { throw error; } // Detect file not found error from error message const errorMessage = error instanceof Error ? error.message : String(error); if (errorMessage.includes('not found') || errorMessage.includes('No such file')) { throw new FileNotFoundError(filePath); } throw new InvalidDictionaryError(errorMessage); } } /** * Saves a dictionary file * @param handle dictionary handle * @param filePath destination file path * @returns true if successful, false otherwise */ // eslint-disable-next-line class-methods-use-this saveDictionary(handle, filePath) { try { const result = native.saveDictionary(handle, filePath); if (result === false) { throw new DartsError(`Failed to save dictionary to ${filePath}`); } return result; } catch (error) { if (error instanceof DartsError) { throw error; } throw new DartsError(`Failed to save dictionary: ${error instanceof Error ? error.message : String(error)}`); } } /** * Performs an exact match search * @param handle dictionary handle * @param key search key * @returns the corresponding value if found, -1 otherwise */ // eslint-disable-next-line class-methods-use-this exactMatchSearch(handle, key) { try { return native.exactMatchSearch(handle, key); } catch (error) { throw new DartsError(`Failed to perform exact match search: ${error instanceof Error ? error.message : String(error)}`); } } /** * Performs a common prefix search * @param handle dictionary handle * @param key search key * @returns array of found values */ // eslint-disable-next-line class-methods-use-this commonPrefixSearch(handle, key) { try { return native.commonPrefixSearch(handle, key); } catch (error) { throw new DartsError(`Failed to perform common prefix search: ${error instanceof Error ? error.message : String(error)}`); } } /** * Traverses the trie * @param handle dictionary handle * @param key search key * @param callback callback function */ // eslint-disable-next-line class-methods-use-this traverse(handle, key, callback) { try { native.traverse(handle, key, callback); } catch (error) { throw new DartsError(`Failed to traverse: ${error instanceof Error ? error.message : String(error)}`); } } /** * Builds a Double-Array * @param keys array of keys * @param values array of values (indices are used if omitted) * @returns dictionary handle */ // eslint-disable-next-line class-methods-use-this build(keys, values) { try { if (!Array.isArray(keys) || keys.length === 0) { throw new BuildError('Empty keys array'); } // Ensure keys are strings keys.forEach((key) => { if (typeof key !== 'string') { throw new BuildError('All keys must be strings'); } }); // Ensure values are numbers if (values !== undefined) { if (!Array.isArray(values) || values.length !== keys.length) { throw new BuildError('Values array length must match keys array length'); } values.forEach((value) => { if (typeof value !== 'number') { throw new BuildError('All values must be numbers'); } }); } const handle = native.build(keys, values); if (handle === null || handle === undefined) { throw new BuildError('Failed to build dictionary'); } return handle; } catch (error) { if (error instanceof DartsError) { throw error; } throw new BuildError(error instanceof Error ? error.message : String(error)); } } /** * Gets the size of the dictionary * @param handle dictionary handle * @returns size of the dictionary */ // eslint-disable-next-line class-methods-use-this size(handle) { try { return native.size(handle); } catch (error) { throw new DartsError(`Failed to get dictionary size: ${error instanceof Error ? error.message : String(error)}`); } } } // Export singleton instance export const dartsNative = new DartsNativeWrapper(); //# sourceMappingURL=native.js.map