@atlasnpm/atlas-api-helper 0.2.4

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 ADDED
@@ -0,0 +1,150 @@
1
+ # Atlas Command HTTP Client (TypeScript)
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
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @atlasnpm/atlas-api-helper
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { AtlasHttpClient } from "@atlasnpm/atlas-api-helper";
15
+
16
+ const client = new AtlasHttpClient({
17
+ baseUrl: "http://localhost:8000",
18
+ token: "my-api-token",
19
+ });
20
+
21
+ // Basic entity operations
22
+ const entities = await client.listEntities();
23
+ console.log("Entities", entities);
24
+
25
+ await client.createTask({
26
+ task_id: "survey-1",
27
+ status: "pending",
28
+ components: { parameters: { latitude: 40.7, longitude: -74.0 } },
29
+ });
30
+
31
+ // New API methods (version 0.2.1)
32
+ const entity = await client.getEntityByAlias("drone-1");
33
+ await client.updateEntityTelemetry("drone-1", {
34
+ latitude: 40.7128,
35
+ longitude: -74.0060,
36
+ altitude_m: 100,
37
+ speed_m_s: 15,
38
+ heading_deg: 90,
39
+ });
40
+
41
+ // Task lifecycle management
42
+ await client.startTask("task-1", { started_by: "operator-1" });
43
+ await client.completeTask("task-1", { result: { data: "success" } });
44
+
45
+ // Query capabilities
46
+ const changes = await client.getChangedSince("2023-01-01T00:00:00Z", 10);
47
+ const fullData = await client.getFullDataset({
48
+ entityLimit: 50,
49
+ taskLimit: 25,
50
+ objectLimit: 100,
51
+ });
52
+ ```
53
+
54
+ ## API Surface
55
+
56
+ The client now exposes comprehensive helpers for every HTTP endpoint, matching the Python client:
57
+
58
+ ### Entities
59
+ - `listEntities(limit?, offset?)` - List all entities with pagination
60
+ - `getEntity(entityId)` - Get a specific entity by ID
61
+ - `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
64
+ - `deleteEntity(entityId)` - Delete an entity
65
+ - `updateEntityTelemetry(entityId, telemetry)` - Update entity telemetry with specific parameters (NEW in 0.2.1)
66
+
67
+ ### Tasks
68
+ - `listTasks(limit?, status?)` - List tasks with optional status filter
69
+ - `getTask(taskId)` - Get a specific task
70
+ - `createTask(body)` - Create a new task
71
+ - `updateTask(taskId, body)` - Update an existing task
72
+ - `deleteTask(taskId)` - Delete a task
73
+ - `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)
77
+
78
+ ### Objects
79
+ - `listObjects(limit?, offset?, contentType?)` - List objects with filters
80
+ - `getObject(objectId)` - Get a specific object
81
+ - `createObject(body)` - Create a new object
82
+ - `updateObject(objectId, body)` - Update an existing object
83
+ - `deleteObject(objectId)` - Delete an object
84
+ - `getObjectsByEntity(entityId, limit?)` - Get objects by entity
85
+ - `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
88
+ - `findOrphanedObjects(limit?)` - Find orphaned objects
89
+ - `getObjectReferences(objectId)` - Get object references
90
+ - `validateObjectReferences(objectId)` - Validate object references
91
+ - `cleanupObjectReferences(objectId)` - Cleanup object references
92
+
93
+ ### Queries
94
+ - `getChangedSince(since, limitPerType?)` - Get changes since timestamp (NEW in 0.2.1)
95
+ - `getFullDataset(options?)` - Get full dataset with limits (NEW in 0.2.1)
96
+
97
+ ## Type System
98
+
99
+ The package now includes comprehensive TypeScript types for all entities and operations:
100
+
101
+ ```ts
102
+ import {
103
+ Entity,
104
+ Task,
105
+ Telemetry,
106
+ TaskStart,
107
+ TaskComplete,
108
+ TaskFail,
109
+ // ... and many more
110
+ } from "@atlasnpm/atlas-api-helper";
111
+ ```
112
+
113
+ ## Custom Fetch / Testing
114
+
115
+ Pass a custom `fetchImpl` when constructing the client to inject your own transport (e.g., `node-fetch`, `cross-fetch`, or a mocked implementation for unit tests):
116
+
117
+ ```ts
118
+ const client = new AtlasHttpClient({
119
+ baseUrl: "https://atlas.example.com",
120
+ fetchImpl: myCustomFetch,
121
+ });
122
+ ```
123
+
124
+ See `tests/httpClient.test.ts` for examples using mocked fetch functions.
125
+
126
+ ## Building & Testing
127
+
128
+ ```bash
129
+ npm install
130
+ npm run build
131
+ npm run test
132
+ ```
133
+
134
+ The build produces both ESM and CJS bundles plus `.d.ts` type definitions via `tsup`.
135
+
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
+ ## Publishing
149
+
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.
package/dist/index.cjs ADDED
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AtlasHttpClient: () => AtlasHttpClient
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/httpClient.ts
28
+ var AtlasHttpClient = class {
29
+ baseUrl;
30
+ token;
31
+ fetchImpl;
32
+ constructor(options) {
33
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
34
+ this.token = options.token;
35
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
36
+ if (!this.fetchImpl) {
37
+ throw new Error("fetch is not available; provide fetchImpl");
38
+ }
39
+ }
40
+ headers() {
41
+ const headers = { "Content-Type": "application/json" };
42
+ if (this.token) {
43
+ headers["Authorization"] = `Bearer ${this.token}`;
44
+ }
45
+ return headers;
46
+ }
47
+ async request(method, path, body, params) {
48
+ const url = new URL(`${this.baseUrl}${path}`);
49
+ if (params) {
50
+ for (const [key, value] of Object.entries(params)) {
51
+ if (value === void 0 || value === null) continue;
52
+ url.searchParams.set(key, String(value));
53
+ }
54
+ }
55
+ const response = await this.fetchImpl(url.toString(), {
56
+ method,
57
+ headers: this.headers(),
58
+ body: body ? JSON.stringify(body) : void 0
59
+ });
60
+ if (!response.ok) {
61
+ const detail = await response.text();
62
+ throw new Error(`HTTP ${response.status}: ${detail}`);
63
+ }
64
+ if (response.status === 204) {
65
+ return void 0;
66
+ }
67
+ return await response.json();
68
+ }
69
+ // Entities ------------------------------------------------------------------
70
+ listEntities(limit = 100, offset = 0) {
71
+ return this.request("GET", "/entities", null, { limit, offset });
72
+ }
73
+ getEntity(entityId) {
74
+ return this.request("GET", `/entities/${entityId}`);
75
+ }
76
+ getEntityByAlias(alias) {
77
+ return this.request("GET", `/entities/alias/${alias}`);
78
+ }
79
+ createEntity(body) {
80
+ return this.request("POST", "/entities", body);
81
+ }
82
+ updateEntity(entityId, body) {
83
+ return this.request("PATCH", `/entities/${entityId}`, body);
84
+ }
85
+ deleteEntity(entityId) {
86
+ return this.request("DELETE", `/entities/${entityId}`);
87
+ }
88
+ updateEntityTelemetry(entityId, body) {
89
+ return this.request("PATCH", `/entities/${entityId}/telemetry`, body);
90
+ }
91
+ // Tasks ---------------------------------------------------------------------
92
+ listTasks(limit = 25, status) {
93
+ return this.request("GET", "/tasks", null, { limit, status });
94
+ }
95
+ getTask(taskId) {
96
+ return this.request("GET", `/tasks/${taskId}`);
97
+ }
98
+ createTask(body) {
99
+ return this.request("POST", "/tasks", body);
100
+ }
101
+ updateTask(taskId, body) {
102
+ return this.request("PATCH", `/tasks/${taskId}`, body);
103
+ }
104
+ deleteTask(taskId) {
105
+ return this.request("DELETE", `/tasks/${taskId}`);
106
+ }
107
+ getTasksByEntity(entityId, limit = 25, status) {
108
+ return this.request("GET", `/entities/${entityId}/tasks`, null, { limit, status });
109
+ }
110
+ startTask(taskId, body = {}) {
111
+ return this.request("POST", `/tasks/${taskId}/start`, body);
112
+ }
113
+ completeTask(taskId, body = {}) {
114
+ return this.request("POST", `/tasks/${taskId}/complete`, body);
115
+ }
116
+ failTask(taskId, body = {}) {
117
+ return this.request("POST", `/tasks/${taskId}/fail`, body);
118
+ }
119
+ // Objects -------------------------------------------------------------------
120
+ listObjects(limit = 100, offset = 0, contentType) {
121
+ return this.request("GET", "/objects", null, { limit, offset, content_type: contentType });
122
+ }
123
+ getObject(objectId) {
124
+ return this.request("GET", `/objects/${objectId}`);
125
+ }
126
+ createObject(body) {
127
+ return this.request("POST", "/objects", body);
128
+ }
129
+ updateObject(objectId, body) {
130
+ return this.request("PATCH", `/objects/${objectId}`, body);
131
+ }
132
+ deleteObject(objectId) {
133
+ return this.request("DELETE", `/objects/${objectId}`);
134
+ }
135
+ getObjectsByEntity(entityId, limit = 50) {
136
+ return this.request("GET", `/entities/${entityId}/objects`, null, { limit });
137
+ }
138
+ getObjectsByTask(taskId, limit = 50) {
139
+ return this.request("GET", `/tasks/${taskId}/objects`, null, { limit });
140
+ }
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);
146
+ }
147
+ findOrphanedObjects(limit = 100) {
148
+ return this.request("GET", "/objects/orphaned", null, { limit });
149
+ }
150
+ getObjectReferences(objectId) {
151
+ return this.request("GET", `/objects/${objectId}/references/info`);
152
+ }
153
+ validateObjectReferences(objectId) {
154
+ return this.request("GET", `/objects/${objectId}/references/validate`);
155
+ }
156
+ cleanupObjectReferences(objectId) {
157
+ return this.request("POST", `/objects/${objectId}/references/cleanup`, {});
158
+ }
159
+ // Queries -------------------------------------------------------------------
160
+ getChangedSince(since, limitPerType) {
161
+ return this.request("GET", "/queries/changed-since", null, {
162
+ since,
163
+ limit_per_type: limitPerType
164
+ });
165
+ }
166
+ getFullDataset(options) {
167
+ return this.request("GET", "/queries/full", null, {
168
+ entity_limit: options?.entityLimit,
169
+ task_limit: options?.taskLimit,
170
+ object_limit: options?.objectLimit
171
+ });
172
+ }
173
+ };
174
+ // Annotate the CommonJS export names for ESM import in node:
175
+ 0 && (module.exports = {
176
+ AtlasHttpClient
177
+ });
@@ -0,0 +1,208 @@
1
+ interface FetchImplementation {
2
+ (input: RequestInfo, init?: RequestInit): Promise<Response>;
3
+ }
4
+ interface ClientOptions {
5
+ baseUrl: string;
6
+ token?: string;
7
+ fetchImpl?: FetchImplementation;
8
+ }
9
+ type JsonRecord = Record<string, unknown>;
10
+ declare class AtlasHttpClient {
11
+ private readonly baseUrl;
12
+ private readonly token?;
13
+ private readonly fetchImpl;
14
+ constructor(options: ClientOptions);
15
+ private headers;
16
+ private request;
17
+ listEntities(limit?: number, offset?: number): Promise<unknown>;
18
+ getEntity(entityId: string): Promise<unknown>;
19
+ getEntityByAlias(alias: string): Promise<unknown>;
20
+ createEntity(body: JsonRecord): Promise<unknown>;
21
+ updateEntity(entityId: string, body: JsonRecord): Promise<unknown>;
22
+ deleteEntity(entityId: string): Promise<unknown>;
23
+ updateEntityTelemetry(entityId: string, body: {
24
+ latitude?: number;
25
+ longitude?: number;
26
+ altitude_m?: number;
27
+ speed_m_s?: number;
28
+ heading_deg?: number;
29
+ }): Promise<unknown>;
30
+ listTasks(limit?: number, status?: string): Promise<unknown>;
31
+ 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;
41
+ }): Promise<unknown>;
42
+ failTask(taskId: string, body?: {
43
+ error_message?: string;
44
+ error_details?: JsonRecord;
45
+ }): Promise<unknown>;
46
+ listObjects(limit?: number, offset?: number, contentType?: string): Promise<unknown>;
47
+ 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: {
54
+ entity_id?: string;
55
+ task_id?: string;
56
+ }): Promise<unknown>;
57
+ removeObjectReference(objectId: string, body: {
58
+ entity_id?: string;
59
+ task_id?: string;
60
+ }): Promise<unknown>;
61
+ findOrphanedObjects(limit?: number): Promise<unknown>;
62
+ getObjectReferences(objectId: string): Promise<unknown>;
63
+ validateObjectReferences(objectId: string): Promise<unknown>;
64
+ cleanupObjectReferences(objectId: string): Promise<unknown>;
65
+ getChangedSince(since: string, limitPerType?: number): Promise<unknown>;
66
+ getFullDataset(options?: {
67
+ entityLimit?: number;
68
+ taskLimit?: number;
69
+ objectLimit?: number;
70
+ }): Promise<unknown>;
71
+ }
72
+
73
+ interface Entity {
74
+ entity_id: string;
75
+ json: {
76
+ type: "asset" | "track" | "geofeature" | string;
77
+ alias?: string;
78
+ components?: Record<string, unknown>;
79
+ [key: string]: unknown;
80
+ };
81
+ created_at?: string;
82
+ updated_at?: string;
83
+ }
84
+ interface Task {
85
+ task_id: string;
86
+ json: {
87
+ status: string;
88
+ components?: Record<string, unknown>;
89
+ [key: string]: unknown;
90
+ };
91
+ created_at?: string;
92
+ updated_at?: string;
93
+ }
94
+ interface StoredObject {
95
+ object_id: string;
96
+ json: Record<string, unknown>;
97
+ created_at?: string;
98
+ updated_at?: string;
99
+ }
100
+ type Asset = Entity;
101
+ type Track = Entity;
102
+ type GeoFeature = Entity;
103
+ type Command = Task;
104
+ interface Model {
105
+ id: string | number;
106
+ name?: string;
107
+ asset_type?: string;
108
+ capabilities?: Record<string, unknown>;
109
+ heartbeat_interval?: number;
110
+ location_update_frequency?: number;
111
+ settings_schema?: Record<string, unknown>;
112
+ default_settings?: Record<string, unknown>;
113
+ created_at?: string;
114
+ updated_at?: string;
115
+ [key: string]: unknown;
116
+ }
117
+ interface CommandDefinition {
118
+ id: number;
119
+ name?: string;
120
+ parameters_schema?: Record<string, unknown>;
121
+ [key: string]: unknown;
122
+ }
123
+ interface EventType {
124
+ id: number;
125
+ name?: string;
126
+ [key: string]: unknown;
127
+ }
128
+ interface Event {
129
+ id: number;
130
+ asset_id?: string;
131
+ event_type_id?: number;
132
+ timestamp?: string;
133
+ payload?: Record<string, unknown>;
134
+ entity?: string;
135
+ [key: string]: unknown;
136
+ }
137
+ interface Sensor {
138
+ id: number;
139
+ asset_id?: string;
140
+ name?: string;
141
+ [key: string]: unknown;
142
+ }
143
+ interface TrackTelemetry {
144
+ track_id: string;
145
+ timestamp: string;
146
+ latitude?: number | string;
147
+ longitude?: number | string;
148
+ altitude?: number;
149
+ sensor_id?: number;
150
+ [key: string]: unknown;
151
+ }
152
+ interface Telemetry {
153
+ latitude?: number;
154
+ longitude?: number;
155
+ altitude_m?: number;
156
+ speed_m_s?: number;
157
+ heading_deg?: number;
158
+ [key: string]: unknown;
159
+ }
160
+ interface TaskStatusUpdate {
161
+ status?: string;
162
+ components?: Record<string, unknown>;
163
+ extra?: Record<string, unknown>;
164
+ }
165
+ interface TaskStart {
166
+ started_by?: string;
167
+ }
168
+ interface TaskComplete {
169
+ result?: Record<string, unknown>;
170
+ }
171
+ interface TaskFail {
172
+ error_message?: string;
173
+ error_details?: Record<string, unknown>;
174
+ }
175
+ interface ObjectReference {
176
+ entity_id?: string;
177
+ task_id?: string;
178
+ }
179
+ interface ObjectCreate {
180
+ object_id: string;
181
+ path?: string;
182
+ bucket?: string;
183
+ size_bytes?: number;
184
+ content_type?: string;
185
+ usage_hints?: string[];
186
+ referenced_by?: ObjectReference[];
187
+ extra?: Record<string, unknown>;
188
+ }
189
+ interface ObjectUpdate {
190
+ path?: string;
191
+ bucket?: string;
192
+ size_bytes?: number;
193
+ content_type?: string;
194
+ usage_hints?: string[];
195
+ referenced_by?: ObjectReference[];
196
+ extra?: Record<string, unknown>;
197
+ }
198
+ interface ChangedSinceOptions {
199
+ since: string;
200
+ limit_per_type?: number;
201
+ }
202
+ interface FullDatasetOptions {
203
+ entity_limit?: number;
204
+ task_limit?: number;
205
+ object_limit?: number;
206
+ }
207
+
208
+ export { type Asset, AtlasHttpClient, type ChangedSinceOptions, type ClientOptions, type Command, type CommandDefinition, type Entity, type Event, type EventType, type FetchImplementation, type FullDatasetOptions, type GeoFeature, type JsonRecord, type Model, type ObjectCreate, type ObjectReference, type ObjectUpdate, type Sensor, type StoredObject, type Task, type TaskComplete, type TaskFail, type TaskStart, type TaskStatusUpdate, type Telemetry, type Track, type TrackTelemetry };
@@ -0,0 +1,208 @@
1
+ interface FetchImplementation {
2
+ (input: RequestInfo, init?: RequestInit): Promise<Response>;
3
+ }
4
+ interface ClientOptions {
5
+ baseUrl: string;
6
+ token?: string;
7
+ fetchImpl?: FetchImplementation;
8
+ }
9
+ type JsonRecord = Record<string, unknown>;
10
+ declare class AtlasHttpClient {
11
+ private readonly baseUrl;
12
+ private readonly token?;
13
+ private readonly fetchImpl;
14
+ constructor(options: ClientOptions);
15
+ private headers;
16
+ private request;
17
+ listEntities(limit?: number, offset?: number): Promise<unknown>;
18
+ getEntity(entityId: string): Promise<unknown>;
19
+ getEntityByAlias(alias: string): Promise<unknown>;
20
+ createEntity(body: JsonRecord): Promise<unknown>;
21
+ updateEntity(entityId: string, body: JsonRecord): Promise<unknown>;
22
+ deleteEntity(entityId: string): Promise<unknown>;
23
+ updateEntityTelemetry(entityId: string, body: {
24
+ latitude?: number;
25
+ longitude?: number;
26
+ altitude_m?: number;
27
+ speed_m_s?: number;
28
+ heading_deg?: number;
29
+ }): Promise<unknown>;
30
+ listTasks(limit?: number, status?: string): Promise<unknown>;
31
+ 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;
41
+ }): Promise<unknown>;
42
+ failTask(taskId: string, body?: {
43
+ error_message?: string;
44
+ error_details?: JsonRecord;
45
+ }): Promise<unknown>;
46
+ listObjects(limit?: number, offset?: number, contentType?: string): Promise<unknown>;
47
+ 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: {
54
+ entity_id?: string;
55
+ task_id?: string;
56
+ }): Promise<unknown>;
57
+ removeObjectReference(objectId: string, body: {
58
+ entity_id?: string;
59
+ task_id?: string;
60
+ }): Promise<unknown>;
61
+ findOrphanedObjects(limit?: number): Promise<unknown>;
62
+ getObjectReferences(objectId: string): Promise<unknown>;
63
+ validateObjectReferences(objectId: string): Promise<unknown>;
64
+ cleanupObjectReferences(objectId: string): Promise<unknown>;
65
+ getChangedSince(since: string, limitPerType?: number): Promise<unknown>;
66
+ getFullDataset(options?: {
67
+ entityLimit?: number;
68
+ taskLimit?: number;
69
+ objectLimit?: number;
70
+ }): Promise<unknown>;
71
+ }
72
+
73
+ interface Entity {
74
+ entity_id: string;
75
+ json: {
76
+ type: "asset" | "track" | "geofeature" | string;
77
+ alias?: string;
78
+ components?: Record<string, unknown>;
79
+ [key: string]: unknown;
80
+ };
81
+ created_at?: string;
82
+ updated_at?: string;
83
+ }
84
+ interface Task {
85
+ task_id: string;
86
+ json: {
87
+ status: string;
88
+ components?: Record<string, unknown>;
89
+ [key: string]: unknown;
90
+ };
91
+ created_at?: string;
92
+ updated_at?: string;
93
+ }
94
+ interface StoredObject {
95
+ object_id: string;
96
+ json: Record<string, unknown>;
97
+ created_at?: string;
98
+ updated_at?: string;
99
+ }
100
+ type Asset = Entity;
101
+ type Track = Entity;
102
+ type GeoFeature = Entity;
103
+ type Command = Task;
104
+ interface Model {
105
+ id: string | number;
106
+ name?: string;
107
+ asset_type?: string;
108
+ capabilities?: Record<string, unknown>;
109
+ heartbeat_interval?: number;
110
+ location_update_frequency?: number;
111
+ settings_schema?: Record<string, unknown>;
112
+ default_settings?: Record<string, unknown>;
113
+ created_at?: string;
114
+ updated_at?: string;
115
+ [key: string]: unknown;
116
+ }
117
+ interface CommandDefinition {
118
+ id: number;
119
+ name?: string;
120
+ parameters_schema?: Record<string, unknown>;
121
+ [key: string]: unknown;
122
+ }
123
+ interface EventType {
124
+ id: number;
125
+ name?: string;
126
+ [key: string]: unknown;
127
+ }
128
+ interface Event {
129
+ id: number;
130
+ asset_id?: string;
131
+ event_type_id?: number;
132
+ timestamp?: string;
133
+ payload?: Record<string, unknown>;
134
+ entity?: string;
135
+ [key: string]: unknown;
136
+ }
137
+ interface Sensor {
138
+ id: number;
139
+ asset_id?: string;
140
+ name?: string;
141
+ [key: string]: unknown;
142
+ }
143
+ interface TrackTelemetry {
144
+ track_id: string;
145
+ timestamp: string;
146
+ latitude?: number | string;
147
+ longitude?: number | string;
148
+ altitude?: number;
149
+ sensor_id?: number;
150
+ [key: string]: unknown;
151
+ }
152
+ interface Telemetry {
153
+ latitude?: number;
154
+ longitude?: number;
155
+ altitude_m?: number;
156
+ speed_m_s?: number;
157
+ heading_deg?: number;
158
+ [key: string]: unknown;
159
+ }
160
+ interface TaskStatusUpdate {
161
+ status?: string;
162
+ components?: Record<string, unknown>;
163
+ extra?: Record<string, unknown>;
164
+ }
165
+ interface TaskStart {
166
+ started_by?: string;
167
+ }
168
+ interface TaskComplete {
169
+ result?: Record<string, unknown>;
170
+ }
171
+ interface TaskFail {
172
+ error_message?: string;
173
+ error_details?: Record<string, unknown>;
174
+ }
175
+ interface ObjectReference {
176
+ entity_id?: string;
177
+ task_id?: string;
178
+ }
179
+ interface ObjectCreate {
180
+ object_id: string;
181
+ path?: string;
182
+ bucket?: string;
183
+ size_bytes?: number;
184
+ content_type?: string;
185
+ usage_hints?: string[];
186
+ referenced_by?: ObjectReference[];
187
+ extra?: Record<string, unknown>;
188
+ }
189
+ interface ObjectUpdate {
190
+ path?: string;
191
+ bucket?: string;
192
+ size_bytes?: number;
193
+ content_type?: string;
194
+ usage_hints?: string[];
195
+ referenced_by?: ObjectReference[];
196
+ extra?: Record<string, unknown>;
197
+ }
198
+ interface ChangedSinceOptions {
199
+ since: string;
200
+ limit_per_type?: number;
201
+ }
202
+ interface FullDatasetOptions {
203
+ entity_limit?: number;
204
+ task_limit?: number;
205
+ object_limit?: number;
206
+ }
207
+
208
+ export { type Asset, AtlasHttpClient, type ChangedSinceOptions, type ClientOptions, type Command, type CommandDefinition, type Entity, type Event, type EventType, type FetchImplementation, type FullDatasetOptions, type GeoFeature, type JsonRecord, type Model, type ObjectCreate, type ObjectReference, type ObjectUpdate, type Sensor, type StoredObject, type Task, type TaskComplete, type TaskFail, type TaskStart, type TaskStatusUpdate, type Telemetry, type Track, type TrackTelemetry };
package/dist/index.js ADDED
@@ -0,0 +1,150 @@
1
+ // src/httpClient.ts
2
+ var AtlasHttpClient = class {
3
+ baseUrl;
4
+ token;
5
+ fetchImpl;
6
+ constructor(options) {
7
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
8
+ this.token = options.token;
9
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
10
+ if (!this.fetchImpl) {
11
+ throw new Error("fetch is not available; provide fetchImpl");
12
+ }
13
+ }
14
+ headers() {
15
+ const headers = { "Content-Type": "application/json" };
16
+ if (this.token) {
17
+ headers["Authorization"] = `Bearer ${this.token}`;
18
+ }
19
+ return headers;
20
+ }
21
+ async request(method, path, body, params) {
22
+ const url = new URL(`${this.baseUrl}${path}`);
23
+ if (params) {
24
+ for (const [key, value] of Object.entries(params)) {
25
+ if (value === void 0 || value === null) continue;
26
+ url.searchParams.set(key, String(value));
27
+ }
28
+ }
29
+ const response = await this.fetchImpl(url.toString(), {
30
+ method,
31
+ headers: this.headers(),
32
+ body: body ? JSON.stringify(body) : void 0
33
+ });
34
+ if (!response.ok) {
35
+ const detail = await response.text();
36
+ throw new Error(`HTTP ${response.status}: ${detail}`);
37
+ }
38
+ if (response.status === 204) {
39
+ return void 0;
40
+ }
41
+ return await response.json();
42
+ }
43
+ // Entities ------------------------------------------------------------------
44
+ listEntities(limit = 100, offset = 0) {
45
+ return this.request("GET", "/entities", null, { limit, offset });
46
+ }
47
+ getEntity(entityId) {
48
+ return this.request("GET", `/entities/${entityId}`);
49
+ }
50
+ getEntityByAlias(alias) {
51
+ return this.request("GET", `/entities/alias/${alias}`);
52
+ }
53
+ createEntity(body) {
54
+ return this.request("POST", "/entities", body);
55
+ }
56
+ updateEntity(entityId, body) {
57
+ return this.request("PATCH", `/entities/${entityId}`, body);
58
+ }
59
+ deleteEntity(entityId) {
60
+ return this.request("DELETE", `/entities/${entityId}`);
61
+ }
62
+ updateEntityTelemetry(entityId, body) {
63
+ return this.request("PATCH", `/entities/${entityId}/telemetry`, body);
64
+ }
65
+ // Tasks ---------------------------------------------------------------------
66
+ listTasks(limit = 25, status) {
67
+ return this.request("GET", "/tasks", null, { limit, status });
68
+ }
69
+ getTask(taskId) {
70
+ return this.request("GET", `/tasks/${taskId}`);
71
+ }
72
+ createTask(body) {
73
+ return this.request("POST", "/tasks", body);
74
+ }
75
+ updateTask(taskId, body) {
76
+ return this.request("PATCH", `/tasks/${taskId}`, body);
77
+ }
78
+ deleteTask(taskId) {
79
+ return this.request("DELETE", `/tasks/${taskId}`);
80
+ }
81
+ getTasksByEntity(entityId, limit = 25, status) {
82
+ return this.request("GET", `/entities/${entityId}/tasks`, null, { limit, status });
83
+ }
84
+ startTask(taskId, body = {}) {
85
+ return this.request("POST", `/tasks/${taskId}/start`, body);
86
+ }
87
+ completeTask(taskId, body = {}) {
88
+ return this.request("POST", `/tasks/${taskId}/complete`, body);
89
+ }
90
+ failTask(taskId, body = {}) {
91
+ return this.request("POST", `/tasks/${taskId}/fail`, body);
92
+ }
93
+ // Objects -------------------------------------------------------------------
94
+ listObjects(limit = 100, offset = 0, contentType) {
95
+ return this.request("GET", "/objects", null, { limit, offset, content_type: contentType });
96
+ }
97
+ getObject(objectId) {
98
+ return this.request("GET", `/objects/${objectId}`);
99
+ }
100
+ createObject(body) {
101
+ return this.request("POST", "/objects", body);
102
+ }
103
+ updateObject(objectId, body) {
104
+ return this.request("PATCH", `/objects/${objectId}`, body);
105
+ }
106
+ deleteObject(objectId) {
107
+ return this.request("DELETE", `/objects/${objectId}`);
108
+ }
109
+ getObjectsByEntity(entityId, limit = 50) {
110
+ return this.request("GET", `/entities/${entityId}/objects`, null, { limit });
111
+ }
112
+ getObjectsByTask(taskId, limit = 50) {
113
+ return this.request("GET", `/tasks/${taskId}/objects`, null, { limit });
114
+ }
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);
120
+ }
121
+ findOrphanedObjects(limit = 100) {
122
+ return this.request("GET", "/objects/orphaned", null, { limit });
123
+ }
124
+ getObjectReferences(objectId) {
125
+ return this.request("GET", `/objects/${objectId}/references/info`);
126
+ }
127
+ validateObjectReferences(objectId) {
128
+ return this.request("GET", `/objects/${objectId}/references/validate`);
129
+ }
130
+ cleanupObjectReferences(objectId) {
131
+ return this.request("POST", `/objects/${objectId}/references/cleanup`, {});
132
+ }
133
+ // Queries -------------------------------------------------------------------
134
+ getChangedSince(since, limitPerType) {
135
+ return this.request("GET", "/queries/changed-since", null, {
136
+ since,
137
+ limit_per_type: limitPerType
138
+ });
139
+ }
140
+ getFullDataset(options) {
141
+ return this.request("GET", "/queries/full", null, {
142
+ entity_limit: options?.entityLimit,
143
+ task_limit: options?.taskLimit,
144
+ object_limit: options?.objectLimit
145
+ });
146
+ }
147
+ };
148
+ export {
149
+ AtlasHttpClient
150
+ };
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/index";
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@atlasnpm/atlas-api-helper",
3
+ "version": "0.2.4",
4
+ "type": "module",
5
+ "description": "HTTP client for the Atlas Command REST API.",
6
+ "license": "MIT",
7
+ "main": "dist/index.cjs",
8
+ "module": "dist/index.mjs",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "index.d.ts"
20
+ ],
21
+ "scripts": {
22
+ "build": "npx tsup",
23
+ "test": "vitest run",
24
+ "prepare": "node ./scripts/prepare.mjs"
25
+ },
26
+ "dependencies": {},
27
+ "devDependencies": {
28
+ "@types/node": "^24.10.1",
29
+ "tsup": "^8.5.1",
30
+ "typescript": "^5.4.5",
31
+ "vitest": "^1.5.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ }
36
+ }