add ts type define and api exports

This commit is contained in:
lion 2025-10-13 15:28:30 +08:00
parent 5a8d7c4152
commit 3cab1bae2e
8 changed files with 185 additions and 41 deletions

83
binding/javascript/index.d.ts vendored Normal file
View File

@ -0,0 +1,83 @@
// Copyright 2022 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// Type definitions for ip2region
// @Author Lion <chenxin619315@gmail.com>
export declare class Header {
version: number;
indexPolicy: number;
createdAt: number;
startIndexPtr: number;
endIndexPtr: number;
ipVersion: number;
runtimePtrBytes: number;
buff: Buffer;
constructor(buff: Buffer);
toString(): string;
}
export declare class Version {
id: number;
name: string;
bytes: number;
indexSize: number;
ipCompareFunc: (ip1: Buffer, ip2: Buffer, offset: number) => number;
constructor(id: number, name: string, bytes: number, indexSize: number, ipCompareFunc: (ip1: Buffer, ip2: Buffer, offset: number) => number);
ipCompare(ip1: Buffer, ip2: Buffer): number;
ipSubCompare(ip1: Buffer, ip2: Buffer, offset: number): number;
toString(): string;
}
export declare class Searcher {
ioCount: number;
version: Version;
handle: number | null;
vectorIndex: Buffer | null;
cBuffer: Buffer | null;
constructor(version: Version, dbPath: string | null, vectorIndex: Buffer | null, cBuffer: Buffer | null);
getIOCount(): number;
search(ip: string | Buffer): string;
read(offset: number, buff: Buffer, stats?: any): void;
close(): void;
}
// Constants
export declare const XdbStructure20: 2;
export declare const XdbStructure30: 3;
export declare const XdbIPv4Id: 4;
export declare const XdbIPv6Id: 6;
export declare const HeaderInfoLength: 256;
export declare const VectorIndexRows: 256;
export declare const VectorIndexCols: 256;
export declare const VectorIndexSize: 8;
// Version instances
export declare const IPv4: Version;
export declare const IPv6: Version;
// Utility functions
export declare function parseIP(ipString: string): Buffer;
export declare function ipToString(ipBytes: Buffer, compress?: boolean): string;
export declare function ipBytesString(ipBytes: Buffer): string;
export declare function ipSubCompare(ip1: Buffer, buff: Buffer, offset: number): number;
export declare function ipCompare(ip1: Buffer, ip2: Buffer): number;
export declare function versionFromName(name: string): Version | null;
export declare function versionFromHeader(h: Header): Version | null;
// File operations
export declare function loadHeader(fd: number): Header;
export declare function loadHeaderFromFile(dbPath: string): Header;
export declare function loadVectorIndex(fd: number): Buffer;
export declare function loadVectorIndexFromFile(dbPath: string): Buffer;
export declare function loadContent(fd: number): Buffer;
export declare function loadContentFromFile(dbPath: string): Buffer;
// Searcher factory functions
export declare function newWithFileOnly(version: Version, dbPath: string): Searcher;
export declare function newWithVectorIndex(version: Version, dbPath: string, vectorIndex: Buffer): Searcher;
export declare function newWithBuffer(version: Version, cBuffer: Buffer): Searcher;

View File

@ -0,0 +1,41 @@
// Copyright 2022 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// ip2region JavaScript binding with IPv4 and IPv6 support.
// @Author Lion <chenxin619315@gmail.com>
export {
Searcher,
newWithFileOnly,
newWithVectorIndex,
newWithBuffer
} from './searcher.js';
export {
Header,
Version,
IPv4,
IPv6,
XdbStructure20,
XdbStructure30,
XdbIPv4Id,
XdbIPv6Id,
HeaderInfoLength,
VectorIndexRows,
VectorIndexCols,
VectorIndexSize,
parseIP,
ipToString,
ipBytesString,
ipSubCompare,
ipCompare,
versionFromName,
versionFromHeader,
loadHeader,
loadHeaderFromFile,
loadVectorIndex,
loadVectorIndexFromFile,
loadContent,
loadContentFromFile
} from './util.js';

View File

@ -1,10 +0,0 @@
// Copyright 2022 The Ip2Region Authors. All rights reserved.
// Use of this source code is governed by a Apache2.0-style
// license that can be found in the LICENSE file.
// ip2region.js
// @Author Lion <chenxin619315@gmail.com>
// Re-export all utilities and searcher functions
export * from './util.js';
export * from './searcher.js';

View File

@ -3,7 +3,8 @@
"version": "3.0.0", "version": "3.0.0",
"description": "javascript binding for ip2region with both IPv4 and IPv6 supported ", "description": "javascript binding for ip2region with both IPv4 and IPv6 supported ",
"type": "module", "type": "module",
"main": "ip2region.js", "main": "index.js",
"types": "index.d.ts",
"scripts": { "scripts": {
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest" "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest"
}, },
@ -36,6 +37,9 @@
}, },
"homepage": "https://github.com/lionsoul2014/ip2region#readme", "homepage": "https://github.com/lionsoul2014/ip2region#readme",
"devDependencies": { "devDependencies": {
"jest": "^30.2.0" "@types/jest": "^30.0.0",
"jest": "^30.2.0",
"ts-jest": "^29.4.5",
"typescript": "^5.9.3"
} }
} }

View File

