@indexable/sdk 0.0.2 → 0.2.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.
- package/npm/linux-x64-gnu/ix-sdk.linux-x64-gnu.node +0 -0
- package/npm/linux-x64-gnu/libix_sdk_ffi.so +0 -0
- package/npm/linux-x64-gnu/package.json +10 -5
- package/package.json +9 -7
- package/src/bindings.ts +9 -0
- package/src/generated/ix_sdk_ffi.ts +4507 -0
- package/src/index.ts +6 -134
- package/src/index.test.ts +0 -102
package/src/index.ts
CHANGED
|
@@ -1,135 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* ```ts
|
|
7
|
-
* import Ix from "@indexable/sdk"
|
|
8
|
-
*
|
|
9
|
-
* const ix = new Ix()
|
|
10
|
-
* const vm = await ix.spawn("ubuntu:24.04")
|
|
11
|
-
* console.log(vm.ipv6)
|
|
12
|
-
*
|
|
13
|
-
* await vm.writeFile("/tmp/hi", "hello")
|
|
14
|
-
* const content = await vm.readFile("/tmp/hi")
|
|
15
|
-
*
|
|
16
|
-
* const fork = await vm.fork("experiment")
|
|
17
|
-
* await fork.writeFile("/tmp/new", "from fork")
|
|
18
|
-
* await vm.merge(fork)
|
|
19
|
-
*
|
|
20
|
-
* await vm.stop()
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
1
|
+
// @indexable/sdk — TypeScript bindings for the ix platform.
|
|
2
|
+
//
|
|
3
|
+
// This package re-exports UniFFI-generated bindings from ix-sdk-ffi.
|
|
4
|
+
// All business logic, RPC, and protocol handling lives in the Rust SDK.
|
|
5
|
+
// This package is a thin TypeScript wrapper — nothing more.
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
import { createRequire } from "node:module";
|
|
26
|
-
|
|
27
|
-
const require = createRequire(import.meta.url);
|
|
28
|
-
|
|
29
|
-
// Platform packages installed via optionalDependencies.
|
|
30
|
-
// npm/bun only installs the one matching the current os+cpu.
|
|
31
|
-
const PLATFORM_PACKAGES: Record<string, string> = {
|
|
32
|
-
"linux-x64": "@indexable/sdk-linux-x64-gnu",
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
function loadNativeAddon() {
|
|
36
|
-
const key = `${process.platform}-${process.arch}`;
|
|
37
|
-
const pkg = PLATFORM_PACKAGES[key];
|
|
38
|
-
if (!pkg) throw new Error(`@indexable/sdk: unsupported platform ${key}`);
|
|
39
|
-
try {
|
|
40
|
-
return require(pkg);
|
|
41
|
-
} catch {
|
|
42
|
-
throw new Error(
|
|
43
|
-
`@indexable/sdk: failed to load native addon for ${key}. ` +
|
|
44
|
-
`Ensure ${pkg} is installed (npm install / bun install).`,
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const native = loadNativeAddon();
|
|
50
|
-
|
|
51
|
-
export interface SpawnOptions {
|
|
52
|
-
name?: string;
|
|
53
|
-
memory?: number;
|
|
54
|
-
cpus?: number;
|
|
55
|
-
ipv4?: boolean;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface DirEntry {
|
|
59
|
-
name: string;
|
|
60
|
-
size: number;
|
|
61
|
-
isDir: boolean;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface MergeResult {
|
|
65
|
-
appliedOps: number;
|
|
66
|
-
conflictPaths: string[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface SecretEntry {
|
|
70
|
-
name: string;
|
|
71
|
-
createdAt: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface ConnectOptions {
|
|
75
|
-
server?: string;
|
|
76
|
-
token?: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** A virtual machine. */
|
|
80
|
-
export interface Vm {
|
|
81
|
-
/** VM identifier (e.g. "vm_06e9...") */
|
|
82
|
-
readonly id: string;
|
|
83
|
-
readonly name: string;
|
|
84
|
-
readonly image: string;
|
|
85
|
-
readonly status: string;
|
|
86
|
-
readonly ipv6: string;
|
|
87
|
-
readonly ipv4: string | null;
|
|
88
|
-
readonly subdomain: string | null;
|
|
89
|
-
|
|
90
|
-
stop(): Promise<void>;
|
|
91
|
-
start(): Promise<void>;
|
|
92
|
-
restart(): Promise<void>;
|
|
93
|
-
delete(): Promise<void>;
|
|
94
|
-
|
|
95
|
-
writeFile(path: string, content: string): Promise<void>;
|
|
96
|
-
readFile(path: string): Promise<string>;
|
|
97
|
-
listDir(path: string): Promise<DirEntry[]>;
|
|
98
|
-
|
|
99
|
-
fork(name?: string): Promise<Vm>;
|
|
100
|
-
merge(source: Vm): Promise<MergeResult>;
|
|
101
|
-
|
|
102
|
-
undo(): Promise<boolean>;
|
|
103
|
-
redo(): Promise<boolean>;
|
|
104
|
-
revert(timestampMs: number): Promise<void>;
|
|
105
|
-
|
|
106
|
-
setSecret(key: string, value: string): Promise<void>;
|
|
107
|
-
deleteSecret(key: string): Promise<void>;
|
|
108
|
-
secrets(): Promise<SecretEntry[]>;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** The ix SDK client. */
|
|
112
|
-
export class Ix {
|
|
113
|
-
private inner: InstanceType<typeof native.Ix>;
|
|
114
|
-
|
|
115
|
-
constructor(options?: ConnectOptions) {
|
|
116
|
-
this.inner = new native.Ix(options ?? undefined);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Create a VM from an OCI image. */
|
|
120
|
-
async spawn(image: string, options?: SpawnOptions): Promise<Vm> {
|
|
121
|
-
return this.inner.spawn(image, options ?? undefined);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Retrieve a single VM by ID. */
|
|
125
|
-
async getVm(vmId: string): Promise<Vm> {
|
|
126
|
-
return this.inner.getVm(vmId);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** List all VMs. */
|
|
130
|
-
async vms(): Promise<Vm[]> {
|
|
131
|
-
return this.inner.vms();
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export default Ix;
|
|
7
|
+
export * from './bindings'
|
package/src/index.test.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, afterEach } from "bun:test";
|
|
2
|
-
import Ix from "./index";
|
|
3
|
-
import type { Vm } from "./index";
|
|
4
|
-
|
|
5
|
-
const IMAGE = "ubuntu:24.04";
|
|
6
|
-
const TIMEOUT_MS = 120_000;
|
|
7
|
-
|
|
8
|
-
let cleanup: Vm[] = [];
|
|
9
|
-
|
|
10
|
-
afterEach(async () => {
|
|
11
|
-
for (const vm of cleanup) {
|
|
12
|
-
try {
|
|
13
|
-
await vm.stop();
|
|
14
|
-
} catch {
|
|
15
|
-
// might already be stopped
|
|
16
|
-
}
|
|
17
|
-
try {
|
|
18
|
-
await vm.delete();
|
|
19
|
-
} catch {
|
|
20
|
-
// best-effort
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
cleanup = [];
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
function track(vm: Vm): Vm {
|
|
27
|
-
cleanup.push(vm);
|
|
28
|
-
return vm;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
describe("Ix", () => {
|
|
32
|
-
test("lists VMs", async () => {
|
|
33
|
-
const ix = new Ix();
|
|
34
|
-
const vms = await ix.vms();
|
|
35
|
-
expect(Array.isArray(vms)).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe("Vm lifecycle", () => {
|
|
40
|
-
test(
|
|
41
|
-
"spawn → getters → stop",
|
|
42
|
-
async () => {
|
|
43
|
-
const ix = new Ix();
|
|
44
|
-
const vm = track(await ix.spawn(IMAGE, { name: "sdk-lifecycle" }));
|
|
45
|
-
|
|
46
|
-
expect(vm.id).toBeTruthy();
|
|
47
|
-
expect(vm.image).toBe(IMAGE);
|
|
48
|
-
expect(vm.ipv6).toBeTruthy();
|
|
49
|
-
expect(vm.status).toBe("running");
|
|
50
|
-
|
|
51
|
-
await vm.stop();
|
|
52
|
-
cleanup = [];
|
|
53
|
-
},
|
|
54
|
-
TIMEOUT_MS,
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe("Vm filesystem", () => {
|
|
59
|
-
test(
|
|
60
|
-
"writeFile → readFile → listDir",
|
|
61
|
-
async () => {
|
|
62
|
-
const ix = new Ix();
|
|
63
|
-
const vm = track(await ix.spawn(IMAGE, { name: "sdk-fs" }));
|
|
64
|
-
|
|
65
|
-
const content = `hello from sdk test ${Date.now()}`;
|
|
66
|
-
await vm.writeFile("/tmp/sdk-test.txt", content);
|
|
67
|
-
|
|
68
|
-
const read = await vm.readFile("/tmp/sdk-test.txt");
|
|
69
|
-
expect(read).toBe(content);
|
|
70
|
-
|
|
71
|
-
const entries = await vm.listDir("/tmp");
|
|
72
|
-
const found = entries.find((e) => e.name === "sdk-test.txt");
|
|
73
|
-
expect(found).toBeTruthy();
|
|
74
|
-
},
|
|
75
|
-
TIMEOUT_MS,
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe("Vm version control", () => {
|
|
80
|
-
test(
|
|
81
|
-
"fork → write on fork → merge back",
|
|
82
|
-
async () => {
|
|
83
|
-
const ix = new Ix();
|
|
84
|
-
const main = track(await ix.spawn(IMAGE, { name: "sdk-vcs-main" }));
|
|
85
|
-
|
|
86
|
-
await main.writeFile("/tmp/file-a.txt", "from main");
|
|
87
|
-
|
|
88
|
-
const fork = track(await main.fork("sdk-vcs-fork"));
|
|
89
|
-
|
|
90
|
-
await fork.writeFile("/tmp/file-b.txt", "from fork");
|
|
91
|
-
|
|
92
|
-
const result = await main.merge(fork);
|
|
93
|
-
expect(result.conflictPaths.length).toBe(0);
|
|
94
|
-
|
|
95
|
-
const a = await main.readFile("/tmp/file-a.txt");
|
|
96
|
-
expect(a).toBe("from main");
|
|
97
|
-
const b = await main.readFile("/tmp/file-b.txt");
|
|
98
|
-
expect(b).toBe("from fork");
|
|
99
|
-
},
|
|
100
|
-
TIMEOUT_MS,
|
|
101
|
-
);
|
|
102
|
-
});
|