@atlasnpm/atlas-api-helper 0.2.4 → 0.2.6

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 CHANGED
@@ -1,7 +1,5 @@
1
1
  # Atlas Command HTTP Client (TypeScript)
2
2
 
3
- `@atlasnpm/atlas-api-helper` has been updated to version 0.2.1 with a comprehensive HTTP client for the Atlas Command REST API. This version now includes full API parity with the Python `atlas_asset_ws_client` package.
4
-
5
3
  ## Installation
6
4
 
7
5
  ```bash
@@ -22,13 +20,12 @@ const client = new AtlasHttpClient({
22
20
  const entities = await client.listEntities();
23
21
  console.log("Entities", entities);
24
22
 
25
- await client.createTask({
26
- task_id: "survey-1",
27
- status: "pending",
28
- components: { parameters: { latitude: 40.7, longitude: -74.0 } },
23
+ await client.createEntity("asset-1", "asset", "Surveyor One", "drone", {
24
+ telemetry: { latitude: 40.7, longitude: -74.0 },
29
25
  });
26
+ await client.createTask("survey-1", { parameters: { latitude: 40.7, longitude: -74.0 } });
30
27
 
31
- // New API methods (version 0.2.1)
28
+ // Entity telemetry updates
32
29
  const entity = await client.getEntityByAlias("drone-1");
33
30
  await client.updateEntityTelemetry("drone-1", {
34
31
  latitude: 40.7128,
@@ -39,8 +36,18 @@ await client.updateEntityTelemetry("drone-1", {
39
36
  });
40
37
 
41
38
  // Task lifecycle management
42
- await client.startTask("task-1", { started_by: "operator-1" });
43
- await client.completeTask("task-1", { result: { data: "success" } });
39
+ await client.startTask("task-1");
40
+ await client.completeTask("task-1");
41
+ await client.failTask("task-2", "Calibration failed", { code: "CAL-01" });
42
+
43
+ // Object upload + reference helpers
44
+ const stored = await client.createObject(videoBlob, "mission-video", "mission_video", [
45
+ { entity_id: "asset-1" },
46
+ ]);
47
+ await client.addObjectReference(stored["object_id"] as string, undefined, "task-1");
48
+ await client.updateObject("mission-video", ["mission_video"], [
49
+ { task_id: "task-1" },
50
+ ]);
44
51
 
45
52
  // Query capabilities
46
53
  const changes = await client.getChangedSince("2023-01-01T00:00:00Z", 10);
@@ -55,36 +62,33 @@ const fullData = await client.getFullDataset({
55
62
 
56
63
  The client now exposes comprehensive helpers for every HTTP endpoint, matching the Python client:
57
64
 
58
- ### Entities
59
65
  - `listEntities(limit?, offset?)` - List all entities with pagination
60
66
  - `getEntity(entityId)` - Get a specific entity by ID
61
67
  - `getEntityByAlias(alias)` - Get entity by alias (NEW in 0.2.1)
62
- - `createEntity(body)` - Create a new entity
63
- - `updateEntity(entityId, body)` - Update an existing entity
68
+ - `createEntity(entityId, entityType, alias, subtype, components?)` - Create a new entity
69
+ - `updateEntity(entityId, components)` - Update an existing entity (components payload required)
64
70
  - `deleteEntity(entityId)` - Delete an entity
65
71
  - `updateEntityTelemetry(entityId, telemetry)` - Update entity telemetry with specific parameters (NEW in 0.2.1)
66
72
 
67
- ### Tasks
68
73
  - `listTasks(limit?, status?)` - List tasks with optional status filter
69
74
  - `getTask(taskId)` - Get a specific task
70
- - `createTask(body)` - Create a new task
71
- - `updateTask(taskId, body)` - Update an existing task
75
+ - `createTask(taskId, components?)` - Create a new task
76
+ - `updateTask(taskId, components)` - Update an existing task (components payload required)
72
77
  - `deleteTask(taskId)` - Delete a task
73
78
  - `getTasksByEntity(entityId, limit?, status?)` - Get tasks by entity
74
- - `startTask(taskId, started_by?)` - Start a task (NEW in 0.2.1)
75
- - `completeTask(taskId, result?)` - Complete a task (NEW in 0.2.1)
76
- - `failTask(taskId, error_message?, error_details?)` - Fail a task (NEW in 0.2.1)
79
+ - `startTask(taskId)` - Start a task (NEW in 0.2.1)
80
+ - `completeTask(taskId)` - Complete a task (NEW in 0.2.1)
81
+ - `failTask(taskId, errorMessage?, errorDetails?)` - Fail a task (NEW in 0.2.1)
77
82
 
78
- ### Objects
79
83
  - `listObjects(limit?, offset?, contentType?)` - List objects with filters
80
84
  - `getObject(objectId)` - Get a specific object
81
- - `createObject(body)` - Create a new object
82
- - `updateObject(objectId, body)` - Update an existing object
85
+ - `createObject(file, objectId, usageHint?, referencedBy?)` - Upload an object and optionally assign references
86
+ - `updateObject(objectId, usageHints?, referencedBy?)` - Update metadata and references (at least one of `usageHints` or `referencedBy` is required)
83
87
  - `deleteObject(objectId)` - Delete an object
84
88
  - `getObjectsByEntity(entityId, limit?)` - Get objects by entity
85
89
  - `getObjectsByTask(taskId, limit?)` - Get objects by task
86
- - `addObjectReference(objectId, entity_id?, task_id?)` - Add object reference
87
- - `removeObjectReference(objectId, entity_id?, task_id?)` - Remove object reference
90
+ - `addObjectReference(objectId, entityId?, taskId?)` - Add object reference
91
+ - `removeObjectReference(objectId, entityId?, taskId?)` - Remove object reference
88
92
  - `findOrphanedObjects(limit?)` - Find orphaned objects
89
93
  - `getObjectReferences(objectId)` - Get object references
90
94
  - `validateObjectReferences(objectId)` - Validate object references
@@ -133,18 +137,6 @@ npm run test
133
137
 
134
138
  The build produces both ESM and CJS bundles plus `.d.ts` type definitions via `tsup`.
135
139
 
136
- ## Version 0.2.1 Changes
137
-
138
- This update brings the TypeScript client to full feature parity with the Python `atlas_asset_ws_client` package:
139
-
140
- - ✅ Added `getEntityByAlias` method
141
- - ✅ Added `updateEntityTelemetry` with specific telemetry parameters
142
- - ✅ Added task lifecycle methods: `startTask`, `completeTask`, `failTask`
143
- - ✅ Added query methods: `getChangedSince`, `getFullDataset`
144
- - ✅ Enhanced type system with comprehensive interfaces
145
- - ✅ Updated to match Python API signatures and behavior
146
- - ✅ Version bump to 0.2.1 to match Python package
147
-
148
140
  ## Publishing
149
141
 
150
- Publishing is handled by `.github/workflows/publish-controller-websocket-client.yml`. The artifact now contains the comprehensive HTTP client described above. Ensure the `@atlasnpm` scope and automation token are set up as documented in the workflow README before triggering a release.
142
+ Publishing is handled by `.github/workflows/publish-atlas-api-helper.yml`. The artifact now contains the comprehensive HTTP client described above. Ensure the `@atlasnpm` scope and automation token are set up as documented in the workflow README before triggering a release.
package/dist/index.cjs CHANGED
@@ -44,6 +44,13 @@ var AtlasHttpClient = class {
44
44
  }
45
45
  return headers;
46
46
  }
47
+ multipartHeaders() {
48
+ const headers = {};
49
+ if (this.token) {
50
+ headers["Authorization"] = `Bearer ${this.token}`;
51
+ }
52
+ return headers;
53
+ }
47
54
  async request(method, path, body, params) {
48
55
  const url = new URL(`${this.baseUrl}${path}`);
49
56
  if (params) {
@@ -66,6 +73,22 @@ var AtlasHttpClient = class {
66
73
  }
67
74
  return await response.json();
68
75
  }
76
+ async multipartRequest(path, formData) {
77
+ const url = new URL(`${this.baseUrl}${path}`);
78
+ const response = await this.fetchImpl(url.toString(), {
79
+ method: "POST",
80
+ headers: this.multipartHeaders(),
81
+ body: formData
82
+ });
83
+ if (!response.ok) {
84
+ const detail = await response.text();
85
+ throw new Error(`HTTP ${response.status}: ${detail}`);
86
+ }
87
+ if (response.status === 204) {
88
+ return void 0;
89
+ }
90
+ return await response.json();
91
+ }
69
92
  // Entities ------------------------------------------------------------------
70
93
  listEntities(limit = 100, offset = 0) {
71
94
  return this.request("GET", "/entities", null, { limit, offset });
@@ -76,17 +99,36 @@ var AtlasHttpClient = class {
76
99
  getEntityByAlias(alias) {
77
100
  return this.request("GET", `/entities/alias/${alias}`);
78
101
  }
79
- createEntity(body) {
80
- return this.request("POST", "/entities", body);
81
- }
82
- updateEntity(entityId, body) {
83
- return this.request("PATCH", `/entities/${entityId}`, body);
102
+ createEntity(entityId, entityType, alias, subtype, components) {
103
+ const payload = {
104
+ entity_id: entityId,
105
+ entity_type: entityType,
106
+ alias,
107
+ subtype
108
+ };
109
+ if (components !== void 0) payload.components = components;
110
+ return this.request("POST", "/entities", payload);
111
+ }
112
+ updateEntity(entityId, components, options) {
113
+ if (components === void 0 && options?.subtype === void 0) {
114
+ throw new Error("AtlasHttpClient.updateEntity requires a components payload or subtype.");
115
+ }
116
+ const payload = {};
117
+ if (components !== void 0) payload.components = components;
118
+ if (options?.subtype !== void 0) payload.subtype = options.subtype;
119
+ return this.request("PATCH", `/entities/${entityId}`, payload);
84
120
  }
85
121
  deleteEntity(entityId) {
86
122
  return this.request("DELETE", `/entities/${entityId}`);
87
123
  }
88
- updateEntityTelemetry(entityId, body) {
89
- return this.request("PATCH", `/entities/${entityId}/telemetry`, body);
124
+ updateEntityTelemetry(entityId, options) {
125
+ const payload = {};
126
+ if (options.latitude !== void 0) payload.latitude = options.latitude;
127
+ if (options.longitude !== void 0) payload.longitude = options.longitude;
128
+ if (options.altitude_m !== void 0) payload.altitude_m = options.altitude_m;
129
+ if (options.speed_m_s !== void 0) payload.speed_m_s = options.speed_m_s;
130
+ if (options.heading_deg !== void 0) payload.heading_deg = options.heading_deg;
131
+ return this.request("PATCH", `/entities/${entityId}/telemetry`, payload);
90
132
  }
91
133
  // Tasks ---------------------------------------------------------------------
92
134
  listTasks(limit = 25, status) {
@@ -95,11 +137,28 @@ var AtlasHttpClient = class {
95
137
  getTask(taskId) {
96
138
  return this.request("GET", `/tasks/${taskId}`);
97
139
  }
98
- createTask(body) {
99
- return this.request("POST", "/tasks", body);
100
- }
101
- updateTask(taskId, body) {
102
- return this.request("PATCH", `/tasks/${taskId}`, body);
140
+ createTask(taskId, components, options) {
141
+ const payload = {
142
+ task_id: taskId,
143
+ status: options?.status || "pending"
144
+ };
145
+ if (options?.entity_id !== void 0) payload.entity_id = options.entity_id;
146
+ if (components !== void 0) payload.components = components;
147
+ if (options?.extra !== void 0) payload.extra = options.extra;
148
+ return this.request("POST", "/tasks", payload);
149
+ }
150
+ updateTask(taskId, components, options) {
151
+ if (components === void 0 && options === void 0) {
152
+ throw new Error(
153
+ "AtlasHttpClient.updateTask requires a components payload or options."
154
+ );
155
+ }
156
+ const payload = {};
157
+ if (components !== void 0) payload.components = components;
158
+ if (options?.status !== void 0) payload.status = options.status;
159
+ if (options?.entity_id !== void 0) payload.entity_id = options.entity_id;
160
+ if (options?.extra !== void 0) payload.extra = options.extra;
161
+ return this.request("PATCH", `/tasks/${taskId}`, payload);
103
162
  }
104
163
  deleteTask(taskId) {
105
164
  return this.request("DELETE", `/tasks/${taskId}`);
@@ -107,27 +166,56 @@ var AtlasHttpClient = class {
107
166
  getTasksByEntity(entityId, limit = 25, status) {
108
167
  return this.request("GET", `/entities/${entityId}/tasks`, null, { limit, status });
109
168
  }
110
- startTask(taskId, body = {}) {
111
- return this.request("POST", `/tasks/${taskId}/start`, body);
169
+ startTask(taskId) {
170
+ return this.request("POST", `/tasks/${taskId}/start`, {});
112
171
  }
113
- completeTask(taskId, body = {}) {
114
- return this.request("POST", `/tasks/${taskId}/complete`, body);
172
+ completeTask(taskId) {
173
+ return this.request("POST", `/tasks/${taskId}/complete`, {});
115
174
  }
116
- failTask(taskId, body = {}) {
117
- return this.request("POST", `/tasks/${taskId}/fail`, body);
175
+ failTask(taskId, errorMessage, errorDetails) {
176
+ const payload = {};
177
+ if (errorMessage !== void 0) payload.error_message = errorMessage;
178
+ if (errorDetails !== void 0) payload.error_details = errorDetails;
179
+ return this.request("POST", `/tasks/${taskId}/fail`, payload);
118
180
  }
119
181
  // Objects -------------------------------------------------------------------
120
- listObjects(limit = 100, offset = 0, contentType) {
121
- return this.request("GET", "/objects", null, { limit, offset, content_type: contentType });
182
+ listObjects(limit = 100, offset = 0, contentType, type) {
183
+ return this.request("GET", "/objects", null, { limit, offset, content_type: contentType, type });
122
184
  }
123
185
  getObject(objectId) {
124
186
  return this.request("GET", `/objects/${objectId}`);
125
187
  }
126
- createObject(body) {
127
- return this.request("POST", "/objects", body);
188
+ async createObject(file, objectId, usageHint, referencedBy) {
189
+ const formData = new FormData();
190
+ formData.append("object_id", objectId);
191
+ const filename = file.name ?? "upload.bin";
192
+ formData.append("file", file, filename);
193
+ if (usageHint) {
194
+ formData.append("usage_hint", usageHint);
195
+ }
196
+ const stored = await this.multipartRequest("/objects/upload", formData);
197
+ const storedObjectId = stored["object_id"];
198
+ if (referencedBy && storedObjectId !== void 0) {
199
+ for (const reference of referencedBy) {
200
+ await this.addObjectReference(storedObjectId, reference.entity_id, reference.task_id);
201
+ }
202
+ } else if (referencedBy && storedObjectId === void 0) {
203
+ throw new Error(
204
+ "AtlasHttpClient.createObject expected the upload response to include an object_id before attaching references."
205
+ );
206
+ }
207
+ return stored;
128
208
  }
129
- updateObject(objectId, body) {
130
- return this.request("PATCH", `/objects/${objectId}`, body);
209
+ updateObject(objectId, usageHints, referencedBy) {
210
+ if (usageHints === void 0 && referencedBy === void 0) {
211
+ throw new Error(
212
+ "AtlasHttpClient.updateObject requires usageHints or referencedBy to make an update."
213
+ );
214
+ }
215
+ const payload = {};
216
+ if (usageHints !== void 0) payload.usage_hints = usageHints;
217
+ if (referencedBy !== void 0) payload.referenced_by = referencedBy;
218
+ return this.request("PATCH", `/objects/${objectId}`, payload);
131
219
  }
132
220
  deleteObject(objectId) {
133
221
  return this.request("DELETE", `/objects/${objectId}`);
@@ -138,11 +226,17 @@ var AtlasHttpClient = class {
138
226
  getObjectsByTask(taskId, limit = 50) {
139
227
  return this.request("GET", `/tasks/${taskId}/objects`, null, { limit });
140
228
  }
141
- addObjectReference(objectId, body) {
142
- return this.request("POST", `/objects/${objectId}/references`, body);
143
- }
144
- removeObjectReference(objectId, body) {
145
- return this.request("DELETE", `/objects/${objectId}/references`, body);
229
+ addObjectReference(objectId, entityId, taskId) {
230
+ const payload = {};
231
+ if (entityId !== void 0) payload.entity_id = entityId;
232
+ if (taskId !== void 0) payload.task_id = taskId;
233
+ return this.request("POST", `/objects/${objectId}/references`, payload);
234
+ }
235
+ removeObjectReference(objectId, entityId, taskId) {
236
+ const payload = {};
237
+ if (entityId !== void 0) payload.entity_id = entityId;
238
+ if (taskId !== void 0) payload.task_id = taskId;
239
+ return this.request("DELETE", `/objects/${objectId}/references`, payload);
146
240
  }
147
241
  findOrphanedObjects(limit = 100) {
148
242
  return this.request("GET", "/objects/orphaned", null, { limit });
package/dist/index.d.cts CHANGED
@@ -13,14 +13,18 @@ declare class AtlasHttpClient {
13
13
  private readonly fetchImpl;
14
14
  constructor(options: ClientOptions);
15
15
  private headers;
16
+ private multipartHeaders;
16
17
  private request;
18
+ private multipartRequest;
17
19
  listEntities(limit?: number, offset?: number): Promise<unknown>;
18
20
  getEntity(entityId: string): Promise<unknown>;
19
21
  getEntityByAlias(alias: string): Promise<unknown>;
20
- createEntity(body: JsonRecord): Promise<unknown>;
21
- updateEntity(entityId: string, body: JsonRecord): Promise<unknown>;
22
+ createEntity(entityId: string, entityType: string, alias: string, subtype: string, components?: JsonRecord): Promise<unknown>;
23
+ updateEntity(entityId: string, components?: JsonRecord, options?: {
24
+ subtype?: string;
25
+ }): Promise<unknown>;
22
26
  deleteEntity(entityId: string): Promise<unknown>;
23
- updateEntityTelemetry(entityId: string, body: {
27
+ updateEntityTelemetry(entityId: string, options: {
24
28
  latitude?: number;
25
29
  longitude?: number;
26
30
  altitude_m?: number;
@@ -29,35 +33,36 @@ declare class AtlasHttpClient {
29
33
  }): Promise<unknown>;
30
34
  listTasks(limit?: number, status?: string): Promise<unknown>;
31
35
  getTask(taskId: string): Promise<unknown>;
32
- createTask(body: JsonRecord): Promise<unknown>;
33
- updateTask(taskId: string, body: JsonRecord): Promise<unknown>;
34
- deleteTask(taskId: string): Promise<unknown>;
35
- getTasksByEntity(entityId: string, limit?: number, status?: string): Promise<unknown>;
36
- startTask(taskId: string, body?: {
37
- started_by?: string;
38
- }): Promise<unknown>;
39
- completeTask(taskId: string, body?: {
40
- result?: JsonRecord;
36
+ createTask(taskId: string, components?: JsonRecord, options?: {
37
+ status?: string;
38
+ entity_id?: string;
39
+ extra?: JsonRecord;
41
40
  }): Promise<unknown>;
42
- failTask(taskId: string, body?: {
43
- error_message?: string;
44
- error_details?: JsonRecord;
41
+ updateTask(taskId: string, components?: JsonRecord, options?: {
42
+ status?: string;
43
+ entity_id?: string;
44
+ extra?: JsonRecord;
45
45
  }): Promise<unknown>;
46
- listObjects(limit?: number, offset?: number, contentType?: string): Promise<unknown>;
46
+ deleteTask(taskId: string): Promise<unknown>;
47
+ getTasksByEntity(entityId: string, limit?: number, status?: string): Promise<unknown>;
48
+ startTask(taskId: string): Promise<unknown>;
49
+ completeTask(taskId: string): Promise<unknown>;
50
+ failTask(taskId: string, errorMessage?: string, errorDetails?: JsonRecord): Promise<unknown>;
51
+ listObjects(limit?: number, offset?: number, contentType?: string, type?: string): Promise<unknown>;
47
52
  getObject(objectId: string): Promise<unknown>;
48
- createObject(body: JsonRecord): Promise<unknown>;
49
- updateObject(objectId: string, body: JsonRecord): Promise<unknown>;
50
- deleteObject(objectId: string): Promise<unknown>;
51
- getObjectsByEntity(entityId: string, limit?: number): Promise<unknown>;
52
- getObjectsByTask(taskId: string, limit?: number): Promise<unknown>;
53
- addObjectReference(objectId: string, body: {
53
+ createObject(file: Blob | File, objectId: string, usageHint?: string, referencedBy?: Array<{
54
54
  entity_id?: string;
55
55
  task_id?: string;
56
- }): Promise<unknown>;
57
- removeObjectReference(objectId: string, body: {
56
+ }>): Promise<JsonRecord>;
57
+ updateObject(objectId: string, usageHints?: string[], referencedBy?: Array<{
58
58
  entity_id?: string;
59
59
  task_id?: string;
60
- }): Promise<unknown>;
60
+ }>): Promise<unknown>;
61
+ deleteObject(objectId: string): Promise<unknown>;
62
+ getObjectsByEntity(entityId: string, limit?: number): Promise<unknown>;
63
+ getObjectsByTask(taskId: string, limit?: number): Promise<unknown>;
64
+ addObjectReference(objectId: string, entityId?: string, taskId?: string): Promise<unknown>;
65
+ removeObjectReference(objectId: string, entityId?: string, taskId?: string): Promise<unknown>;
61
66
  findOrphanedObjects(limit?: number): Promise<unknown>;
62
67
  getObjectReferences(objectId: string): Promise<unknown>;
63
68
  validateObjectReferences(objectId: string): Promise<unknown>;
@@ -72,9 +77,10 @@ declare class AtlasHttpClient {
72
77
 
73
78
  interface Entity {
74
79
  entity_id: string;
80
+ type: string;
81
+ subtype?: string;
82
+ alias?: string;
75
83
  json: {
76
- type: "asset" | "track" | "geofeature" | string;
77
- alias?: string;
78
84
  components?: Record<string, unknown>;
79
85
  [key: string]: unknown;
80
86
  };
@@ -83,8 +89,9 @@ interface Entity {
83
89
  }
84
90
  interface Task {
85
91
  task_id: string;
92
+ status: string;
93
+ entity_id?: string;
86
94
  json: {
87
- status: string;
88
95
  components?: Record<string, unknown>;
89
96
  [key: string]: unknown;
90
97
  };
@@ -93,6 +100,9 @@ interface Task {
93
100
  }
94
101
  interface StoredObject {
95
102
  object_id: string;
103
+ path?: string;
104
+ content_type?: string;
105
+ type?: string;
96
106
  json: Record<string, unknown>;
97
107
  created_at?: string;
98
108
  updated_at?: string;
@@ -182,6 +192,7 @@ interface ObjectCreate {
182
192
  bucket?: string;
183
193
  size_bytes?: number;
184
194
  content_type?: string;
195
+ type?: string;
185
196
  usage_hints?: string[];
186
197
  referenced_by?: ObjectReference[];
187
198
  extra?: Record<string, unknown>;
@@ -191,6 +202,7 @@ interface ObjectUpdate {
191
202
  bucket?: string;
192
203
  size_bytes?: number;
193
204
  content_type?: string;
205
+ type?: string;
194
206
  usage_hints?: string[];
195
207
  referenced_by?: ObjectReference[];
196
208
  extra?: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -13,14 +13,18 @@ declare class AtlasHttpClient {
13
13
  private readonly fetchImpl;
14
14
  constructor(options: ClientOptions);
15
15
  private headers;
16
+ private multipartHeaders;
16
17
  private request;
18
+ private multipartRequest;
17
19
  listEntities(limit?: number, offset?: number): Promise<unknown>;
18
20
  getEntity(entityId: string): Promise<unknown>;
19
21
  getEntityByAlias(alias: string): Promise<unknown>;
20
- createEntity(body: JsonRecord): Promise<unknown>;
21
- updateEntity(entityId: string, body: JsonRecord): Promise<unknown>;
22
+ createEntity(entityId: string, entityType: string, alias: string, subtype: string, components?: JsonRecord): Promise<unknown>;
23
+ updateEntity(entityId: string, components?: JsonRecord, options?: {
24
+ subtype?: string;
25
+ }): Promise<unknown>;
22
26
  deleteEntity(entityId: string): Promise<unknown>;
23
- updateEntityTelemetry(entityId: string, body: {
27
+ updateEntityTelemetry(entityId: string, options: {
24
28
  latitude?: number;
25
29
  longitude?: number;
26
30
  altitude_m?: number;
@@ -29,35 +33,36 @@ declare class AtlasHttpClient {
29
33
  }): Promise<unknown>;
30
34
  listTasks(limit?: number, status?: string): Promise<unknown>;
31
35
  getTask(taskId: string): Promise<unknown>;
32
- createTask(body: JsonRecord): Promise<unknown>;
33
- updateTask(taskId: string, body: JsonRecord): Promise<unknown>;
34
- deleteTask(taskId: string): Promise<unknown>;
35
- getTasksByEntity(entityId: string, limit?: number, status?: string): Promise<unknown>;
36
- startTask(taskId: string, body?: {
37
- started_by?: string;
38
- }): Promise<unknown>;
39
- completeTask(taskId: string, body?: {
40
- result?: JsonRecord;
36
+ createTask(taskId: string, components?: JsonRecord, options?: {
37
+ status?: string;
38
+ entity_id?: string;
39
+ extra?: JsonRecord;
41
40
  }): Promise<unknown>;
42
- failTask(taskId: string, body?: {
43
- error_message?: string;
44
- error_details?: JsonRecord;
41
+ updateTask(taskId: string, components?: JsonRecord, options?: {
42
+ status?: string;
43
+ entity_id?: string;
44
+ extra?: JsonRecord;
45
45
  }): Promise<unknown>;
46
- listObjects(limit?: number, offset?: number, contentType?: string): Promise<unknown>;
46
+ deleteTask(taskId: string): Promise<unknown>;
47
+ getTasksByEntity(entityId: string, limit?: number, status?: string): Promise<unknown>;
48
+ startTask(taskId: string): Promise<unknown>;
49
+ completeTask(taskId: string): Promise<unknown>;
50
+ failTask(taskId: string, errorMessage?: string, errorDetails?: JsonRecord): Promise<unknown>;
51
+ listObjects(limit?: number, offset?: number, contentType?: string, type?: string): Promise<unknown>;
47
52
  getObject(objectId: string): Promise<unknown>;
48
- createObject(body: JsonRecord): Promise<unknown>;
49
- updateObject(objectId: string, body: JsonRecord): Promise<unknown>;
50
- deleteObject(objectId: string): Promise<unknown>;
51
- getObjectsByEntity(entityId: string, limit?: number): Promise<unknown>;
52
- getObjectsByTask(taskId: string, limit?: number): Promise<unknown>;
53
- addObjectReference(objectId: string, body: {
53
+ createObject(file: Blob | File, objectId: string, usageHint?: string, referencedBy?: Array<{
54
54
  entity_id?: string;
55
55
  task_id?: string;
56
- }): Promise<unknown>;
57
- removeObjectReference(objectId: string, body: {
56
+ }>): Promise<JsonRecord>;
57
+ updateObject(objectId: string, usageHints?: string[], referencedBy?: Array<{
58
58
  entity_id?: string;
59
59
  task_id?: string;
60
- }): Promise<unknown>;
60
+ }>): Promise<unknown>;
61
+ deleteObject(objectId: string): Promise<unknown>;
62
+ getObjectsByEntity(entityId: string, limit?: number): Promise<unknown>;
63
+ getObjectsByTask(taskId: string, limit?: number): Promise<unknown>;
64
+ addObjectReference(objectId: string, entityId?: string, taskId?: string): Promise<unknown>;
65
+ removeObjectReference(objectId: string, entityId?: string, taskId?: string): Promise<unknown>;
61
66
  findOrphanedObjects(limit?: number): Promise<unknown>;
62
67
  getObjectReferences(objectId: string): Promise<unknown>;
63
68
  validateObjectReferences(objectId: string): Promise<unknown>;
@@ -72,9 +77,10 @@ declare class AtlasHttpClient {
72
77
 
73
78
  interface Entity {
74
79
  entity_id: string;
80
+ type: string;
81
+ subtype?: string;
82
+ alias?: string;
75
83
  json: {
76
- type: "asset" | "track" | "geofeature" | string;
77
- alias?: string;
78
84
  components?: Record<string, unknown>;
79
85
  [key: string]: unknown;
80
86
  };
@@ -83,8 +89,9 @@ interface Entity {
83
89
  }
84
90
  interface Task {
85
91
  task_id: string;
92
+ status: string;
93
+ entity_id?: string;
86
94
  json: {
87
- status: string;
88
95
  components?: Record<string, unknown>;
89
96
  [key: string]: unknown;
90
97
  };
@@ -93,6 +100,9 @@ interface Task {
93
100
  }
94
101
  interface StoredObject {
95
102
  object_id: string;
103
+ path?: string;
104
+ content_type?: string;
105
+ type?: string;
96
106
  json: Record<string, unknown>;
97
107
  created_at?: string;
98
108
  updated_at?: string;
@@ -182,6 +192,7 @@ interface ObjectCreate {
182
192
  bucket?: string;
183
193
  size_bytes?: number;
184
194
  content_type?: string;
195
+ type?: string;
185
196
  usage_hints?: string[];
186
197
  referenced_by?: ObjectReference[];
187
198
  extra?: Record<string, unknown>;
@@ -191,6 +202,7 @@ interface ObjectUpdate {
191
202
  bucket?: string;
192
203
  size_bytes?: number;
193
204
  content_type?: string;
205
+ type?: string;
194
206
  usage_hints?: string[];
195
207
  referenced_by?: ObjectReference[];
196
208
  extra?: Record<string, unknown>;
package/dist/index.js CHANGED
@@ -18,6 +18,13 @@ var AtlasHttpClient = class {
18
18
  }
19
19
  return headers;
20
20
  }
21
+ multipartHeaders() {
22
+ const headers = {};
23
+ if (this.token) {
24
+ headers["Authorization"] = `Bearer ${this.token}`;
25
+ }
26
+ return headers;
27
+ }
21
28
  async request(method, path, body, params) {
22
29
  const url = new URL(`${this.baseUrl}${path}`);
23
30
  if (params) {
@@ -40,6 +47,22 @@ var AtlasHttpClient = class {
40
47
  }
41
48
  return await response.json();
42
49
  }
50
+ async multipartRequest(path, formData) {
51
+ const url = new URL(`${this.baseUrl}${path}`);
52
+ const response = await this.fetchImpl(url.toString(), {
53
+ method: "POST",
54
+ headers: this.multipartHeaders(),
55
+ body: formData
56
+ });
57
+ if (!response.ok) {
58
+ const detail = await response.text();
59
+ throw new Error(`HTTP ${response.status}: ${detail}`);
60
+ }
61
+ if (response.status === 204) {
62
+ return void 0;
63
+ }
64
+ return await response.json();
65
+ }
43
66
  // Entities ------------------------------------------------------------------
44
67
  listEntities(limit = 100, offset = 0) {
45
68
  return this.request("GET", "/entities", null, { limit, offset });
@@ -50,17 +73,36 @@ var AtlasHttpClient = class {
50
73
  getEntityByAlias(alias) {
51
74
  return this.request("GET", `/entities/alias/${alias}`);
52
75
  }
53
- createEntity(body) {
54
- return this.request("POST", "/entities", body);
55
- }
56
- updateEntity(entityId, body) {
57
- return this.request("PATCH", `/entities/${entityId}`, body);
76
+ createEntity(entityId, entityType, alias, subtype, components) {
77
+ const payload = {
78
+ entity_id: entityId,
79
+ entity_type: entityType,
80
+ alias,
81
+ subtype
82
+ };
83
+ if (components !== void 0) payload.components = components;
84
+ return this.request("POST", "/entities", payload);
85
+ }
86
+ updateEntity(entityId, components, options) {
87
+ if (components === void 0 && options?.subtype === void 0) {
88
+ throw new Error("AtlasHttpClient.updateEntity requires a components payload or subtype.");
89
+ }
90
+ const payload = {};
91
+ if (components !== void 0) payload.components = components;
92
+ if (options?.subtype !== void 0) payload.subtype = options.subtype;
93
+ return this.request("PATCH", `/entities/${entityId}`, payload);
58
94
  }
59
95
  deleteEntity(entityId) {
60
96
  return this.request("DELETE", `/entities/${entityId}`);
61
97
  }
62
- updateEntityTelemetry(entityId, body) {
63
- return this.request("PATCH", `/entities/${entityId}/telemetry`, body);
98
+ updateEntityTelemetry(entityId, options) {
99
+ const payload = {};
100
+ if (options.latitude !== void 0) payload.latitude = options.latitude;
101
+ if (options.longitude !== void 0) payload.longitude = options.longitude;
102
+ if (options.altitude_m !== void 0) payload.altitude_m = options.altitude_m;
103
+ if (options.speed_m_s !== void 0) payload.speed_m_s = options.speed_m_s;
104
+ if (options.heading_deg !== void 0) payload.heading_deg = options.heading_deg;
105
+ return this.request("PATCH", `/entities/${entityId}/telemetry`, payload);
64
106
  }
65
107
  // Tasks ---------------------------------------------------------------------
66
108
  listTasks(limit = 25, status) {
@@ -69,11 +111,28 @@ var AtlasHttpClient = class {
69
111
  getTask(taskId) {
70
112
  return this.request("GET", `/tasks/${taskId}`);
71
113
  }
72
- createTask(body) {
73
- return this.request("POST", "/tasks", body);
74
- }
75
- updateTask(taskId, body) {
76
- return this.request("PATCH", `/tasks/${taskId}`, body);
114
+ createTask(taskId, components, options) {
115
+ const payload = {
116
+ task_id: taskId,
117
+ status: options?.status || "pending"
118
+ };
119
+ if (options?.entity_id !== void 0) payload.entity_id = options.entity_id;
120
+ if (components !== void 0) payload.components = components;
121
+ if (options?.extra !== void 0) payload.extra = options.extra;
122
+ return this.request("POST", "/tasks", payload);
123
+ }
124
+ updateTask(taskId, components, options) {
125
+ if (components === void 0 && options === void 0) {
126
+ throw new Error(
127
+ "AtlasHttpClient.updateTask requires a components payload or options."
128
+ );
129
+ }
130
+ const payload = {};
131
+ if (components !== void 0) payload.components = components;
132
+ if (options?.status !== void 0) payload.status = options.status;
133
+ if (options?.entity_id !== void 0) payload.entity_id = options.entity_id;
134
+ if (options?.extra !== void 0) payload.extra = options.extra;
135
+ return this.request("PATCH", `/tasks/${taskId}`, payload);
77
136
  }
78
137
  deleteTask(taskId) {
79
138
  return this.request("DELETE", `/tasks/${taskId}`);
@@ -81,27 +140,56 @@ var AtlasHttpClient = class {
81
140
  getTasksByEntity(entityId, limit = 25, status) {
82
141
  return this.request("GET", `/entities/${entityId}/tasks`, null, { limit, status });
83
142
  }
84
- startTask(taskId, body = {}) {
85
- return this.request("POST", `/tasks/${taskId}/start`, body);
143
+ startTask(taskId) {
144
+ return this.request("POST", `/tasks/${taskId}/start`, {});
86
145
  }
87
- completeTask(taskId, body = {}) {
88
- return this.request("POST", `/tasks/${taskId}/complete`, body);
146
+ completeTask(taskId) {
147
+ return this.request("POST", `/tasks/${taskId}/complete`, {});
89
148
  }
90
- failTask(taskId, body = {}) {
91
- return this.request("POST", `/tasks/${taskId}/fail`, body);
149
+ failTask(taskId, errorMessage, errorDetails) {
150
+ const payload = {};
151
+ if (errorMessage !== void 0) payload.error_message = errorMessage;
152
+ if (errorDetails !== void 0) payload.error_details = errorDetails;
153
+ return this.request("POST", `/tasks/${taskId}/fail`, payload);
92
154
  }
93
155
  // Objects -------------------------------------------------------------------
94
- listObjects(limit = 100, offset = 0, contentType) {
95
- return this.request("GET", "/objects", null, { limit, offset, content_type: contentType });
156
+ listObjects(limit = 100, offset = 0, contentType, type) {
157
+ return this.request("GET", "/objects", null, { limit, offset, content_type: contentType, type });
96
158
  }
97
159
  getObject(objectId) {
98
160
  return this.request("GET", `/objects/${objectId}`);
99
161
  }
100
- createObject(body) {
101
- return this.request("POST", "/objects", body);
162
+ async createObject(file, objectId, usageHint, referencedBy) {
163
+ const formData = new FormData();
164
+ formData.append("object_id", objectId);
165
+ const filename = file.name ?? "upload.bin";
166
+ formData.append("file", file, filename);
167
+ if (usageHint) {
168
+ formData.append("usage_hint", usageHint);
169
+ }
170
+ const stored = await this.multipartRequest("/objects/upload", formData);
171
+ const storedObjectId = stored["object_id"];
172
+ if (referencedBy && storedObjectId !== void 0) {
173
+ for (const reference of referencedBy) {
174
+ await this.addObjectReference(storedObjectId, reference.entity_id, reference.task_id);
175
+ }
176
+ } else if (referencedBy && storedObjectId === void 0) {
177
+ throw new Error(
178
+ "AtlasHttpClient.createObject expected the upload response to include an object_id before attaching references."
179
+ );
180
+ }
181
+ return stored;
102
182
  }
103
- updateObject(objectId, body) {
104
- return this.request("PATCH", `/objects/${objectId}`, body);
183
+ updateObject(objectId, usageHints, referencedBy) {
184
+ if (usageHints === void 0 && referencedBy === void 0) {
185
+ throw new Error(
186
+ "AtlasHttpClient.updateObject requires usageHints or referencedBy to make an update."
187
+ );
188
+ }
189
+ const payload = {};
190
+ if (usageHints !== void 0) payload.usage_hints = usageHints;
191
+ if (referencedBy !== void 0) payload.referenced_by = referencedBy;
192
+ return this.request("PATCH", `/objects/${objectId}`, payload);
105
193
  }
106
194
  deleteObject(objectId) {
107
195
  return this.request("DELETE", `/objects/${objectId}`);
@@ -112,11 +200,17 @@ var AtlasHttpClient = class {
112
200
  getObjectsByTask(taskId, limit = 50) {
113
201
  return this.request("GET", `/tasks/${taskId}/objects`, null, { limit });
114
202
  }
115
- addObjectReference(objectId, body) {
116
- return this.request("POST", `/objects/${objectId}/references`, body);
117
- }
118
- removeObjectReference(objectId, body) {
119
- return this.request("DELETE", `/objects/${objectId}/references`, body);
203
+ addObjectReference(objectId, entityId, taskId) {
204
+ const payload = {};
205
+ if (entityId !== void 0) payload.entity_id = entityId;
206
+ if (taskId !== void 0) payload.task_id = taskId;
207
+ return this.request("POST", `/objects/${objectId}/references`, payload);
208
+ }
209
+ removeObjectReference(objectId, entityId, taskId) {
210
+ const payload = {};
211
+ if (entityId !== void 0) payload.entity_id = entityId;
212
+ if (taskId !== void 0) payload.task_id = taskId;
213
+ return this.request("DELETE", `/objects/${objectId}/references`, payload);
120
214
  }
121
215
  findOrphanedObjects(limit = 100) {
122
216
  return this.request("GET", "/objects/orphaned", null, { limit });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasnpm/atlas-api-helper",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "type": "module",
5
5
  "description": "HTTP client for the Atlas Command REST API.",
6
6
  "license": "MIT",