@ -31,7 +31,7 @@ export class Searcher {
return this.ioCount; return this.ioCount;
} }
search(ip) { async search(ip) {
// check and parse the string ip // check and parse the string ip
const ipBytes = Buffer.isBuffer(ip) ? ip : parseIP(ip); const ipBytes = Buffer.isBuffer(ip) ? ip : parseIP(ip);

View File

@ -5,8 +5,7 @@
// searcher search tester // searcher search tester
// @Author Lion <chenxin619315@gmail.com> // @Author Lion <chenxin619315@gmail.com>
import {IPv4, IPv6, parseIP, ipToString} from '../util.js'; import {IPv4, IPv6, parseIP, ipToString, newWithFileOnly} from '../index.js';
import {newWithFileOnly} from '../searcher.js';
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
@ -16,28 +15,26 @@ const dbPath = {
v6: path.join(__dirname, '..', '..', '..', 'data', 'ip2region_v6.xdb') v6: path.join(__dirname, '..', '..', '..', 'data', 'ip2region_v6.xdb')
} }
test('ipv4 search test', () => { test('ipv4 search test', async () => {
try { let searcher = newWithFileOnly(IPv4, dbPath.v4);
let searcher = newWithFileOnly(IPv4, dbPath.v4); let ip_list = [
let ip_list = [ '1.0.0.0',
'1.0.0.0', parseIP('113.118.112.93'),
parseIP('113.118.112.93'), '240e:3b7::'
'240e:3b7::' ];
];
for (var i = 0; i < ip_list.length; i++) { for (var i = 0; i < ip_list.length; i++) {
let ip = ip_list[i]; let ip = ip_list[i];
let region = searcher.search(ip); searcher.search(ip).then((region)=>{
let ipStr = Buffer.isBuffer(ip) ? ipToString(ip) : ip; let ipStr = Buffer.isBuffer(ip) ? ipToString(ip) : ip;
console.log(`search(${ipStr}): {region: ${region}, ioCount: ${searcher.getIOCount()}}`); console.log(`search(${ipStr}): {region: ${region}, ioCount: ${searcher.getIOCount()}}`);
} }).catch((err) => {
} catch (e) { console.log(`${err.message}`);
console.log(`${e.message}`); });
} }
}); });
test('ipv6 search test', async () => { test('ipv6 search test', async () => {
try {
let searcher = newWithFileOnly(IPv6, dbPath.v6); let searcher = newWithFileOnly(IPv6, dbPath.v6);
let ip_list = [ let ip_list = [
'2a02:26f7:c409:4001::', '2a02:26f7:c409:4001::',
@ -48,11 +45,11 @@ test('ipv6 search test', async () => {
for (var i = 0; i < ip_list.length; i++) { for (var i = 0; i < ip_list.length; i++) {
let ip = ip_list[i]; let ip = ip_list[i];
let region = searcher.search(ip); searcher.search(ip).then((region)=>{
let ipStr = Buffer.isBuffer(ip) ? ipToString(ip) : ip; let ipStr = Buffer.isBuffer(ip) ? ipToString(ip) : ip;
console.log(`search(${ipStr}): {region: ${region}, ioCount: ${searcher.getIOCount()}}`); console.log(`search(${ipStr}): {region: ${region}, ioCount: ${searcher.getIOCount()}}`);
}).catch((err) => {
console.log(`${err.message}`);
});
} }
} catch (e) {
console.log(`${e.message}`);
}
}); });

View File

@ -5,10 +5,13 @@
// searcher new tester // searcher new tester
// @Author Lion <chenxin619315@gmail.com> // @Author Lion <chenxin619315@gmail.com>
import {IPv4, IPv6, loadVectorIndexFromFile, XdbIPv4Id, loadContentFromFile} from '../util.js';
import {newWithFileOnly, newWithVectorIndex, newWithBuffer} from '../searcher.js';
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import {
IPv4, IPv6, XdbIPv4Id,
loadVectorIndexFromFile, loadContentFromFile,
newWithFileOnly, newWithVectorIndex, newWithBuffer
} from '../index.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const dbPath = { const dbPath = {
@ -29,14 +32,14 @@ function _get_creater_list(version) {
}]; }];
} }
test('ipv4 searcher test', () => { test('ipv4 searcher test', async () => {
const ip_Str = '120.229.45.92'; const ip_Str = '120.229.45.92';
const c_list = _get_creater_list(IPv4); const c_list = _get_creater_list(IPv4);
try { try {
let bRegion = null; let bRegion = null;
for (var i = 0; i < c_list.length; i++) { for (var i = 0; i < c_list.length; i++) {
const meta = c_list[i](); const meta = c_list[i]();
const region = meta[1].search(ip_Str); const region = await meta[1].search(ip_Str);
if (bRegion != null) { if (bRegion != null) {
expect(region).toBe(region); expect(region).toBe(region);
} }
@ -55,7 +58,7 @@ test('ipv6 searcher test', async () => {
let bRegion = null; let bRegion = null;
for (var i = 0; i < c_list.length; i++) { for (var i = 0; i < c_list.length; i++) {
const meta = c_list[i](); const meta = c_list[i]();
const region = meta[1].search(ip_Str); const region = await meta[1].search(ip_Str);
if (bRegion != null) { if (bRegion != null) {
expect(region).toBe(region); expect(region).toBe(region);
} }

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "node",
"allowJs": true,
"checkJs": false,
"declaration": true,
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true
},
"include": [
"*.js",
"*.d.ts",
"tests/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}