@indexable/sdk 0.0.4 → 0.2.1

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.
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "@indexable/sdk-linux-x64-gnu",
3
- "version": "0.0.4",
4
- "os": ["linux"],
5
- "cpu": ["x64"],
3
+ "version": "0.2.1",
4
+ "os": [
5
+ "linux"
6
+ ],
7
+ "cpu": [
8
+ "x64"
9
+ ],
6
10
  "main": "ix-sdk.linux-x64-gnu.node",
7
- "files": ["ix-sdk.linux-x64-gnu.node"],
11
+ "files": [
12
+ "ix-sdk.linux-x64-gnu.node",
13
+ "libix_sdk_ffi.so"
14
+ ],
8
15
  "license": "MIT",
9
16
  "engines": {
10
17
  "node": ">= 18"
package/package.json CHANGED
@@ -1,25 +1,28 @@
1
1
  {
2
2
  "name": "@indexable/sdk",
3
- "version": "0.0.4",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "exports": {
7
7
  ".": "./src/index.ts"
8
8
  },
9
- "files": ["src/", "npm/"],
9
+ "files": [
10
+ "src/",
11
+ "npm/"
12
+ ],
10
13
  "scripts": {
11
- "build": "cargo build -p ix-sdk-napi --profile release-external --target x86_64-unknown-linux-gnu && cp ../../target/x86_64-unknown-linux-gnu/release-external/libix_sdk_napi.so npm/linux-x64-gnu/ix-sdk.linux-x64-gnu.node",
12
- "test": "bun test src/",
14
+ "build": "bunx tsc --noEmit",
15
+ "build:native": "RUSTFLAGS='--cfg reqwest_unstable' cargo build -p ix-sdk-napi -p ix-sdk-ffi --profile release-external --target x86_64-unknown-linux-gnu && cp ../../target/x86_64-unknown-linux-gnu/release-external/libix_sdk_napi.so npm/linux-x64-gnu/ix-sdk.linux-x64-gnu.node && cp ../../target/x86_64-unknown-linux-gnu/release-external/libix_sdk_ffi.so npm/linux-x64-gnu/libix_sdk_ffi.so",
13
16
  "typecheck": "bunx tsc --noEmit"
14
17
  },
15
- "optionalDependencies": {
16
- "@indexable/sdk-linux-x64-gnu": "0.0.4"
18
+ "dependencies": {
19
+ "koffi": "^2.9.0"
17
20
  },
18
21
  "devDependencies": {
19
22
  "bun-types": "latest"
20
23
  },
21
24
  "engines": {
22
- "node": ">= 18"
25
+ "bun": ">= 1.0.0"
23
26
  },
24
27
  "license": "MIT"
25
28
  }
@@ -0,0 +1,174 @@
1
+ // UniFFI-generated TypeScript bindings for ix-sdk-ffi remain the public API.
2
+ //
3
+ // On Linux, Bun crashes in the koffi/UniFFI path for a narrow set of async VM
4
+ // methods. Those methods are patched to a napi-rs backend built from the same
5
+ // Rust SDK so Rust remains the single behavior owner.
6
+
7
+ import { existsSync } from 'node:fs'
8
+ import { createRequire } from 'node:module'
9
+ import path from 'node:path'
10
+ import { fileURLToPath } from 'node:url'
11
+
12
+ import {
13
+ IxSdkClient as GeneratedIxSdkClient,
14
+ type FfiBillingStatus,
15
+ type FfiCreateVmResult,
16
+ type FfiExecResult,
17
+ type FfiSpawnOptions,
18
+ } from './generated/ix_sdk_ffi'
19
+
20
+ export * from './generated/ix_sdk_ffi'
21
+
22
+ type NativeIxSdkLinuxClient = {
23
+ billingStatus(): Promise<FfiBillingStatus>
24
+ spawn(
25
+ image: string,
26
+ name: string | null,
27
+ memoryMib: bigint | null,
28
+ cpuCores: bigint | null,
29
+ ipv4: boolean | null
30
+ ): Promise<string>
31
+ createVm(
32
+ id: string | null,
33
+ image: string,
34
+ name: string | null,
35
+ maxMemoryMib: bigint | null,
36
+ maxCpuCores: bigint | null,
37
+ enableIpv4: boolean | null,
38
+ waitUntilReady: boolean | null,
39
+ region: string | null
40
+ ): Promise<FfiCreateVmResult>
41
+ execVm(
42
+ vmId: string,
43
+ command: string[],
44
+ workingDir: string | null
45
+ ): Promise<FfiExecResult>
46
+ deleteVm(vmId: string): Promise<void>
47
+ }
48
+
49
+ type NativeAddon = {
50
+ IxSdkLinuxClient: new (server: string, token: string) => NativeIxSdkLinuxClient
51
+ }
52
+
53
+ const isLinux = process.platform === 'linux'
54
+ const isBun = typeof process.versions?.bun === 'string'
55
+ const linuxTripleDir = `${process.platform}-${process.arch}-gnu`
56
+ const linuxAddonName = `ix-sdk.${linuxTripleDir}.node`
57
+ const nativeClients = new WeakMap<GeneratedIxSdkClient, NativeIxSdkLinuxClient>()
58
+
59
+ function loadNativeAddon(): NativeAddon {
60
+ const require = createRequire(import.meta.url)
61
+ const filename = fileURLToPath(import.meta.url)
62
+ const dirname = path.dirname(filename)
63
+ const addonPath = path.resolve(
64
+ dirname,
65
+ '..',
66
+ 'npm',
67
+ linuxTripleDir,
68
+ linuxAddonName
69
+ )
70
+ if (!existsSync(addonPath)) {
71
+ throw new Error(`Missing Linux SDK addon at ${addonPath}`)
72
+ }
73
+ return require(addonPath) as NativeAddon
74
+ }
75
+
76
+ function nativeClient(client: GeneratedIxSdkClient): NativeIxSdkLinuxClient {
77
+ const native = nativeClients.get(client)
78
+ if (native) {
79
+ return native
80
+ }
81
+ throw new Error('Linux native SDK backend not initialized; use IxSdkClient.create()')
82
+ }
83
+
84
+ if (isLinux) {
85
+ const addon = loadNativeAddon()
86
+ const create = GeneratedIxSdkClient.create.bind(GeneratedIxSdkClient)
87
+ const supportedBunLinuxMethods = new Set([
88
+ 'billingStatus',
89
+ 'close',
90
+ 'constructor',
91
+ 'createVm',
92
+ 'deleteVm',
93
+ 'describe',
94
+ 'execVm',
95
+ 'filter',
96
+ 'getFs',
97
+ 'spawn',
98
+ ])
99
+
100
+ GeneratedIxSdkClient.create = (server: string, token: string): GeneratedIxSdkClient => {
101
+ const client = create(server, token)
102
+ nativeClients.set(client, new addon.IxSdkLinuxClient(server, token))
103
+ return client
104
+ }
105
+
106
+ GeneratedIxSdkClient.prototype.billingStatus = function (): Promise<FfiBillingStatus> {
107
+ return nativeClient(this).billingStatus()
108
+ }
109
+
110
+ GeneratedIxSdkClient.prototype.spawn = function (
111
+ image: string,
112
+ options: FfiSpawnOptions | null
113
+ ): Promise<string> {
114
+ return nativeClient(this).spawn(
115
+ image,
116
+ options?.name ?? null,
117
+ options?.memoryMib ?? null,
118
+ options?.cpuCores ?? null,
119
+ options?.ipv4 ?? null
120
+ )
121
+ }
122
+
123
+ GeneratedIxSdkClient.prototype.createVm = function (
124
+ id: string | null,
125
+ image: string,
126
+ name: string | null,
127
+ maxMemoryMib: bigint | null,
128
+ maxCpuCores: bigint | null,
129
+ enableIpv4: boolean | null,
130
+ waitUntilReady: boolean | null,
131
+ region: string | null
132
+ ): Promise<FfiCreateVmResult> {
133
+ return nativeClient(this).createVm(
134
+ id,
135
+ image,
136
+ name,
137
+ maxMemoryMib,
138
+ maxCpuCores,
139
+ enableIpv4,
140
+ waitUntilReady,
141
+ region
142
+ )
143
+ }
144
+
145
+ GeneratedIxSdkClient.prototype.execVm = function (
146
+ vmId: string,
147
+ command: string[],
148
+ workingDir: string | null
149
+ ): Promise<FfiExecResult> {
150
+ return nativeClient(this).execVm(vmId, command, workingDir)
151
+ }
152
+
153
+ GeneratedIxSdkClient.prototype.deleteVm = function (vmId: string): Promise<void> {
154
+ return nativeClient(this).deleteVm(vmId)
155
+ }
156
+
157
+ if (isBun) {
158
+ const prototype = GeneratedIxSdkClient.prototype as unknown as Record<string, unknown>
159
+ for (const methodName of Object.getOwnPropertyNames(prototype)) {
160
+ if (supportedBunLinuxMethods.has(methodName)) {
161
+ continue
162
+ }
163
+ const method = prototype[methodName]
164
+ if (typeof method !== 'function') {
165
+ continue
166
+ }
167
+ prototype[methodName] = function (): never {
168
+ throw new Error(
169
+ `IxSdkClient.${methodName} is disabled on Bun/Linux until it is ported to the native backend`
170
+ )
171
+ }
172
+ }
173
+ }
174
+ }