@samyok/annoy 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ type Metric = "angular" | "euclidean" | "manhattan" | "dot";
2
+ interface NearestNeighborsResult {
3
+ neighbors: number[];
4
+ distances: number[];
5
+ }
6
+ declare class AnnoyIndex {
7
+ private index;
8
+ constructor(f: number, metric?: Metric);
9
+ addItem(index: number, vector: number[]): void;
10
+ build(numTrees: number, numThreads?: number): void;
11
+ unbuild(): void;
12
+ save(filename: string, prefault?: boolean): void;
13
+ load(filename: string, prefault?: boolean): void;
14
+ unload(): void;
15
+ getDistance(i: number, j: number): number;
16
+ getNnsByItem(item: number, n: number, searchK: number, includeDistances: true): NearestNeighborsResult;
17
+ getNnsByItem(item: number, n: number, searchK?: number, includeDistances?: false): number[];
18
+ getNnsByVector(vector: number[], n: number, searchK: number, includeDistances: true): NearestNeighborsResult;
19
+ getNnsByVector(vector: number[], n: number, searchK?: number, includeDistances?: false): number[];
20
+ getNItems(): number;
21
+ getNTrees(): number;
22
+ getItem(item: number): number[];
23
+ setSeed(seed: number): void;
24
+ onDiskBuild(filename: string): void;
25
+ verbose(v: boolean): void;
26
+ getF(): number;
27
+ }
28
+
29
+ export { AnnoyIndex, type Metric, type NearestNeighborsResult, AnnoyIndex as default };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export type Metric = "angular" | "euclidean" | "manhattan" | "dot";
2
- export interface NearestNeighborsResult {
1
+ type Metric = "angular" | "euclidean" | "manhattan" | "dot";
2
+ interface NearestNeighborsResult {
3
3
  neighbors: number[];
4
4
  distances: number[];
5
5
  }
6
- export declare class AnnoyIndex {
6
+ declare class AnnoyIndex {
7
7
  private index;
8
8
  constructor(f: number, metric?: Metric);
9
9
  addItem(index: number, vector: number[]): void;
@@ -25,4 +25,5 @@ export declare class AnnoyIndex {
25
25
  verbose(v: boolean): void;
26
26
  getF(): number;
27
27
  }
28
- export default AnnoyIndex;
28
+
29
+ export { AnnoyIndex, type Metric, type NearestNeighborsResult, AnnoyIndex as default };
package/dist/index.js CHANGED
@@ -1,103 +1,122 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AnnoyIndex: () => AnnoyIndex,
34
+ default: () => index_default
17
35
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_module = require("module");
38
+ var path = __toESM(require("path"));
39
+ var _require = (0, import_module.createRequire)(__filename);
40
+ var addon = _require(
41
+ path.join(__dirname, "..", "build", "Release", "annoy.node")
42
+ );
43
+ var AnnoyIndex = class {
44
+ constructor(f, metric = "angular") {
45
+ const constructors = {
46
+ angular: addon.AnnoyIndexAngular,
47
+ euclidean: addon.AnnoyIndexEuclidean,
48
+ manhattan: addon.AnnoyIndexManhattan,
49
+ dot: addon.AnnoyIndexDotProduct
33
50
  };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.AnnoyIndex = void 0;
37
- const path = __importStar(require("path"));
38
- const addon = require(path.join(__dirname, "..", "build", "Release", "annoy.node"));
39
- class AnnoyIndex {
40
- constructor(f, metric = "angular") {
41
- const constructors = {
42
- angular: addon.AnnoyIndexAngular,
43
- euclidean: addon.AnnoyIndexEuclidean,
44
- manhattan: addon.AnnoyIndexManhattan,
45
- dot: addon.AnnoyIndexDotProduct,
46
- };
47
- const Ctor = constructors[metric];
48
- if (!Ctor) {
49
- throw new Error(`Unknown metric "${metric}". Use: angular, euclidean, manhattan, dot`);
50
- }
51
- this.index = new Ctor(f);
52
- }
53
- addItem(index, vector) {
54
- this.index.addItem(index, vector);
55
- }
56
- build(numTrees, numThreads = -1) {
57
- this.index.build(numTrees, numThreads);
58
- }
59
- unbuild() {
60
- this.index.unbuild();
61
- }
62
- save(filename, prefault = false) {
63
- this.index.save(filename, prefault);
64
- }
65
- load(filename, prefault = false) {
66
- this.index.load(filename, prefault);
67
- }
68
- unload() {
69
- this.index.unload();
70
- }
71
- getDistance(i, j) {
72
- return this.index.getDistance(i, j);
73
- }
74
- getNnsByItem(item, n, searchK = -1, includeDistances = false) {
75
- return this.index.getNnsByItem(item, n, searchK, includeDistances);
76
- }
77
- getNnsByVector(vector, n, searchK = -1, includeDistances = false) {
78
- return this.index.getNnsByVector(vector, n, searchK, includeDistances);
79
- }
80
- getNItems() {
81
- return this.index.getNItems();
82
- }
83
- getNTrees() {
84
- return this.index.getNTrees();
85
- }
86
- getItem(item) {
87
- return this.index.getItem(item);
88
- }
89
- setSeed(seed) {
90
- this.index.setSeed(seed);
91
- }
92
- onDiskBuild(filename) {
93
- this.index.onDiskBuild(filename);
94
- }
95
- verbose(v) {
96
- this.index.verbose(v);
97
- }
98
- getF() {
99
- return this.index.getF();
100
- }
101
- }
102
- exports.AnnoyIndex = AnnoyIndex;
103
- exports.default = AnnoyIndex;
51
+ const Ctor = constructors[metric];
52
+ if (!Ctor) {
53
+ throw new Error(
54
+ `Unknown metric "${metric}". Use: angular, euclidean, manhattan, dot`
55
+ );
56
+ }
57
+ this.index = new Ctor(f);
58
+ }
59
+ addItem(index, vector) {
60
+ this.index.addItem(index, vector);
61
+ }
62
+ build(numTrees, numThreads = -1) {
63
+ this.index.build(numTrees, numThreads);
64
+ }
65
+ unbuild() {
66
+ this.index.unbuild();
67
+ }
68
+ save(filename, prefault = false) {
69
+ this.index.save(filename, prefault);
70
+ }
71
+ load(filename, prefault = false) {
72
+ this.index.load(filename, prefault);
73
+ }
74
+ unload() {
75
+ this.index.unload();
76
+ }
77
+ getDistance(i, j) {
78
+ return this.index.getDistance(i, j);
79
+ }
80
+ getNnsByItem(item, n, searchK = -1, includeDistances = false) {
81
+ return this.index.getNnsByItem(
82
+ item,
83
+ n,
84
+ searchK,
85
+ includeDistances
86
+ );
87
+ }
88
+ getNnsByVector(vector, n, searchK = -1, includeDistances = false) {
89
+ return this.index.getNnsByVector(
90
+ vector,
91
+ n,
92
+ searchK,
93
+ includeDistances
94
+ );
95
+ }
96
+ getNItems() {
97
+ return this.index.getNItems();
98
+ }
99
+ getNTrees() {
100
+ return this.index.getNTrees();
101
+ }
102
+ getItem(item) {
103
+ return this.index.getItem(item);
104
+ }
105
+ setSeed(seed) {
106
+ this.index.setSeed(seed);
107
+ }
108
+ onDiskBuild(filename) {
109
+ this.index.onDiskBuild(filename);
110
+ }
111
+ verbose(v) {
112
+ this.index.verbose(v);
113
+ }
114
+ getF() {
115
+ return this.index.getF();
116
+ }
117
+ };
118
+ var index_default = AnnoyIndex;
119
+ // Annotate the CommonJS export names for ESM import in node:
120
+ 0 && (module.exports = {
121
+ AnnoyIndex
122
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,95 @@
1
+ // node_modules/tsup/assets/esm_shims.js
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ var getFilename = () => fileURLToPath(import.meta.url);
5
+ var getDirname = () => path.dirname(getFilename());
6
+ var __dirname = /* @__PURE__ */ getDirname();
7
+ var __filename = /* @__PURE__ */ getFilename();
8
+
9
+ // src/index.ts
10
+ import { createRequire } from "module";
11
+ import * as path2 from "path";
12
+ var _require = createRequire(__filename);
13
+ var addon = _require(
14
+ path2.join(__dirname, "..", "build", "Release", "annoy.node")
15
+ );
16
+ var AnnoyIndex = class {
17
+ constructor(f, metric = "angular") {
18
+ const constructors = {
19
+ angular: addon.AnnoyIndexAngular,
20
+ euclidean: addon.AnnoyIndexEuclidean,
21
+ manhattan: addon.AnnoyIndexManhattan,
22
+ dot: addon.AnnoyIndexDotProduct
23
+ };
24
+ const Ctor = constructors[metric];
25
+ if (!Ctor) {
26
+ throw new Error(
27
+ `Unknown metric "${metric}". Use: angular, euclidean, manhattan, dot`
28
+ );
29
+ }
30
+ this.index = new Ctor(f);
31
+ }
32
+ addItem(index, vector) {
33
+ this.index.addItem(index, vector);
34
+ }
35
+ build(numTrees, numThreads = -1) {
36
+ this.index.build(numTrees, numThreads);
37
+ }
38
+ unbuild() {
39
+ this.index.unbuild();
40
+ }
41
+ save(filename, prefault = false) {
42
+ this.index.save(filename, prefault);
43
+ }
44
+ load(filename, prefault = false) {
45
+ this.index.load(filename, prefault);
46
+ }
47
+ unload() {
48
+ this.index.unload();
49
+ }
50
+ getDistance(i, j) {
51
+ return this.index.getDistance(i, j);
52
+ }
53
+ getNnsByItem(item, n, searchK = -1, includeDistances = false) {
54
+ return this.index.getNnsByItem(
55
+ item,
56
+ n,
57
+ searchK,
58
+ includeDistances
59
+ );
60
+ }
61
+ getNnsByVector(vector, n, searchK = -1, includeDistances = false) {
62
+ return this.index.getNnsByVector(
63
+ vector,
64
+ n,
65
+ searchK,
66
+ includeDistances
67
+ );
68
+ }
69
+ getNItems() {
70
+ return this.index.getNItems();
71
+ }
72
+ getNTrees() {
73
+ return this.index.getNTrees();
74
+ }
75
+ getItem(item) {
76
+ return this.index.getItem(item);
77
+ }
78
+ setSeed(seed) {
79
+ this.index.setSeed(seed);
80
+ }
81
+ onDiskBuild(filename) {
82
+ this.index.onDiskBuild(filename);
83
+ }
84
+ verbose(v) {
85
+ this.index.verbose(v);
86
+ }
87
+ getF() {
88
+ return this.index.getF();
89
+ }
90
+ };
91
+ var index_default = AnnoyIndex;
92
+ export {
93
+ AnnoyIndex,
94
+ index_default as default
95
+ };
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/test.d.ts CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+
2
+ export { }
package/dist/test.js CHANGED
@@ -1,171 +1,244 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/index.ts
26
+ var import_module = require("module");
27
+ var path = __toESM(require("path"));
28
+ var _require = (0, import_module.createRequire)(__filename);
29
+ var addon = _require(
30
+ path.join(__dirname, "..", "build", "Release", "annoy.node")
31
+ );
32
+ var AnnoyIndex = class {
33
+ constructor(f, metric = "angular") {
34
+ const constructors = {
35
+ angular: addon.AnnoyIndexAngular,
36
+ euclidean: addon.AnnoyIndexEuclidean,
37
+ manhattan: addon.AnnoyIndexManhattan,
38
+ dot: addon.AnnoyIndexDotProduct
33
39
  };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- const index_1 = require("./index");
37
- const fs = __importStar(require("fs"));
38
- const path = __importStar(require("path"));
39
- const DIMS = 40;
40
- const NUM_ITEMS = 1000;
41
- const NUM_TREES = 10;
42
- const tmpFile = path.join(__dirname, "..", "test_index.ann");
43
- let passed = 0;
44
- let failed = 0;
45
- function assert(condition, msg) {
46
- if (condition) {
47
- passed++;
48
- console.log(` PASS: ${msg}`);
49
- }
50
- else {
51
- failed++;
52
- console.error(` FAIL: ${msg}`);
40
+ const Ctor = constructors[metric];
41
+ if (!Ctor) {
42
+ throw new Error(
43
+ `Unknown metric "${metric}". Use: angular, euclidean, manhattan, dot`
44
+ );
53
45
  }
46
+ this.index = new Ctor(f);
47
+ }
48
+ addItem(index, vector) {
49
+ this.index.addItem(index, vector);
50
+ }
51
+ build(numTrees, numThreads = -1) {
52
+ this.index.build(numTrees, numThreads);
53
+ }
54
+ unbuild() {
55
+ this.index.unbuild();
56
+ }
57
+ save(filename, prefault = false) {
58
+ this.index.save(filename, prefault);
59
+ }
60
+ load(filename, prefault = false) {
61
+ this.index.load(filename, prefault);
62
+ }
63
+ unload() {
64
+ this.index.unload();
65
+ }
66
+ getDistance(i, j) {
67
+ return this.index.getDistance(i, j);
68
+ }
69
+ getNnsByItem(item, n, searchK = -1, includeDistances = false) {
70
+ return this.index.getNnsByItem(
71
+ item,
72
+ n,
73
+ searchK,
74
+ includeDistances
75
+ );
76
+ }
77
+ getNnsByVector(vector, n, searchK = -1, includeDistances = false) {
78
+ return this.index.getNnsByVector(
79
+ vector,
80
+ n,
81
+ searchK,
82
+ includeDistances
83
+ );
84
+ }
85
+ getNItems() {
86
+ return this.index.getNItems();
87
+ }
88
+ getNTrees() {
89
+ return this.index.getNTrees();
90
+ }
91
+ getItem(item) {
92
+ return this.index.getItem(item);
93
+ }
94
+ setSeed(seed) {
95
+ this.index.setSeed(seed);
96
+ }
97
+ onDiskBuild(filename) {
98
+ this.index.onDiskBuild(filename);
99
+ }
100
+ verbose(v) {
101
+ this.index.verbose(v);
102
+ }
103
+ getF() {
104
+ return this.index.getF();
105
+ }
106
+ };
107
+
108
+ // src/test.ts
109
+ var fs = __toESM(require("fs"));
110
+ var path2 = __toESM(require("path"));
111
+ var DIMS = 40;
112
+ var NUM_ITEMS = 1e3;
113
+ var NUM_TREES = 10;
114
+ var tmpFile = path2.join(__dirname, "..", "test_index.ann");
115
+ var passed = 0;
116
+ var failed = 0;
117
+ function assert(condition, msg) {
118
+ if (condition) {
119
+ passed++;
120
+ console.log(` PASS: ${msg}`);
121
+ } else {
122
+ failed++;
123
+ console.error(` FAIL: ${msg}`);
124
+ }
54
125
  }
55
126
  function randomVector(dims) {
56
- return Array.from({ length: dims }, () => Math.random() * 2 - 1);
127
+ return Array.from({ length: dims }, () => Math.random() * 2 - 1);
57
128
  }
58
129
  function cleanup() {
59
- try {
60
- fs.unlinkSync(tmpFile);
61
- }
62
- catch { }
130
+ try {
131
+ fs.unlinkSync(tmpFile);
132
+ } catch {
133
+ }
63
134
  }
64
135
  console.log("=== annoy-node test suite ===\n");
65
- // Test 1: Basic build and query (Angular)
66
136
  console.log("Test 1: Build and query (Angular)");
67
137
  {
68
- const index = new index_1.AnnoyIndex(DIMS, "angular");
69
- for (let i = 0; i < NUM_ITEMS; i++) {
70
- index.addItem(i, randomVector(DIMS));
71
- }
72
- index.build(NUM_TREES);
73
- assert(index.getNItems() === NUM_ITEMS, `getNItems() === ${NUM_ITEMS}`);
74
- assert(index.getNTrees() === NUM_TREES, `getNTrees() === ${NUM_TREES}`);
75
- assert(index.getF() === DIMS, `getF() === ${DIMS}`);
76
- const neighbors = index.getNnsByItem(0, 10);
77
- assert(Array.isArray(neighbors), "getNnsByItem returns array");
78
- assert(neighbors.length === 10, "returns 10 neighbors");
79
- assert(neighbors[0] === 0, "nearest neighbor of item 0 is itself");
138
+ const index = new AnnoyIndex(DIMS, "angular");
139
+ for (let i = 0; i < NUM_ITEMS; i++) {
140
+ index.addItem(i, randomVector(DIMS));
141
+ }
142
+ index.build(NUM_TREES);
143
+ assert(index.getNItems() === NUM_ITEMS, `getNItems() === ${NUM_ITEMS}`);
144
+ assert(index.getNTrees() === NUM_TREES, `getNTrees() === ${NUM_TREES}`);
145
+ assert(index.getF() === DIMS, `getF() === ${DIMS}`);
146
+ const neighbors = index.getNnsByItem(0, 10);
147
+ assert(Array.isArray(neighbors), "getNnsByItem returns array");
148
+ assert(neighbors.length === 10, "returns 10 neighbors");
149
+ assert(neighbors[0] === 0, "nearest neighbor of item 0 is itself");
80
150
  }
81
- // Test 2: Include distances
82
151
  console.log("\nTest 2: Include distances");
83
152
  {
84
- const index = new index_1.AnnoyIndex(DIMS, "angular");
85
- for (let i = 0; i < 100; i++) {
86
- index.addItem(i, randomVector(DIMS));
87
- }
88
- index.build(NUM_TREES);
89
- const result = index.getNnsByItem(0, 5, -1, true);
90
- assert("neighbors" in result && "distances" in result, "result has neighbors and distances");
91
- assert(result.neighbors.length === 5, "5 neighbors returned");
92
- assert(result.distances.length === 5, "5 distances returned");
93
- assert(result.distances[0] === 0, "distance to self is 0");
153
+ const index = new AnnoyIndex(DIMS, "angular");
154
+ for (let i = 0; i < 100; i++) {
155
+ index.addItem(i, randomVector(DIMS));
156
+ }
157
+ index.build(NUM_TREES);
158
+ const result = index.getNnsByItem(0, 5, -1, true);
159
+ assert(
160
+ "neighbors" in result && "distances" in result,
161
+ "result has neighbors and distances"
162
+ );
163
+ assert(result.neighbors.length === 5, "5 neighbors returned");
164
+ assert(result.distances.length === 5, "5 distances returned");
165
+ assert(result.distances[0] === 0, "distance to self is 0");
94
166
  }
95
- // Test 3: getNnsByVector
96
167
  console.log("\nTest 3: getNnsByVector");
97
168
  {
98
- const index = new index_1.AnnoyIndex(DIMS, "euclidean");
99
- const vectors = [];
100
- for (let i = 0; i < 100; i++) {
101
- const v = randomVector(DIMS);
102
- vectors.push(v);
103
- index.addItem(i, v);
104
- }
105
- index.build(NUM_TREES);
106
- const result = index.getNnsByVector(vectors[0], 5);
107
- assert(Array.isArray(result), "getNnsByVector returns array");
108
- assert(result[0] === 0, "closest to vector[0] is item 0");
169
+ const index = new AnnoyIndex(DIMS, "euclidean");
170
+ const vectors = [];
171
+ for (let i = 0; i < 100; i++) {
172
+ const v = randomVector(DIMS);
173
+ vectors.push(v);
174
+ index.addItem(i, v);
175
+ }
176
+ index.build(NUM_TREES);
177
+ const result = index.getNnsByVector(vectors[0], 5);
178
+ assert(Array.isArray(result), "getNnsByVector returns array");
179
+ assert(result[0] === 0, "closest to vector[0] is item 0");
109
180
  }
110
- // Test 4: Save and load
111
181
  console.log("\nTest 4: Save and load");
112
182
  {
113
- cleanup();
114
- const index = new index_1.AnnoyIndex(DIMS, "angular");
115
- for (let i = 0; i < 100; i++) {
116
- index.addItem(i, randomVector(DIMS));
117
- }
118
- index.build(NUM_TREES);
119
- index.save(tmpFile);
120
- const loaded = new index_1.AnnoyIndex(DIMS, "angular");
121
- loaded.load(tmpFile);
122
- assert(loaded.getNItems() === 100, "loaded index has 100 items");
123
- assert(loaded.getNTrees() === NUM_TREES, `loaded index has ${NUM_TREES} trees`);
124
- const item = loaded.getItem(0);
125
- assert(item.length === DIMS, `getItem returns vector of length ${DIMS}`);
126
- cleanup();
183
+ cleanup();
184
+ const index = new AnnoyIndex(DIMS, "angular");
185
+ for (let i = 0; i < 100; i++) {
186
+ index.addItem(i, randomVector(DIMS));
187
+ }
188
+ index.build(NUM_TREES);
189
+ index.save(tmpFile);
190
+ const loaded = new AnnoyIndex(DIMS, "angular");
191
+ loaded.load(tmpFile);
192
+ assert(loaded.getNItems() === 100, "loaded index has 100 items");
193
+ assert(loaded.getNTrees() === NUM_TREES, `loaded index has ${NUM_TREES} trees`);
194
+ const item = loaded.getItem(0);
195
+ assert(item.length === DIMS, `getItem returns vector of length ${DIMS}`);
196
+ cleanup();
127
197
  }
128
- // Test 5: getDistance
129
198
  console.log("\nTest 5: getDistance");
130
199
  {
131
- const index = new index_1.AnnoyIndex(DIMS, "euclidean");
132
- const v = randomVector(DIMS);
133
- index.addItem(0, v);
134
- index.addItem(1, v);
135
- index.build(1);
136
- const dist = index.getDistance(0, 1);
137
- assert(Math.abs(dist) < 1e-6, `distance between identical vectors is ~0 (got ${dist})`);
200
+ const index = new AnnoyIndex(DIMS, "euclidean");
201
+ const v = randomVector(DIMS);
202
+ index.addItem(0, v);
203
+ index.addItem(1, v);
204
+ index.build(1);
205
+ const dist = index.getDistance(0, 1);
206
+ assert(Math.abs(dist) < 1e-6, `distance between identical vectors is ~0 (got ${dist})`);
138
207
  }
139
- // Test 6: All metrics
140
208
  console.log("\nTest 6: All metrics");
141
209
  {
142
- const metrics = ["angular", "euclidean", "manhattan", "dot"];
143
- for (const metric of metrics) {
144
- const index = new index_1.AnnoyIndex(DIMS, metric);
145
- for (let i = 0; i < 50; i++) {
146
- index.addItem(i, randomVector(DIMS));
147
- }
148
- index.build(5);
149
- const nn = index.getNnsByItem(0, 5);
150
- assert(nn.length === 5, `${metric}: returns 5 neighbors`);
210
+ const metrics = ["angular", "euclidean", "manhattan", "dot"];
211
+ for (const metric of metrics) {
212
+ const index = new AnnoyIndex(DIMS, metric);
213
+ for (let i = 0; i < 50; i++) {
214
+ index.addItem(i, randomVector(DIMS));
151
215
  }
216
+ index.build(5);
217
+ const nn = index.getNnsByItem(0, 5);
218
+ assert(nn.length === 5, `${metric}: returns 5 neighbors`);
219
+ }
152
220
  }
153
- // Test 7: setSeed reproducibility
154
221
  console.log("\nTest 7: setSeed reproducibility");
155
222
  {
156
- const vectors = Array.from({ length: 100 }, () => randomVector(DIMS));
157
- function buildWithSeed(seed) {
158
- const idx = new index_1.AnnoyIndex(DIMS, "angular");
159
- idx.setSeed(seed);
160
- for (let i = 0; i < 100; i++) {
161
- idx.addItem(i, vectors[i]);
162
- }
163
- idx.build(5);
164
- return idx.getNnsByItem(0, 10);
223
+ let buildWithSeed = function(seed) {
224
+ const idx = new AnnoyIndex(DIMS, "angular");
225
+ idx.setSeed(seed);
226
+ for (let i = 0; i < 100; i++) {
227
+ idx.addItem(i, vectors[i]);
165
228
  }
166
- const r1 = buildWithSeed(42);
167
- const r2 = buildWithSeed(42);
168
- assert(JSON.stringify(r1) === JSON.stringify(r2), "same seed produces same results");
229
+ idx.build(5);
230
+ return idx.getNnsByItem(0, 10);
231
+ };
232
+ buildWithSeed2 = buildWithSeed;
233
+ const vectors = Array.from({ length: 100 }, () => randomVector(DIMS));
234
+ const r1 = buildWithSeed(42);
235
+ const r2 = buildWithSeed(42);
236
+ assert(
237
+ JSON.stringify(r1) === JSON.stringify(r2),
238
+ "same seed produces same results"
239
+ );
169
240
  }
170
- console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`);
241
+ var buildWithSeed2;
242
+ console.log(`
243
+ === Results: ${passed} passed, ${failed} failed ===`);
171
244
  process.exit(failed > 0 ? 1 : 0);
package/dist/test.mjs ADDED
@@ -0,0 +1,228 @@
1
+ // node_modules/tsup/assets/esm_shims.js
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ var getFilename = () => fileURLToPath(import.meta.url);
5
+ var getDirname = () => path.dirname(getFilename());
6
+ var __dirname = /* @__PURE__ */ getDirname();
7
+ var __filename = /* @__PURE__ */ getFilename();
8
+
9
+ // src/index.ts
10
+ import { createRequire } from "module";
11
+ import * as path2 from "path";
12
+ var _require = createRequire(__filename);
13
+ var addon = _require(
14
+ path2.join(__dirname, "..", "build", "Release", "annoy.node")
15
+ );
16
+ var AnnoyIndex = class {
17
+ constructor(f, metric = "angular") {
18
+ const constructors = {
19
+ angular: addon.AnnoyIndexAngular,
20
+ euclidean: addon.AnnoyIndexEuclidean,
21
+ manhattan: addon.AnnoyIndexManhattan,
22
+ dot: addon.AnnoyIndexDotProduct
23
+ };
24
+ const Ctor = constructors[metric];
25
+ if (!Ctor) {
26
+ throw new Error(
27
+ `Unknown metric "${metric}". Use: angular, euclidean, manhattan, dot`
28
+ );
29
+ }
30
+ this.index = new Ctor(f);
31
+ }
32
+ addItem(index, vector) {
33
+ this.index.addItem(index, vector);
34
+ }
35
+ build(numTrees, numThreads = -1) {
36
+ this.index.build(numTrees, numThreads);
37
+ }
38
+ unbuild() {
39
+ this.index.unbuild();
40
+ }
41
+ save(filename, prefault = false) {
42
+ this.index.save(filename, prefault);
43
+ }
44
+ load(filename, prefault = false) {
45
+ this.index.load(filename, prefault);
46
+ }
47
+ unload() {
48
+ this.index.unload();
49
+ }
50
+ getDistance(i, j) {
51
+ return this.index.getDistance(i, j);
52
+ }
53
+ getNnsByItem(item, n, searchK = -1, includeDistances = false) {
54
+ return this.index.getNnsByItem(
55
+ item,
56
+ n,
57
+ searchK,
58
+ includeDistances
59
+ );
60
+ }
61
+ getNnsByVector(vector, n, searchK = -1, includeDistances = false) {
62
+ return this.index.getNnsByVector(
63
+ vector,
64
+ n,
65
+ searchK,
66
+ includeDistances
67
+ );
68
+ }
69
+ getNItems() {
70
+ return this.index.getNItems();
71
+ }
72
+ getNTrees() {
73
+ return this.index.getNTrees();
74
+ }
75
+ getItem(item) {
76
+ return this.index.getItem(item);
77
+ }
78
+ setSeed(seed) {
79
+ this.index.setSeed(seed);
80
+ }
81
+ onDiskBuild(filename) {
82
+ this.index.onDiskBuild(filename);
83
+ }
84
+ verbose(v) {
85
+ this.index.verbose(v);
86
+ }
87
+ getF() {
88
+ return this.index.getF();
89
+ }
90
+ };
91
+
92
+ // src/test.ts
93
+ import * as fs from "fs";
94
+ import * as path3 from "path";
95
+ var DIMS = 40;
96
+ var NUM_ITEMS = 1e3;
97
+ var NUM_TREES = 10;
98
+ var tmpFile = path3.join(__dirname, "..", "test_index.ann");
99
+ var passed = 0;
100
+ var failed = 0;
101
+ function assert(condition, msg) {
102
+ if (condition) {
103
+ passed++;
104
+ console.log(` PASS: ${msg}`);
105
+ } else {
106
+ failed++;
107
+ console.error(` FAIL: ${msg}`);
108
+ }
109
+ }
110
+ function randomVector(dims) {
111
+ return Array.from({ length: dims }, () => Math.random() * 2 - 1);
112
+ }
113
+ function cleanup() {
114
+ try {
115
+ fs.unlinkSync(tmpFile);
116
+ } catch {
117
+ }
118
+ }
119
+ console.log("=== annoy-node test suite ===\n");
120
+ console.log("Test 1: Build and query (Angular)");
121
+ {
122
+ const index = new AnnoyIndex(DIMS, "angular");
123
+ for (let i = 0; i < NUM_ITEMS; i++) {
124
+ index.addItem(i, randomVector(DIMS));
125
+ }
126
+ index.build(NUM_TREES);
127
+ assert(index.getNItems() === NUM_ITEMS, `getNItems() === ${NUM_ITEMS}`);
128
+ assert(index.getNTrees() === NUM_TREES, `getNTrees() === ${NUM_TREES}`);
129
+ assert(index.getF() === DIMS, `getF() === ${DIMS}`);
130
+ const neighbors = index.getNnsByItem(0, 10);
131
+ assert(Array.isArray(neighbors), "getNnsByItem returns array");
132
+ assert(neighbors.length === 10, "returns 10 neighbors");
133
+ assert(neighbors[0] === 0, "nearest neighbor of item 0 is itself");
134
+ }
135
+ console.log("\nTest 2: Include distances");
136
+ {
137
+ const index = new AnnoyIndex(DIMS, "angular");
138
+ for (let i = 0; i < 100; i++) {
139
+ index.addItem(i, randomVector(DIMS));
140
+ }
141
+ index.build(NUM_TREES);
142
+ const result = index.getNnsByItem(0, 5, -1, true);
143
+ assert(
144
+ "neighbors" in result && "distances" in result,
145
+ "result has neighbors and distances"
146
+ );
147
+ assert(result.neighbors.length === 5, "5 neighbors returned");
148
+ assert(result.distances.length === 5, "5 distances returned");
149
+ assert(result.distances[0] === 0, "distance to self is 0");
150
+ }
151
+ console.log("\nTest 3: getNnsByVector");
152
+ {
153
+ const index = new AnnoyIndex(DIMS, "euclidean");
154
+ const vectors = [];
155
+ for (let i = 0; i < 100; i++) {
156
+ const v = randomVector(DIMS);
157
+ vectors.push(v);
158
+ index.addItem(i, v);
159
+ }
160
+ index.build(NUM_TREES);
161
+ const result = index.getNnsByVector(vectors[0], 5);
162
+ assert(Array.isArray(result), "getNnsByVector returns array");
163
+ assert(result[0] === 0, "closest to vector[0] is item 0");
164
+ }
165
+ console.log("\nTest 4: Save and load");
166
+ {
167
+ cleanup();
168
+ const index = new AnnoyIndex(DIMS, "angular");
169
+ for (let i = 0; i < 100; i++) {
170
+ index.addItem(i, randomVector(DIMS));
171
+ }
172
+ index.build(NUM_TREES);
173
+ index.save(tmpFile);
174
+ const loaded = new AnnoyIndex(DIMS, "angular");
175
+ loaded.load(tmpFile);
176
+ assert(loaded.getNItems() === 100, "loaded index has 100 items");
177
+ assert(loaded.getNTrees() === NUM_TREES, `loaded index has ${NUM_TREES} trees`);
178
+ const item = loaded.getItem(0);
179
+ assert(item.length === DIMS, `getItem returns vector of length ${DIMS}`);
180
+ cleanup();
181
+ }
182
+ console.log("\nTest 5: getDistance");
183
+ {
184
+ const index = new AnnoyIndex(DIMS, "euclidean");
185
+ const v = randomVector(DIMS);
186
+ index.addItem(0, v);
187
+ index.addItem(1, v);
188
+ index.build(1);
189
+ const dist = index.getDistance(0, 1);
190
+ assert(Math.abs(dist) < 1e-6, `distance between identical vectors is ~0 (got ${dist})`);
191
+ }
192
+ console.log("\nTest 6: All metrics");
193
+ {
194
+ const metrics = ["angular", "euclidean", "manhattan", "dot"];
195
+ for (const metric of metrics) {
196
+ const index = new AnnoyIndex(DIMS, metric);
197
+ for (let i = 0; i < 50; i++) {
198
+ index.addItem(i, randomVector(DIMS));
199
+ }
200
+ index.build(5);
201
+ const nn = index.getNnsByItem(0, 5);
202
+ assert(nn.length === 5, `${metric}: returns 5 neighbors`);
203
+ }
204
+ }
205
+ console.log("\nTest 7: setSeed reproducibility");
206
+ {
207
+ let buildWithSeed = function(seed) {
208
+ const idx = new AnnoyIndex(DIMS, "angular");
209
+ idx.setSeed(seed);
210
+ for (let i = 0; i < 100; i++) {
211
+ idx.addItem(i, vectors[i]);
212
+ }
213
+ idx.build(5);
214
+ return idx.getNnsByItem(0, 10);
215
+ };
216
+ buildWithSeed2 = buildWithSeed;
217
+ const vectors = Array.from({ length: 100 }, () => randomVector(DIMS));
218
+ const r1 = buildWithSeed(42);
219
+ const r2 = buildWithSeed(42);
220
+ assert(
221
+ JSON.stringify(r1) === JSON.stringify(r2),
222
+ "same seed produces same results"
223
+ );
224
+ }
225
+ var buildWithSeed2;
226
+ console.log(`
227
+ === Results: ${passed} passed, ${failed} failed ===`);
228
+ process.exit(failed > 0 ? 1 : 0);
package/package.json CHANGED
@@ -1,15 +1,28 @@
1
1
  {
2
2
  "name": "@samyok/annoy",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Native Node.js bindings for Spotify's Annoy — fast approximate nearest neighbor search",
5
5
  "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
6
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
7
20
  "scripts": {
8
21
  "install": "node-gyp rebuild",
9
22
  "build:native": "node-gyp rebuild",
10
- "build:ts": "tsc",
23
+ "build:ts": "tsup",
11
24
  "build": "npm run build:native && npm run build:ts",
12
- "test": "npm run build:ts && node dist/test.js",
25
+ "test": "npm run build:ts && node dist/test.js && node --input-type=module -e \"import('./dist/test.mjs')\"",
13
26
  "prepublishOnly": "npm run build:ts"
14
27
  },
15
28
  "keywords": [
@@ -42,11 +55,11 @@
42
55
  "devDependencies": {
43
56
  "@types/node": "^25.7.0",
44
57
  "node-gyp": "^11.2.0",
58
+ "tsup": "^8.5.1",
45
59
  "typescript": "^5.8.3"
46
60
  },
47
61
  "files": [
48
- "dist/**/*.js",
49
- "dist/**/*.d.ts",
62
+ "dist",
50
63
  "src/addon.cc",
51
64
  "deps/annoy/src/annoylib.h",
52
65
  "deps/annoy/src/kissrandom.h",