sekejap 0.13.3
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.
- package/README.md +62 -0
- package/index.d.ts +40 -0
- package/index.js +317 -0
- package/package.json +24 -0
- package/sekejap.darwin-arm64.node +0 -0
- package/sekejap.darwin-x64.node +0 -0
- package/sekejap.linux-arm64-gnu.node +0 -0
- package/sekejap.linux-x64-gnu.node +0 -0
- package/sekejap.win32-x64-msvc.node +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# sekejap for Node.js
|
|
2
|
+
|
|
3
|
+
**Status: working** (tested). Native Node.js binding via [napi-rs](https://napi.rs/) —
|
|
4
|
+
`#[napi]` over `sekejap::CoreDB`, compiled to a native N-API addon.
|
|
5
|
+
|
|
6
|
+
## Run it
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd wrappers/node
|
|
10
|
+
cargo build --release # builds the addon
|
|
11
|
+
cp target/release/libsekejap_node.dylib sekejap.node # (.so on Linux, .dll on Windows)
|
|
12
|
+
node test.cjs # → OK — sekejap-node 0.13.0 …
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For real packaging use `npx @napi-rs/cli build --release`, which names the addon
|
|
16
|
+
per-platform and generates `index.js` + `index.d.ts` (TypeScript types). JS API:
|
|
17
|
+
`Db.open(path)`, `execute`, `query`/`queryParams` (→ JSON string, `JSON.parse` it),
|
|
18
|
+
`put`, `link`, `nodeCount`/`edgeCount`, `compact`, `version()`.
|
|
19
|
+
|
|
20
|
+
## Approach
|
|
21
|
+
|
|
22
|
+
napi-rs is Node's equivalent of PyO3: you annotate Rust with `#[napi]` and it
|
|
23
|
+
builds a native Node addon (`.node`) that speaks Node's stable **N-API** directly —
|
|
24
|
+
idiomatic JS types, no manual C ABI. (An alternative is `koffi`/`ffi-napi` calling
|
|
25
|
+
the C ABI in `../c`, but napi-rs gives better perf and TypeScript types.)
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
wrappers/node/
|
|
29
|
+
├── Cargo.toml # crate-type = ["cdylib"], deps: napi, napi-derive; depends on the sekejap crate
|
|
30
|
+
├── package.json # name "sekejap", @napi-rs/cli build/publish scripts
|
|
31
|
+
├── src/lib.rs # #[napi] wrappers over sekejap::CoreDB / Engine
|
|
32
|
+
├── index.d.ts # generated TypeScript types
|
|
33
|
+
└── examples/ # .js / .ts usage
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Minimal `Cargo.toml` to add (then add `wrappers/node` to the workspace members):
|
|
37
|
+
|
|
38
|
+
```toml
|
|
39
|
+
[package]
|
|
40
|
+
name = "sekejap-node"
|
|
41
|
+
version.workspace = true
|
|
42
|
+
edition.workspace = true
|
|
43
|
+
|
|
44
|
+
[lib]
|
|
45
|
+
crate-type = ["cdylib"]
|
|
46
|
+
|
|
47
|
+
[dependencies]
|
|
48
|
+
sekejap = { path = "../.." }
|
|
49
|
+
napi = { version = "2", features = ["napi8"] }
|
|
50
|
+
napi-derive = "2"
|
|
51
|
+
|
|
52
|
+
[build-dependencies]
|
|
53
|
+
napi-build = "2"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Distribution
|
|
57
|
+
|
|
58
|
+
- **Registry:** [npm](https://npmjs.com) → `npm install sekejap`
|
|
59
|
+
- **Publish:** `npm publish`. Build prebuilt binaries per platform in CI with
|
|
60
|
+
`@napi-rs/cli` (`napi build --release`) and ship them as platform packages under
|
|
61
|
+
`optionalDependencies`, so users don't need a Rust toolchain.
|
|
62
|
+
- Reserve the name `sekejap` on npm now.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/** The library version. */
|
|
7
|
+
export declare function version(): string
|
|
8
|
+
/**
|
|
9
|
+
* An open sekejap database. JS is single-threaded, but we guard with a Mutex so
|
|
10
|
+
* the handle is sound even if shared via worker threads.
|
|
11
|
+
*/
|
|
12
|
+
export declare class Db {
|
|
13
|
+
/** Open (or create) a database at `path`. */
|
|
14
|
+
static open(path: string): Db
|
|
15
|
+
/** Run a mutating statement; returns affected rows. */
|
|
16
|
+
execute(sql: string): number
|
|
17
|
+
/** Run a SELECT; returns a JSON-array string (caller `JSON.parse`s it). */
|
|
18
|
+
query(sql: string): string
|
|
19
|
+
/** Parameterized SELECT ($1, $2, …); `paramsJson` is a JSON array string. */
|
|
20
|
+
queryParams(sql: string, paramsJson: string): string
|
|
21
|
+
/** Compile a query once for repeated execution — a prepared statement. */
|
|
22
|
+
prepare(sql: string): PreparedStatement
|
|
23
|
+
/**
|
|
24
|
+
* Run a prepared statement, binding `$1`, `$2`, … from a JSON-array string.
|
|
25
|
+
* Returns a JSON-array string (caller `JSON.parse`s it).
|
|
26
|
+
*/
|
|
27
|
+
queryPrepared(stmt: PreparedStatement, paramsJson: string): string
|
|
28
|
+
/** Insert/replace one node by slug with a JSON payload. */
|
|
29
|
+
put(slug: string, payloadJson: string): void
|
|
30
|
+
/** Create a plain edge from -> to of the given type. */
|
|
31
|
+
link(from: string, to: string, edgeType: string): void
|
|
32
|
+
/** Number of nodes. */
|
|
33
|
+
nodeCount(): number
|
|
34
|
+
/** Number of edges. */
|
|
35
|
+
edgeCount(): number
|
|
36
|
+
/** Compact: truncate WAL, rewrite payloads/topology, reclaim RAM. */
|
|
37
|
+
compact(): void
|
|
38
|
+
}
|
|
39
|
+
/** A prepared (compiled) query — from `Db.prepare`, run with `Db.queryPrepared`. */
|
|
40
|
+
export declare class PreparedStatement { }
|
package/index.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'sekejap.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./sekejap.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('sekejap-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'sekejap.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./sekejap.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('sekejap-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'sekejap.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./sekejap.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('sekejap-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'sekejap.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./sekejap.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('sekejap-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'sekejap.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./sekejap.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('sekejap-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'sekejap.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./sekejap.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('sekejap-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'sekejap.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./sekejap.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('sekejap-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'sekejap.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./sekejap.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('sekejap-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'sekejap.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./sekejap.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('sekejap-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'sekejap.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./sekejap.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('sekejap-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'sekejap.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./sekejap.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('sekejap-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'sekejap.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./sekejap.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('sekejap-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'sekejap.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./sekejap.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('sekejap-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'sekejap.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./sekejap.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('sekejap-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'sekejap.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./sekejap.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('sekejap-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'sekejap.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./sekejap.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('sekejap-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'sekejap.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./sekejap.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('sekejap-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'sekejap.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./sekejap.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('sekejap-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { Db, PreparedStatement, version } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.Db = Db
|
|
316
|
+
module.exports.PreparedStatement = PreparedStatement
|
|
317
|
+
module.exports.version = version
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sekejap",
|
|
3
|
+
"version": "0.13.3",
|
|
4
|
+
"description": "Embedded graph-first multi-model database — Node.js binding",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"repository": "github:sekejapdb/sekejap",
|
|
7
|
+
"homepage": "https://sekejap.zebflow.com",
|
|
8
|
+
"keywords": ["database", "graph", "vector", "spatial", "embedded", "multi-model"],
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"types": "index.d.ts",
|
|
11
|
+
"files": ["index.js", "index.d.ts", "*.node", "README.md"],
|
|
12
|
+
"napi": {
|
|
13
|
+
"name": "sekejap"
|
|
14
|
+
},
|
|
15
|
+
"engines": { "node": ">= 16" },
|
|
16
|
+
"os": ["darwin", "linux", "win32"],
|
|
17
|
+
"cpu": ["x64", "arm64"],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "napi build --platform --release"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@napi-rs/cli": "^2.18.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|