@dataworks-technology/data 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -10
- package/dist/index.cjs +137 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -5
- package/dist/index.d.ts +116 -5
- package/dist/index.js +136 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ You need a Dataworks developer account. Contact your Dataworks administrator to
|
|
|
28
28
|
| `errorUrl` | API Gateway endpoint for error reporting |
|
|
29
29
|
| `realtimeUrl` | AppSync Events API endpoint for subscriptions |
|
|
30
30
|
| Username + password | Your developer login credentials |
|
|
31
|
+
| `apiKey` (optional) | AppSync Events API key for subscription-only access |
|
|
31
32
|
|
|
32
33
|
## Installation
|
|
33
34
|
|
|
@@ -58,6 +59,7 @@ const dataworks = new DataClient({
|
|
|
58
59
|
ingestUrl: "https://your-ingest-endpoint.dataworks.live",
|
|
59
60
|
errorUrl: "https://your-error-endpoint.dataworks.live",
|
|
60
61
|
realtimeUrl: "https://your-realtime-endpoint.dataworks.live",
|
|
62
|
+
apiKey: "your-appsync-events-api-key", // optional
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
// Authenticate
|
|
@@ -94,9 +96,33 @@ const dataworks = new DataClient({
|
|
|
94
96
|
});
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
#### API Key Authentication (Subscription-Only)
|
|
100
|
+
|
|
101
|
+
For read-only access to real-time subscriptions without Cognito credentials:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { DataClient, SubscriptionEvent } from "@dataworks-technology/data";
|
|
105
|
+
|
|
106
|
+
const dataworks = new DataClient({
|
|
107
|
+
cognitoEndpoint: "https://cognito-idp.eu-west-1.amazonaws.com/",
|
|
108
|
+
clientId: "unused",
|
|
109
|
+
ingestUrl: "https://unused.dataworks.live",
|
|
110
|
+
errorUrl: "https://unused.dataworks.live",
|
|
111
|
+
realtimeUrl: "https://realtime.dataworks.live",
|
|
112
|
+
apiKey: "da2-xxxxxxxxxx", // AppSync Events API key
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// No login required — subscribe directly
|
|
116
|
+
const sub = dataworks.subscribe("dataworks/*", (event: SubscriptionEvent) => {
|
|
117
|
+
console.log(event.athleteId, event.metrics);
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> **Note:** API key authentication only supports subscriptions. Ingest and error reporting require Cognito credentials. If both `apiKey` and Cognito credentials are provided, Cognito takes precedence.
|
|
122
|
+
|
|
97
123
|
### `dataworks.login(username, password)`
|
|
98
124
|
|
|
99
|
-
Authenticate with Cognito. Must be called before any other operation.
|
|
125
|
+
Authenticate with Cognito. Must be called before any other operation (unless using API key for subscriptions).
|
|
100
126
|
|
|
101
127
|
```typescript
|
|
102
128
|
const result = await dataworks.login("username", "password");
|
|
@@ -105,7 +131,7 @@ const result = await dataworks.login("username", "password");
|
|
|
105
131
|
|
|
106
132
|
### `dataworks.ingest(metrics, eventId, datasetDatasourceId)`
|
|
107
133
|
|
|
108
|
-
Send metric data points to the Data Engine. Invalid metrics are
|
|
134
|
+
Send metric data points to the Data Engine. Invalid metrics are dropped with warnings.
|
|
109
135
|
|
|
110
136
|
```typescript
|
|
111
137
|
await dataworks.ingest(
|
|
@@ -118,6 +144,21 @@ await dataworks.ingest(
|
|
|
118
144
|
);
|
|
119
145
|
```
|
|
120
146
|
|
|
147
|
+
### `dataworks.ingestWithResult(metrics, eventId, datasetDatasourceId, options?)`
|
|
148
|
+
|
|
149
|
+
Ingest with structured validation diagnostics.
|
|
150
|
+
|
|
151
|
+
- Default mode (`best-effort`): invalid metrics are dropped and valid metrics continue.
|
|
152
|
+
- Strict mode (`strict`): throws `MetricValidationError` if any metric is invalid.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const result = await dataworks.ingestWithResult(metrics, "event-123", "ds-456", {
|
|
156
|
+
validationMode: "best-effort",
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
console.log(result.acceptedCount, result.droppedCount, result.requestSent);
|
|
160
|
+
```
|
|
161
|
+
|
|
121
162
|
### `dataworks.subscribe(channel, onEvent, onError?)`
|
|
122
163
|
|
|
123
164
|
Subscribe to real-time data events via WebSocket.
|
|
@@ -125,13 +166,16 @@ Subscribe to real-time data events via WebSocket.
|
|
|
125
166
|
Tip: start with `dataworks/1/1/*` to inspect all metrics for a dataset-datasource/event pair, then narrow to a specific metric channel such as `dataworks/1/1/heartrate`.
|
|
126
167
|
|
|
127
168
|
```typescript
|
|
169
|
+
import { SubscriptionEvent, SubscriptionError } from "@dataworks-technology/data";
|
|
170
|
+
|
|
128
171
|
const subscription = dataworks.subscribe(
|
|
129
172
|
"dataworks/1/1/heartrate",
|
|
130
|
-
(event) => {
|
|
131
|
-
console.log("
|
|
173
|
+
(event: SubscriptionEvent) => {
|
|
174
|
+
console.log("Athlete:", event.athleteId);
|
|
175
|
+
console.log("Metrics:", event.metrics);
|
|
132
176
|
},
|
|
133
|
-
(error) => {
|
|
134
|
-
console.error("
|
|
177
|
+
(error: SubscriptionError) => {
|
|
178
|
+
console.error("Error:", error.message, "Code:", error.code);
|
|
135
179
|
},
|
|
136
180
|
);
|
|
137
181
|
|
|
@@ -139,10 +183,61 @@ const subscription = dataworks.subscribe(
|
|
|
139
183
|
subscription.close();
|
|
140
184
|
```
|
|
141
185
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
186
|
+
#### Event Type: `SubscriptionEvent`
|
|
187
|
+
|
|
188
|
+
The standard Data Engine event shape:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
interface SubscriptionEvent {
|
|
192
|
+
name: string; // e.g. "heartrateingested"
|
|
193
|
+
timestamp: number; // Unix timestamp (milliseconds)
|
|
194
|
+
timestampSec: number; // Unix timestamp (seconds)
|
|
195
|
+
eventId: string;
|
|
196
|
+
datasetDatasourceId: string;
|
|
197
|
+
athleteId: string;
|
|
198
|
+
metrics: SubscriptionMetric[];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
interface SubscriptionMetric {
|
|
202
|
+
metric: string; // e.g. "current", "heartrate"
|
|
203
|
+
value: number | string;
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Custom Event Types
|
|
208
|
+
|
|
209
|
+
If your channel publishes a different format, use the generic type parameter:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface MyCustomEvent {
|
|
213
|
+
athleteId: string;
|
|
214
|
+
customField: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
dataworks.subscribe<MyCustomEvent>("custom/*", (event) => {
|
|
218
|
+
console.log(event.customField); // TypeScript knows this exists
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Error Type: `SubscriptionError`
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
interface SubscriptionError {
|
|
226
|
+
message: string;
|
|
227
|
+
code: "CONNECTION_ERROR" | "UNAUTHORIZED" | "SUBSCRIPTION_ERROR"
|
|
228
|
+
| "PARSE_ERROR" | "RECONNECT_FAILED" | "UNKNOWN";
|
|
229
|
+
cause?: Error;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
| Code | Description |
|
|
234
|
+
|------|-------------|
|
|
235
|
+
| `CONNECTION_ERROR` | WebSocket connection failed (network, TLS) |
|
|
236
|
+
| `UNAUTHORIZED` | Auth token expired or invalid |
|
|
237
|
+
| `SUBSCRIPTION_ERROR` | AppSync subscription error (invalid channel, server error) |
|
|
238
|
+
| `PARSE_ERROR` | Malformed message or event payload |
|
|
239
|
+
| `RECONNECT_FAILED` | Token refresh failed after auth expiry |
|
|
240
|
+
| `UNKNOWN` | Unexpected error |
|
|
146
241
|
|
|
147
242
|
### `dataworks.reportError(error)`
|
|
148
243
|
|
|
@@ -234,6 +329,10 @@ import type {
|
|
|
234
329
|
SubscriptionHandler,
|
|
235
330
|
ErrorHandler,
|
|
236
331
|
Subscription,
|
|
332
|
+
ValidationMode,
|
|
333
|
+
DroppedMetric,
|
|
334
|
+
IngestOptions,
|
|
335
|
+
IngestResult,
|
|
237
336
|
} from "@dataworks-technology/data";
|
|
238
337
|
```
|
|
239
338
|
|
|
@@ -283,6 +382,10 @@ try {
|
|
|
283
382
|
|
|
284
383
|
Calling `ingest()`, `reportError()`, or `subscribe()` before `login()` throws immediately.
|
|
285
384
|
|
|
385
|
+
Exception: `subscribe()` can run without `login()` when `apiKey` is configured. This mode is subscription-only — `ingest()` and `reportError()` still require `login()`.
|
|
386
|
+
|
|
387
|
+
When both Cognito credentials (`login(username, password)` + `clientId`) and `apiKey` are available, the SDK always uses Cognito auth for subscriptions.
|
|
388
|
+
|
|
286
389
|
## Requirements
|
|
287
390
|
|
|
288
391
|
- **Node.js** ≥ 18 (uses native `fetch`)
|
package/dist/index.cjs
CHANGED
|
@@ -31,11 +31,32 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
DataClient: () => DataClient,
|
|
34
|
+
MetricValidationError: () => MetricValidationError,
|
|
34
35
|
filterValidMetrics: () => filterValidMetrics2,
|
|
35
36
|
validateMetric: () => validateMetric2
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(index_exports);
|
|
38
39
|
|
|
40
|
+
// node_modules/@dataworks/sdk/dist/client/events-auth.js
|
|
41
|
+
var INGEST_AUTH_ERROR = "Authentication failed: username, password, and clientId are required for ingest.";
|
|
42
|
+
function resolveEventsAuth(input) {
|
|
43
|
+
const userToken = input.userToken?.trim();
|
|
44
|
+
if (userToken) {
|
|
45
|
+
return { mode: "userCredentials", token: userToken };
|
|
46
|
+
}
|
|
47
|
+
const apiKey = input.apiKey?.trim();
|
|
48
|
+
if (apiKey) {
|
|
49
|
+
return { mode: "apiKey", apiKey };
|
|
50
|
+
}
|
|
51
|
+
throw new Error(INGEST_AUTH_ERROR);
|
|
52
|
+
}
|
|
53
|
+
function buildEventsAuthHeader(resolved, host) {
|
|
54
|
+
if (resolved.mode === "userCredentials") {
|
|
55
|
+
return { Authorization: resolved.token, host };
|
|
56
|
+
}
|
|
57
|
+
return { "x-api-key": resolved.apiKey, host };
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
// node_modules/@dataworks/sdk/dist/client/subscription-manager.js
|
|
40
61
|
function createAutoRefreshingSubscription(options) {
|
|
41
62
|
const maxReconnectAttempts = options.maxReconnectAttempts ?? 1;
|
|
@@ -238,8 +259,22 @@ async function computeSecretHashAsync(username, clientId, clientSecret) {
|
|
|
238
259
|
// src/validation.ts
|
|
239
260
|
var validateMetric2 = validateMetric;
|
|
240
261
|
var filterValidMetrics2 = filterValidMetrics;
|
|
262
|
+
var getMetricValidationResult2 = getMetricValidationResult;
|
|
263
|
+
|
|
264
|
+
// src/types.ts
|
|
265
|
+
var MetricValidationError = class extends Error {
|
|
266
|
+
constructor(message, dropped) {
|
|
267
|
+
super(message);
|
|
268
|
+
this.code = "METRIC_VALIDATION_FAILED";
|
|
269
|
+
this.name = "MetricValidationError";
|
|
270
|
+
this.dropped = dropped;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
241
273
|
|
|
242
274
|
// src/data-client.ts
|
|
275
|
+
function createSubscriptionError(message, code, cause) {
|
|
276
|
+
return { message, code, cause };
|
|
277
|
+
}
|
|
243
278
|
var DataClient = class {
|
|
244
279
|
constructor(config) {
|
|
245
280
|
this.credentials = null;
|
|
@@ -267,7 +302,7 @@ var DataClient = class {
|
|
|
267
302
|
}
|
|
268
303
|
/**
|
|
269
304
|
* Ingest metric data points into the Dataworks Data Engine.
|
|
270
|
-
* Validates each metric before sending — invalid metrics are
|
|
305
|
+
* Validates each metric before sending — invalid metrics are dropped with warnings.
|
|
271
306
|
*
|
|
272
307
|
* @param metrics - Array of metric data points
|
|
273
308
|
* @param eventId - Event identifier
|
|
@@ -276,12 +311,53 @@ var DataClient = class {
|
|
|
276
311
|
* @see https://data-sdk-docs.dataworks.live/ingesting-data
|
|
277
312
|
*/
|
|
278
313
|
async ingest(metrics, eventId, datasetDatasourceId) {
|
|
279
|
-
this.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
314
|
+
await this.ingestWithResult(metrics, eventId, datasetDatasourceId);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Ingest metrics with structured validation diagnostics.
|
|
318
|
+
*
|
|
319
|
+
* By default (`validationMode: "best-effort"`), invalid metrics are dropped and
|
|
320
|
+
* valid metrics continue. In strict mode, invalid metrics cause a
|
|
321
|
+
* MetricValidationError before any network request is sent.
|
|
322
|
+
*
|
|
323
|
+
* @returns IngestResult with accepted/dropped counts and dropped reasons.
|
|
324
|
+
*/
|
|
325
|
+
async ingestWithResult(metrics, eventId, datasetDatasourceId, options = {}) {
|
|
326
|
+
this.requireIngestAuth();
|
|
327
|
+
const validationMode = options.validationMode ?? "best-effort";
|
|
328
|
+
const validation = getMetricValidationResult2(metrics);
|
|
329
|
+
const valid = validation.valid;
|
|
330
|
+
const dropped = validation.dropped.map((item) => ({
|
|
331
|
+
index: item.index,
|
|
332
|
+
reason: item.reason,
|
|
333
|
+
metric: item.metric
|
|
334
|
+
}));
|
|
335
|
+
dropped.forEach((item) => {
|
|
336
|
+
options.onDroppedMetric?.(item);
|
|
337
|
+
console.warn(
|
|
338
|
+
`[@dataworks-technology/data] Dropping invalid metric [${String(item.metric.metric)}=${String(item.metric.value)}]: ${item.reason}`
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
if (validationMode === "strict" && dropped.length > 0) {
|
|
342
|
+
throw new MetricValidationError(
|
|
343
|
+
"[@dataworks-technology/data] validation failed: one or more metrics are invalid",
|
|
344
|
+
dropped
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (valid.length === 0) {
|
|
348
|
+
if (options.requireAtLeastOneValidMetric) {
|
|
349
|
+
throw new MetricValidationError(
|
|
350
|
+
"[@dataworks-technology/data] validation failed: no valid metrics to ingest",
|
|
351
|
+
dropped
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
acceptedCount: 0,
|
|
356
|
+
droppedCount: dropped.length,
|
|
357
|
+
dropped,
|
|
358
|
+
requestSent: false
|
|
359
|
+
};
|
|
360
|
+
}
|
|
285
361
|
const payload = {
|
|
286
362
|
eventId,
|
|
287
363
|
datasetDatasourceId,
|
|
@@ -303,6 +379,12 @@ var DataClient = class {
|
|
|
303
379
|
`[@dataworks-technology/data] ingest failed: ${resp.status} \u2014 ${body}`
|
|
304
380
|
);
|
|
305
381
|
}
|
|
382
|
+
return {
|
|
383
|
+
acceptedCount: valid.length,
|
|
384
|
+
droppedCount: dropped.length,
|
|
385
|
+
dropped,
|
|
386
|
+
requestSent: true
|
|
387
|
+
};
|
|
306
388
|
}
|
|
307
389
|
/**
|
|
308
390
|
* Report an error to the Dataworks Data Engine.
|
|
@@ -312,7 +394,7 @@ var DataClient = class {
|
|
|
312
394
|
* @see https://data-sdk-docs.dataworks.live/error-reporting
|
|
313
395
|
*/
|
|
314
396
|
async reportError(error) {
|
|
315
|
-
this.
|
|
397
|
+
this.requireIngestAuth();
|
|
316
398
|
const resp = await this.fetchWithAutoRefresh(
|
|
317
399
|
(accessToken) => fetch(this.config.errorUrl, {
|
|
318
400
|
method: "POST",
|
|
@@ -351,7 +433,10 @@ var DataClient = class {
|
|
|
351
433
|
* @see https://data-sdk-docs.dataworks.live/real-time-subscriptions
|
|
352
434
|
*/
|
|
353
435
|
subscribe(channel, onEvent, onError) {
|
|
354
|
-
this.
|
|
436
|
+
const apiKey = this.config.apiKey?.trim();
|
|
437
|
+
if (!this.credentials && !apiKey) {
|
|
438
|
+
this.requireAuth();
|
|
439
|
+
}
|
|
355
440
|
if (typeof WebSocket === "undefined") {
|
|
356
441
|
throw new Error(
|
|
357
442
|
"[@dataworks-technology/data] WebSocket is not available. Use Node >= 22, Bun, or a browser environment. For older Node versions, install a WebSocket polyfill (e.g. ws) and assign it to globalThis.WebSocket."
|
|
@@ -365,20 +450,26 @@ var DataClient = class {
|
|
|
365
450
|
const channelPath = channel.startsWith("/") ? channel : `/${channel}`;
|
|
366
451
|
return createAutoRefreshingSubscription({
|
|
367
452
|
refreshAuth: async () => {
|
|
368
|
-
|
|
453
|
+
if (this.credentials) {
|
|
454
|
+
await this.refreshSession();
|
|
455
|
+
}
|
|
369
456
|
},
|
|
370
457
|
onReconnectError: (error) => {
|
|
371
|
-
onError?.(
|
|
458
|
+
onError?.(
|
|
459
|
+
createSubscriptionError(error.message, "RECONNECT_FAILED", error)
|
|
460
|
+
);
|
|
372
461
|
},
|
|
373
462
|
connect: ({ onUnexpectedClose }) => {
|
|
374
463
|
const url = new URL(this.config.realtimeUrl);
|
|
375
464
|
url.pathname = "/event/realtime";
|
|
376
465
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
377
466
|
const host = new URL(this.config.realtimeUrl).host;
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
467
|
+
const resolvedAuth = resolveEventsAuth({
|
|
468
|
+
userToken: this.credentials?.accessToken,
|
|
469
|
+
apiKey: this.config.apiKey?.trim()
|
|
381
470
|
});
|
|
471
|
+
const realtimeAuthHeader = buildEventsAuthHeader(resolvedAuth, host);
|
|
472
|
+
const authPayload = JSON.stringify(realtimeAuthHeader);
|
|
382
473
|
const authHeader = toBase64Url(authPayload);
|
|
383
474
|
const ws = new WebSocket(url.toString(), [
|
|
384
475
|
"aws-appsync-event-ws",
|
|
@@ -396,8 +487,9 @@ var DataClient = class {
|
|
|
396
487
|
});
|
|
397
488
|
ws.addEventListener("error", () => {
|
|
398
489
|
onError?.(
|
|
399
|
-
|
|
400
|
-
"[@dataworks-technology/data] WebSocket connection error"
|
|
490
|
+
createSubscriptionError(
|
|
491
|
+
"[@dataworks-technology/data] WebSocket connection error",
|
|
492
|
+
"CONNECTION_ERROR"
|
|
401
493
|
)
|
|
402
494
|
);
|
|
403
495
|
});
|
|
@@ -407,8 +499,9 @@ var DataClient = class {
|
|
|
407
499
|
msg = JSON.parse(String(event.data));
|
|
408
500
|
} catch {
|
|
409
501
|
onError?.(
|
|
410
|
-
|
|
411
|
-
"[@dataworks-technology/data] Received malformed message from AppSync"
|
|
502
|
+
createSubscriptionError(
|
|
503
|
+
"[@dataworks-technology/data] Received malformed message from AppSync",
|
|
504
|
+
"PARSE_ERROR"
|
|
412
505
|
)
|
|
413
506
|
);
|
|
414
507
|
return;
|
|
@@ -419,10 +512,7 @@ var DataClient = class {
|
|
|
419
512
|
type: "subscribe",
|
|
420
513
|
id: crypto.randomUUID(),
|
|
421
514
|
channel: channelPath,
|
|
422
|
-
authorization:
|
|
423
|
-
Authorization: this.credentials.accessToken,
|
|
424
|
-
host
|
|
425
|
-
}
|
|
515
|
+
authorization: realtimeAuthHeader
|
|
426
516
|
})
|
|
427
517
|
);
|
|
428
518
|
} else if (msg.type === "data") {
|
|
@@ -432,21 +522,31 @@ var DataClient = class {
|
|
|
432
522
|
onEvent(JSON.parse(String(raw)));
|
|
433
523
|
} catch {
|
|
434
524
|
onError?.(
|
|
435
|
-
|
|
436
|
-
"[@dataworks-technology/data] Received malformed event payload from AppSync"
|
|
525
|
+
createSubscriptionError(
|
|
526
|
+
"[@dataworks-technology/data] Received malformed event payload from AppSync",
|
|
527
|
+
"PARSE_ERROR"
|
|
437
528
|
)
|
|
438
529
|
);
|
|
439
530
|
}
|
|
440
531
|
}
|
|
441
532
|
} else if (msg.type === "error" || msg.type === "connection_error" || msg.type === "subscribe_error" || msg.type === "broadcast_error" || msg.type === "unsubscribe_error") {
|
|
442
533
|
const msgStr = JSON.stringify(msg);
|
|
443
|
-
if (msgStr.toLowerCase().includes("unauthor")) {
|
|
534
|
+
if (msgStr.toLowerCase().includes("unauthor") && !unexpectedCloseHandled) {
|
|
535
|
+
onError?.(
|
|
536
|
+
createSubscriptionError(
|
|
537
|
+
"[@dataworks-technology/data] Unauthorized \u2014 session may have expired, attempting to reconnect",
|
|
538
|
+
"UNAUTHORIZED"
|
|
539
|
+
)
|
|
540
|
+
);
|
|
444
541
|
handleUnexpectedCloseOnce();
|
|
445
542
|
} else {
|
|
446
543
|
const errors = msg.errors;
|
|
447
544
|
const errorMessage = msg.message ?? errors?.[0]?.message ?? errors?.[0]?.errorType ?? "AppSync subscription error";
|
|
448
545
|
onError?.(
|
|
449
|
-
|
|
546
|
+
createSubscriptionError(
|
|
547
|
+
`[@dataworks-technology/data] ${errorMessage}`,
|
|
548
|
+
"SUBSCRIPTION_ERROR"
|
|
549
|
+
)
|
|
450
550
|
);
|
|
451
551
|
}
|
|
452
552
|
}
|
|
@@ -481,6 +581,16 @@ var DataClient = class {
|
|
|
481
581
|
);
|
|
482
582
|
}
|
|
483
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* @internal Guard for ingest-only operations (ingest, reportError). Throws the
|
|
586
|
+
* canonical SDK ingest auth error so the message is consistent with the lower-level
|
|
587
|
+
* `@dataworks/sdk/client` HttpClient guard.
|
|
588
|
+
*/
|
|
589
|
+
requireIngestAuth() {
|
|
590
|
+
if (!this.credentials) {
|
|
591
|
+
throw new Error(`[@dataworks-technology/data] ${INGEST_AUTH_ERROR}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
484
594
|
async fetchWithAutoRefresh(makeRequest) {
|
|
485
595
|
this.requireAuth();
|
|
486
596
|
let response = await makeRequest(this.credentials.accessToken);
|
|
@@ -531,6 +641,7 @@ DataClient.filterValidMetrics = filterValidMetrics2;
|
|
|
531
641
|
// Annotate the CommonJS export names for ESM import in node:
|
|
532
642
|
0 && (module.exports = {
|
|
533
643
|
DataClient,
|
|
644
|
+
MetricValidationError,
|
|
534
645
|
filterValidMetrics,
|
|
535
646
|
validateMetric
|
|
536
647
|
});
|