@thingd/sdk 0.31.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.
Files changed (72) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +39 -0
  3. package/dist/client/http-thing-store.d.ts +41 -0
  4. package/dist/client/http-thing-store.d.ts.map +1 -0
  5. package/dist/client/http-thing-store.js +178 -0
  6. package/dist/client/in-memory-thing-store.d.ts +38 -0
  7. package/dist/client/in-memory-thing-store.d.ts.map +1 -0
  8. package/dist/client/in-memory-thing-store.js +270 -0
  9. package/dist/client/index.d.ts +5 -0
  10. package/dist/client/index.d.ts.map +1 -0
  11. package/dist/client/index.js +3 -0
  12. package/dist/client/thingd.d.ts +46 -0
  13. package/dist/client/thingd.d.ts.map +1 -0
  14. package/dist/client/thingd.js +115 -0
  15. package/dist/index.d.ts +11 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +9 -0
  18. package/dist/mcp/audit.d.ts +27 -0
  19. package/dist/mcp/audit.d.ts.map +1 -0
  20. package/dist/mcp/audit.js +36 -0
  21. package/dist/mcp/config.d.ts +22 -0
  22. package/dist/mcp/config.d.ts.map +1 -0
  23. package/dist/mcp/config.js +52 -0
  24. package/dist/mcp/index.d.ts +6 -0
  25. package/dist/mcp/index.d.ts.map +1 -0
  26. package/dist/mcp/index.js +5 -0
  27. package/dist/mcp/result.d.ts +3 -0
  28. package/dist/mcp/result.d.ts.map +1 -0
  29. package/dist/mcp/result.js +10 -0
  30. package/dist/mcp/server.d.ts +19 -0
  31. package/dist/mcp/server.d.ts.map +1 -0
  32. package/dist/mcp/server.js +51 -0
  33. package/dist/mcp/tools.d.ts +10 -0
  34. package/dist/mcp/tools.d.ts.map +1 -0
  35. package/dist/mcp/tools.js +568 -0
  36. package/dist/memory/index.d.ts +36 -0
  37. package/dist/memory/index.d.ts.map +1 -0
  38. package/dist/memory/index.js +86 -0
  39. package/dist/rest/helpers.d.ts +17 -0
  40. package/dist/rest/helpers.d.ts.map +1 -0
  41. package/dist/rest/helpers.js +55 -0
  42. package/dist/rest/index.d.ts +3 -0
  43. package/dist/rest/index.d.ts.map +1 -0
  44. package/dist/rest/index.js +2 -0
  45. package/dist/rest/server.d.ts +4 -0
  46. package/dist/rest/server.d.ts.map +1 -0
  47. package/dist/rest/server.js +317 -0
  48. package/dist/stores/cloud-thing-store.d.ts +49 -0
  49. package/dist/stores/cloud-thing-store.d.ts.map +1 -0
  50. package/dist/stores/cloud-thing-store.js +243 -0
  51. package/dist/stores/in-memory-thing-store.d.ts +44 -0
  52. package/dist/stores/in-memory-thing-store.d.ts.map +1 -0
  53. package/dist/stores/in-memory-thing-store.js +411 -0
  54. package/dist/stores/native-thing-store.d.ts +53 -0
  55. package/dist/stores/native-thing-store.d.ts.map +1 -0
  56. package/dist/stores/native-thing-store.js +312 -0
  57. package/dist/stores/remote-thing-store.d.ts +27 -0
  58. package/dist/stores/remote-thing-store.d.ts.map +1 -0
  59. package/dist/stores/remote-thing-store.js +131 -0
  60. package/dist/thingd.d.ts +48 -0
  61. package/dist/thingd.d.ts.map +1 -0
  62. package/dist/thingd.js +147 -0
  63. package/dist/types/index.d.ts +2 -0
  64. package/dist/types/index.d.ts.map +1 -0
  65. package/dist/types/index.js +1 -0
  66. package/dist/types.d.ts +185 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +1 -0
  69. package/dist/version.d.ts +6 -0
  70. package/dist/version.d.ts.map +1 -0
  71. package/dist/version.js +5 -0
  72. package/package.json +79 -0
@@ -0,0 +1,53 @@
1
+ import type { ListEventsOptions, ListObjectsOptions, MemoryEvent, MemoryObject, MemorySearchOptions, MemorySearchResult, QueueClaimOptions, QueueJob, QueueJobOptions, QueueJobPayload, QueueJobResult, QueueNackOptions, StoredMemoryEvent, StoredMemoryObject, ThingDeleteResult, ThingStore } from "../types.js";
2
+ export declare class NativeThingStore implements ThingStore {
3
+ private readonly binding;
4
+ static open(path: string): Promise<NativeThingStore>;
5
+ static isAvailable(): Promise<boolean>;
6
+ static getLoadedPath(): Promise<string | undefined>;
7
+ private constructor();
8
+ put(collection: string, object: MemoryObject): Promise<StoredMemoryObject>;
9
+ get<T = StoredMemoryObject>(collection: string, id: string): Promise<T | null>;
10
+ delete(collection: string, id: string): Promise<ThingDeleteResult>;
11
+ listObjects<T = StoredMemoryObject>(collection: string, options?: ListObjectsOptions): Promise<T[]>;
12
+ appendEvent(stream: string, event: MemoryEvent): Promise<StoredMemoryEvent>;
13
+ listEvents<T = StoredMemoryEvent>(stream?: string, options?: ListEventsOptions): Promise<T[]>;
14
+ pushJob(queue: string, payload: QueueJobPayload, options?: QueueJobOptions): Promise<QueueJob>;
15
+ claimJob(queue: string, options?: QueueClaimOptions): Promise<QueueJob | null>;
16
+ ackJob(queue: string, jobId: string): Promise<QueueJobResult>;
17
+ nackJob(queue: string, jobId: string, options?: QueueNackOptions): Promise<QueueJobResult>;
18
+ listJobs(queue: string): Promise<QueueJob[]>;
19
+ listDeadJobs(queue: string): Promise<QueueJob[]>;
20
+ search(query: string, options?: MemorySearchOptions): Promise<MemorySearchResult[]>;
21
+ putObjectsBatch(objects: Array<{
22
+ collection: string;
23
+ id: string;
24
+ body: string;
25
+ }>): Promise<StoredMemoryObject[]>;
26
+ appendEventsBatch(events: Array<{
27
+ stream: string;
28
+ eventType: string;
29
+ body: string;
30
+ }>): Promise<StoredMemoryEvent[]>;
31
+ pushJobsBatch(jobs: Array<{
32
+ queue: string;
33
+ id: string;
34
+ body: string;
35
+ maxAttempts: number;
36
+ delayMs: number;
37
+ }>): Promise<QueueJob[]>;
38
+ countObjects(): Promise<number>;
39
+ countEvents(): Promise<number>;
40
+ countActiveJobs(): Promise<number>;
41
+ countDeadJobs(): Promise<number>;
42
+ countLinks(): Promise<number>;
43
+ putBatch(collection: string, objects: MemoryObject[]): Promise<StoredMemoryObject[]>;
44
+ deleteBatch(collection: string, ids: string[]): Promise<number>;
45
+ createLink(fromRef: string, linkType: string, toRef: string, weight?: number, metadataJson?: string): Promise<import("../types.js").Link>;
46
+ deleteLink(id: string): Promise<boolean>;
47
+ getLink(id: string): Promise<import("../types.js").Link | null>;
48
+ getNeighbors(reference: string, direction: import("../types.js").LinkDirection, options: import("../types.js").LinkQueryOptions): Promise<import("../types.js").Link[]>;
49
+ listCollections(): Promise<string[]>;
50
+ listStreams(): Promise<string[]>;
51
+ listQueues(): Promise<string[]>;
52
+ }
53
+ //# sourceMappingURL=native-thing-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-thing-store.d.ts","sourceRoot":"","sources":["../../src/stores/native-thing-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,312 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { createRequire } from "node:module";
3
+ const DEFAULT_LEASE_MS = 30_000;
4
+ const NATIVE_PACKAGE_NAME = "@thingd/native";
5
+ export class NativeThingStore {
6
+ binding;
7
+ static async open(path) {
8
+ const native = await loadNativeModule();
9
+ return new NativeThingStore(native.NativeThingStore.open(path));
10
+ }
11
+ static async isAvailable() {
12
+ try {
13
+ await loadNativeModule();
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ static async getLoadedPath() {
21
+ try {
22
+ const native = await loadNativeModule();
23
+ return native.loadedPath;
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ }
29
+ constructor(binding) {
30
+ this.binding = binding;
31
+ }
32
+ async put(collection, object) {
33
+ const record = parseJson(this.binding.putObjectJson(collection, object.id, JSON.stringify(object)));
34
+ return objectFromNative(record);
35
+ }
36
+ async get(collection, id) {
37
+ const record = this.binding.getObjectJson(collection, id);
38
+ return record ? objectFromNative(parseJson(record)) : null;
39
+ }
40
+ async delete(collection, id) {
41
+ return {
42
+ deleted: this.binding.deleteObject(collection, id),
43
+ };
44
+ }
45
+ async listObjects(collection, options) {
46
+ const collectionsJson = JSON.stringify([collection]);
47
+ const filterJson = options?.filter ? JSON.stringify(options.filter) : undefined;
48
+ const sortField = options?.sortBy?.field;
49
+ const sortDirection = options?.sortBy?.direction;
50
+ return parseJson(this.binding.listObjectsJson(collectionsJson, filterJson, options?.limit, options?.offset, sortField, sortDirection)).map(objectFromNative);
51
+ }
52
+ async appendEvent(stream, event) {
53
+ const record = parseJson(this.binding.appendEventJson(stream, JSON.stringify(event)));
54
+ return eventFromNative(record);
55
+ }
56
+ async listEvents(stream, options) {
57
+ return parseJson(this.binding.listEventsJson(stream, options?.fromSequence, options?.limit)).map(eventFromNative);
58
+ }
59
+ async pushJob(queue, payload, options = {}) {
60
+ const record = parseJson(this.binding.pushJobJson(queue, options.idempotencyKey ?? randomUUID(), JSON.stringify(payload), options.maxAttempts ?? 3, options.delayMs ?? 0));
61
+ return jobFromNative(record);
62
+ }
63
+ async claimJob(queue, options = {}) {
64
+ const record = this.binding.claimJobJson(queue, options.leaseMs ?? DEFAULT_LEASE_MS);
65
+ return record ? jobFromNative(parseJson(record)) : null;
66
+ }
67
+ async ackJob(queue, jobId) {
68
+ return resultFromNative(parseJson(this.binding.ackJobJson(queue, jobId)));
69
+ }
70
+ async nackJob(queue, jobId, options = {}) {
71
+ const result = resultFromNative(parseJson(this.binding.nackJobJson(queue, jobId, options.delayMs ?? 0, options.error)));
72
+ return result;
73
+ }
74
+ async listJobs(queue) {
75
+ return parseJson(this.binding.listJobsJson(queue)).map(jobFromNative);
76
+ }
77
+ async listDeadJobs(queue) {
78
+ return parseJson(this.binding.listDeadJobsJson(queue)).map(jobFromNative);
79
+ }
80
+ async search(query, options = {}) {
81
+ const collectionsJson = options.collections ? JSON.stringify(options.collections) : undefined;
82
+ const filterJson = options.filter ? JSON.stringify(options.filter) : undefined;
83
+ const hits = parseJson(this.binding.searchJson(query, collectionsJson, options.limit, filterJson));
84
+ return hits.map((hit) => {
85
+ if (hit.kind === "object") {
86
+ const objectRecord = {
87
+ collection: hit.collection,
88
+ id: hit.id,
89
+ body: hit.body,
90
+ version: hit.version ?? 0,
91
+ createdAt: hit.createdAt ?? "",
92
+ updatedAt: hit.updatedAt ?? "",
93
+ };
94
+ const storedObject = objectFromNative(objectRecord);
95
+ return {
96
+ kind: "object",
97
+ id: hit.id,
98
+ collection: hit.collection,
99
+ score: hit.score,
100
+ value: storedObject,
101
+ };
102
+ }
103
+ else {
104
+ const eventRecord = {
105
+ stream: hit.collection,
106
+ eventType: hit.eventType ?? "event",
107
+ body: hit.body,
108
+ sequence: Number(hit.id) || 0,
109
+ createdAt: hit.createdAt ?? "",
110
+ };
111
+ const storedEvent = eventFromNative(eventRecord);
112
+ return {
113
+ kind: "event",
114
+ id: hit.id,
115
+ stream: hit.collection,
116
+ score: hit.score,
117
+ value: storedEvent,
118
+ };
119
+ }
120
+ });
121
+ }
122
+ async putObjectsBatch(objects) {
123
+ return parseJson(this.binding.putObjectsBatchJson(JSON.stringify(objects))).map(objectFromNative);
124
+ }
125
+ async appendEventsBatch(events) {
126
+ return parseJson(this.binding.appendEventsBatchJson(JSON.stringify(events))).map(eventFromNative);
127
+ }
128
+ async pushJobsBatch(jobs) {
129
+ return parseJson(this.binding.pushJobsBatchJson(JSON.stringify(jobs))).map(jobFromNative);
130
+ }
131
+ async countObjects() {
132
+ return this.binding.countObjectsJson();
133
+ }
134
+ async countEvents() {
135
+ return this.binding.countEventsJson();
136
+ }
137
+ async countActiveJobs() {
138
+ return this.binding.countActiveJobsJson();
139
+ }
140
+ async countDeadJobs() {
141
+ return this.binding.countDeadJobsJson();
142
+ }
143
+ async countLinks() {
144
+ return this.binding.countLinksJson();
145
+ }
146
+ async putBatch(collection, objects) {
147
+ const inputs = objects.map((obj) => ({ collection, id: obj.id, body: JSON.stringify(obj) }));
148
+ return parseJson(this.binding.putObjectsBatchJson(JSON.stringify(inputs))).map(objectFromNative);
149
+ }
150
+ async deleteBatch(collection, ids) {
151
+ const keys = ids.map((id) => [collection, id]);
152
+ return this.binding.deleteObjectsBatchJson(JSON.stringify(keys));
153
+ }
154
+ async createLink(fromRef, linkType, toRef, weight, metadataJson) {
155
+ return linkFromNative(parseJson(this.binding.createLinkJson(fromRef, linkType, toRef, weight, metadataJson)));
156
+ }
157
+ async deleteLink(id) {
158
+ return this.binding.deleteLink(id);
159
+ }
160
+ async getLink(id) {
161
+ const record = this.binding.getLinkJson(id);
162
+ return record ? linkFromNative(parseJson(record)) : null;
163
+ }
164
+ async getNeighbors(reference, direction, options) {
165
+ return parseJson(this.binding.getNeighborsJson(reference, direction, options.linkType, options.limit)).map(linkFromNative);
166
+ }
167
+ async listCollections() {
168
+ return parseJson(await this.binding.listCollectionsJson());
169
+ }
170
+ async listStreams() {
171
+ return parseJson(await this.binding.listStreamsJson());
172
+ }
173
+ async listQueues() {
174
+ return parseJson(await this.binding.listQueuesJson());
175
+ }
176
+ }
177
+ async function loadNativeModule() {
178
+ const customPath = process.env.THINGD_NATIVE_PATH;
179
+ if (customPath) {
180
+ try {
181
+ const require = createRequire(import.meta.url);
182
+ const binding = require(customPath);
183
+ return {
184
+ NativeThingStore: binding.NativeThingStore,
185
+ loadedPath: customPath,
186
+ };
187
+ }
188
+ catch (error) {
189
+ throw new Error(`Failed to load native store from THINGD_NATIVE_PATH="${customPath}": ${error instanceof Error ? error.message : String(error)}`);
190
+ }
191
+ }
192
+ // Try direct import (resolves via node_modules when published, or workspace link locally)
193
+ try {
194
+ const mod = (await import(NATIVE_PACKAGE_NAME));
195
+ return {
196
+ NativeThingStore: mod.NativeThingStore,
197
+ loadedPath: mod.loadedPath,
198
+ };
199
+ }
200
+ catch (importError) {
201
+ // Fallback: scan workspace-relative paths for local development
202
+ try {
203
+ const { existsSync } = await import("node:fs");
204
+ const { join, dirname } = await import("node:path");
205
+ const { fileURLToPath } = await import("node:url");
206
+ const __dirname = dirname(fileURLToPath(import.meta.url));
207
+ const platform = process.platform;
208
+ const arch = process.arch;
209
+ const candidates = [
210
+ // monorepo: packages/thingd/dist/stores/ -> ../../../../thingd-native/
211
+ join(__dirname, "../../../../thingd-native/dist/thingd_native.node"),
212
+ join(__dirname, "../../../../thingd-native/prebuilds", `${platform}-${arch}`, "thingd_native.node"),
213
+ // global install: sibling to thingd-cli in node_modules
214
+ join(__dirname, "../../../../../../thingd-native/dist/thingd_native.node"),
215
+ join(__dirname, "../../../../../../thingd-native/prebuilds", `${platform}-${arch}`, "thingd_native.node"),
216
+ ];
217
+ for (const candidate of candidates) {
218
+ if (existsSync(candidate)) {
219
+ try {
220
+ const require = createRequire(import.meta.url);
221
+ const binding = require(candidate);
222
+ if (binding?.NativeThingStore) {
223
+ return {
224
+ NativeThingStore: binding.NativeThingStore,
225
+ loadedPath: candidate,
226
+ };
227
+ }
228
+ }
229
+ catch {
230
+ // candidate failed to load, try next
231
+ }
232
+ }
233
+ }
234
+ }
235
+ catch {
236
+ // fallback resolution failed
237
+ }
238
+ throw new Error(`The native thingd driver is not available. Run "pnpm --filter thingd-native build" before using driver: "native". ${formatUnknownError(importError)}`);
239
+ }
240
+ }
241
+ function objectFromNative(record) {
242
+ const value = parseJson(record.body);
243
+ return {
244
+ ...value,
245
+ id: record.id,
246
+ collection: record.collection,
247
+ createdAt: record.createdAt ?? new Date().toISOString(),
248
+ updatedAt: record.updatedAt ?? new Date().toISOString(),
249
+ version: record.version,
250
+ };
251
+ }
252
+ function eventFromNative(record) {
253
+ const value = parseJson(record.body);
254
+ return {
255
+ ...value,
256
+ type: value.type ?? record.eventType,
257
+ id: String(record.sequence),
258
+ sequence: record.sequence,
259
+ stream: record.stream,
260
+ createdAt: record.createdAt ?? new Date().toISOString(),
261
+ };
262
+ }
263
+ function jobFromNative(record) {
264
+ return {
265
+ id: record.id,
266
+ queue: record.queue,
267
+ payload: parseJson(record.body),
268
+ status: record.status,
269
+ attempts: record.attempts,
270
+ maxAttempts: record.maxAttempts,
271
+ createdAt: record.createdAt ?? new Date().toISOString(),
272
+ availableAt: timestampToIso(record.availableAtMs),
273
+ leasedAt: optionalTimestampToIso(record.leasedAtMs),
274
+ leaseExpiresAt: optionalTimestampToIso(record.leaseExpiresAtMs),
275
+ completedAt: optionalTimestampToIso(record.completedAtMs),
276
+ deadAt: optionalTimestampToIso(record.deadAtMs),
277
+ lastError: record.lastError || undefined,
278
+ };
279
+ }
280
+ function linkFromNative(record) {
281
+ return {
282
+ ...record,
283
+ createdAt: record.createdAt ?? new Date().toISOString(),
284
+ };
285
+ }
286
+ function resultFromNative(result) {
287
+ if (!result.ok) {
288
+ return result;
289
+ }
290
+ return {
291
+ ok: true,
292
+ job: jobFromNative(result.job),
293
+ };
294
+ }
295
+ function parseJson(json) {
296
+ return JSON.parse(json);
297
+ }
298
+ function timestampToIso(value) {
299
+ if (value <= 0) {
300
+ return new Date().toISOString();
301
+ }
302
+ return new Date(value).toISOString();
303
+ }
304
+ function optionalTimestampToIso(value) {
305
+ return value === undefined ? undefined : timestampToIso(value);
306
+ }
307
+ function formatUnknownError(error) {
308
+ if (error instanceof Error) {
309
+ return `Original error: ${error.message}`;
310
+ }
311
+ return `Original error: ${String(error)}`;
312
+ }
@@ -0,0 +1,27 @@
1
+ import type { MemoryEvent, MemoryObject, MemorySearchOptions, MemorySearchResult, QueueClaimOptions, QueueJob, QueueJobOptions, QueueJobPayload, QueueJobResult, QueueNackOptions, StoredMemoryEvent, StoredMemoryObject, ThingDeleteResult, ThingStore } from "../types.js";
2
+ export type RemoteThingStoreOptions = {
3
+ url: string;
4
+ authToken?: string;
5
+ clientName?: string;
6
+ clientVersion?: string;
7
+ };
8
+ export declare class RemoteThingStore implements ThingStore {
9
+ private readonly client;
10
+ static open(urlOrOptions: string | RemoteThingStoreOptions): Promise<RemoteThingStore>;
11
+ private constructor();
12
+ put(collection: string, object: MemoryObject): Promise<StoredMemoryObject>;
13
+ get(collection: string, id: string): Promise<StoredMemoryObject | null>;
14
+ delete(collection: string, id: string): Promise<ThingDeleteResult>;
15
+ appendEvent(stream: string, event: MemoryEvent): Promise<StoredMemoryEvent>;
16
+ listEvents(stream?: string): Promise<StoredMemoryEvent[]>;
17
+ pushJob(queue: string, payload: QueueJobPayload, options?: QueueJobOptions): Promise<QueueJob>;
18
+ claimJob(queue: string, options?: QueueClaimOptions): Promise<QueueJob | null>;
19
+ ackJob(queue: string, jobId: string): Promise<QueueJobResult>;
20
+ nackJob(queue: string, jobId: string, options?: QueueNackOptions): Promise<QueueJobResult>;
21
+ listJobs(queue: string): Promise<QueueJob[]>;
22
+ listDeadJobs(queue: string): Promise<QueueJob[]>;
23
+ search(query: string, options?: MemorySearchOptions): Promise<MemorySearchResult[]>;
24
+ close(): Promise<void>;
25
+ private callTool;
26
+ }
27
+ //# sourceMappingURL=remote-thing-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-thing-store.d.ts","sourceRoot":"","sources":["../../src/stores/remote-thing-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,qBAAa,gBAAiB,YAAW,UAAU;IA2B7B,OAAO,CAAC,QAAQ,CAAC,MAAM;WA1B9B,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0B5F,OAAO;IAEP,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAO1E,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAOvE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAOlE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAO3E,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAMzD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,CAAC;IAUpB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAOlF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC;IAS9F,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM5C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMhD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAQjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAId,QAAQ;CAQvB"}
@@ -0,0 +1,131 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ export class RemoteThingStore {
4
+ client;
5
+ static async open(urlOrOptions) {
6
+ const options = typeof urlOrOptions === "string"
7
+ ? {
8
+ url: urlOrOptions,
9
+ }
10
+ : urlOrOptions;
11
+ const client = new Client({
12
+ name: options.clientName ?? "thingd-node-sdk",
13
+ version: options.clientVersion ?? "0.1.0",
14
+ });
15
+ const transport = new StreamableHTTPClientTransport(new URL(resolveMcpUrl(options.url)), {
16
+ requestInit: options.authToken
17
+ ? {
18
+ headers: {
19
+ Authorization: `Bearer ${options.authToken}`,
20
+ },
21
+ }
22
+ : undefined,
23
+ });
24
+ await client.connect(transport);
25
+ return new RemoteThingStore(client);
26
+ }
27
+ constructor(client) {
28
+ this.client = client;
29
+ }
30
+ put(collection, object) {
31
+ return this.callTool("thing.put", {
32
+ collection,
33
+ object,
34
+ });
35
+ }
36
+ get(collection, id) {
37
+ return this.callTool("thing.get", {
38
+ collection,
39
+ id,
40
+ });
41
+ }
42
+ delete(collection, id) {
43
+ return this.callTool("thing.delete", {
44
+ collection,
45
+ id,
46
+ });
47
+ }
48
+ appendEvent(stream, event) {
49
+ return this.callTool("thing.events.append", {
50
+ stream,
51
+ event,
52
+ });
53
+ }
54
+ listEvents(stream) {
55
+ return this.callTool("thing.events.list", {
56
+ stream,
57
+ });
58
+ }
59
+ pushJob(queue, payload, options = {}) {
60
+ return this.callTool("thing.queue.push", {
61
+ queue,
62
+ payload,
63
+ idempotencyKey: options.idempotencyKey,
64
+ maxAttempts: options.maxAttempts,
65
+ delayMs: options.delayMs,
66
+ });
67
+ }
68
+ claimJob(queue, options = {}) {
69
+ return this.callTool("thing.queue.claim", {
70
+ queue,
71
+ leaseMs: options.leaseMs,
72
+ });
73
+ }
74
+ ackJob(queue, jobId) {
75
+ return this.callTool("thing.queue.ack", {
76
+ queue,
77
+ id: jobId,
78
+ });
79
+ }
80
+ nackJob(queue, jobId, options = {}) {
81
+ return this.callTool("thing.queue.nack", {
82
+ queue,
83
+ id: jobId,
84
+ delayMs: options.delayMs,
85
+ error: options.error,
86
+ });
87
+ }
88
+ listJobs(queue) {
89
+ return this.callTool("thing.queue.list", {
90
+ queue,
91
+ });
92
+ }
93
+ listDeadJobs(queue) {
94
+ return this.callTool("thing.queue.dead", {
95
+ queue,
96
+ });
97
+ }
98
+ search(query, options = {}) {
99
+ return this.callTool("thing.search", {
100
+ query,
101
+ collections: options.collections,
102
+ limit: options.limit,
103
+ });
104
+ }
105
+ async close() {
106
+ await this.client.close();
107
+ }
108
+ async callTool(name, args) {
109
+ return parseJsonToolResult((await this.client.callTool({
110
+ name,
111
+ arguments: args,
112
+ })));
113
+ }
114
+ }
115
+ function resolveMcpUrl(value) {
116
+ const normalized = value.startsWith("thingd://")
117
+ ? `http://${value.slice("thingd://".length)}`
118
+ : value;
119
+ const url = new URL(normalized);
120
+ if (url.pathname === "" || url.pathname === "/") {
121
+ url.pathname = "/mcp";
122
+ }
123
+ return url.toString();
124
+ }
125
+ function parseJsonToolResult(result) {
126
+ const text = result.content.find((part) => part.type === "text" && typeof part.text === "string")?.text;
127
+ if (!text) {
128
+ throw new Error("thingd remote tool did not return JSON text content");
129
+ }
130
+ return JSON.parse(text);
131
+ }
@@ -0,0 +1,48 @@
1
+ import type { ListEventsOptions, ListObjectsOptions, MemoryEvent, MemoryObject, MemoryQueue, MemorySearchOptions, MemorySearchResult, StoredMemoryEvent, StoredMemoryObject, ThingDConnection, ThingDeleteResult, ThingStore } from "./types.js";
2
+ export type ThingDDriver = "memory" | "native" | "cloud";
3
+ export type ThingDOpenOptions = {
4
+ driver?: ThingDDriver;
5
+ store?: ThingStore;
6
+ authToken?: string;
7
+ /** Alias for authToken. If both are set, authToken takes precedence. */
8
+ apiKey?: string;
9
+ };
10
+ export type ThingDOpenConfig = ThingDOpenOptions & {
11
+ path?: string;
12
+ url?: string;
13
+ };
14
+ export declare class ThingD implements ThingDConnection {
15
+ readonly path: string;
16
+ private readonly store;
17
+ static open(pathOrConfig?: string | ThingDOpenConfig, options?: ThingDOpenOptions): Promise<ThingD>;
18
+ private constructor();
19
+ put(collection: string, object: MemoryObject): Promise<StoredMemoryObject>;
20
+ get<T = StoredMemoryObject>(collection: string, id: string): Promise<T | null>;
21
+ delete(collection: string, id: string): Promise<ThingDeleteResult>;
22
+ listObjects<T = StoredMemoryObject>(collection: string, options?: ListObjectsOptions): Promise<T[]>;
23
+ search(query: string, options?: MemorySearchOptions): Promise<MemorySearchResult[]>;
24
+ searchObjects<T = StoredMemoryObject>(query: string, options?: MemorySearchOptions): Promise<T[]>;
25
+ putBatch(collection: string, objects: MemoryObject[]): Promise<StoredMemoryObject[]>;
26
+ deleteBatch(collection: string, ids: string[]): Promise<number>;
27
+ readonly events: {
28
+ append: (stream: string, event: MemoryEvent) => Promise<StoredMemoryEvent>;
29
+ list: <T = StoredMemoryEvent>(stream?: string, options?: ListEventsOptions) => Promise<T[]>;
30
+ };
31
+ queue(name: string): MemoryQueue;
32
+ readonly links: {
33
+ create: (fromRef: string, linkType: string, toRef: string, weight?: number, metadataJson?: string) => Promise<import("./types.js").Link>;
34
+ delete: (id: string) => Promise<boolean>;
35
+ get: (id: string) => Promise<import("./types.js").Link | null>;
36
+ neighbors: (reference: string, direction?: import("./types.js").LinkDirection, options?: import("./types.js").LinkQueryOptions) => Promise<import("./types.js").Link[]>;
37
+ };
38
+ close(): Promise<void>;
39
+ countObjects(): Promise<number>;
40
+ countEvents(): Promise<number>;
41
+ countActiveJobs(): Promise<number>;
42
+ countDeadJobs(): Promise<number>;
43
+ countLinks(): Promise<number>;
44
+ listCollections(): Promise<string[]>;
45
+ listStreams(): Promise<string[]>;
46
+ listQueues(): Promise<string[]>;
47
+ }
48
+ //# sourceMappingURL=thingd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thingd.d.ts","sourceRoot":"","sources":["../src/thingd.ts"],"names":[],"mappings":"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"}