@dataworks-technology/data 0.1.4 → 0.1.5

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
@@ -3,6 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@dataworks-technology/data)](https://www.npmjs.com/package/@dataworks-technology/data)
4
4
  [![license](https://img.shields.io/npm/l/@dataworks-technology/data)](./LICENSE)
5
5
  [![bundle size](https://img.shields.io/bundlephobia/minzip/@dataworks-technology/data)](https://bundlephobia.com/package/@dataworks-technology/data)
6
+ [![docs](https://img.shields.io/badge/docs-data--sdk--docs.dataworks.live-blue)](https://data-sdk-docs.dataworks.live)
6
7
 
7
8
  Official SDK for the Dataworks Data Engine — authenticate, ingest live athlete metrics, subscribe to real-time data streams, and report errors.
8
9
 
@@ -51,7 +52,7 @@ bun add @dataworks-technology/data
51
52
  ```typescript
52
53
  import { DataClient } from "@dataworks-technology/data";
53
54
 
54
- const client = new DataClient({
55
+ const dataworks = new DataClient({
55
56
  cognitoEndpoint: "https://cognito-idp.eu-west-1.amazonaws.com/",
56
57
  clientId: "your-client-id",
57
58
  ingestUrl: "https://your-ingest-endpoint.dataworks.live",
@@ -60,14 +61,14 @@ const client = new DataClient({
60
61
  });
61
62
 
62
63
  // Authenticate
63
- await client.login("username", "password");
64
+ await dataworks.login("username", "password");
64
65
 
65
66
  // Ingest metrics
66
- await client.ingest(
67
+ await dataworks.ingest(
67
68
  [
68
69
  {
69
70
  athleteId: "athlete-1",
70
- metric: "heartrate",
71
+ metric: "heartrate_calculated",
71
72
  value: 172,
72
73
  timestamp: Math.floor(Date.now() / 1000),
73
74
  },
@@ -84,7 +85,7 @@ await client.ingest(
84
85
  Create a new client instance.
85
86
 
86
87
  ```typescript
87
- const client = new DataClient({
88
+ const dataworks = new DataClient({
88
89
  cognitoEndpoint: "https://cognito-idp.eu-west-1.amazonaws.com/",
89
90
  clientId: "abc123",
90
91
  ingestUrl: "https://ingest.dataworks.live",
@@ -93,37 +94,39 @@ const client = new DataClient({
93
94
  });
94
95
  ```
95
96
 
96
- ### `client.login(username, password)`
97
+ ### `dataworks.login(username, password)`
97
98
 
98
99
  Authenticate with Cognito. Must be called before any other operation.
99
100
 
100
101
  ```typescript
101
- const result = await client.login("username", "password");
102
+ const result = await dataworks.login("username", "password");
102
103
  // result: { accessToken, idToken, refreshToken, tenant }
103
104
  ```
104
105
 
105
- ### `client.ingest(metrics, eventId, datasetDatasourceId)`
106
+ ### `dataworks.ingest(metrics, eventId, datasetDatasourceId)`
106
107
 
107
108
  Send metric data points to the Data Engine. Invalid metrics are automatically filtered out.
108
109
 
109
110
  ```typescript
110
- await client.ingest(
111
+ await dataworks.ingest(
111
112
  [
112
- { athleteId: "1", metric: "heartrate", value: 172, timestamp: 1700000000 },
113
- { athleteId: "1", metric: "speed", value: 4.2, timestamp: 1700000000 },
113
+ { athleteId: "1", metric: "heartrate_calculated", value: 172, timestamp: 1700000000 },
114
+ { athleteId: "1", metric: "speed_calculated", value: 4.2, timestamp: 1700000000 },
114
115
  ],
115
116
  "event-123",
116
117
  "ds-456",
117
118
  );
118
119
  ```
119
120
 
120
- ### `client.subscribe(channel, onEvent)`
121
+ ### `dataworks.subscribe(channel, onEvent)`
121
122
 
122
123
  Subscribe to real-time data events via WebSocket.
123
124
 
125
+ 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
+
124
127
  ```typescript
125
- const subscription = client.subscribe(
126
- "/default/events/event-123",
128
+ const subscription = dataworks.subscribe(
129
+ "dataworks/1/1/heartrate",
127
130
  (event) => {
128
131
  console.log("Received:", event);
129
132
  },
@@ -133,12 +136,12 @@ const subscription = client.subscribe(
133
136
  subscription.close();
134
137
  ```
135
138
 
136
- ### `client.reportError(error)`
139
+ ### `dataworks.reportError(error)`
137
140
 
138
141
  Report an error to the Data Engine for monitoring and alerting.
139
142
 
140
143
  ```typescript
141
- await client.reportError({
144
+ await dataworks.reportError({
142
145
  datasetDatasourceId: "ds-456",
143
146
  athleteId: "athlete-123",
144
147
  clientId: 1,
@@ -147,22 +150,22 @@ await client.reportError({
147
150
  });
148
151
  ```
149
152
 
150
- ### `client.isAuthenticated`
153
+ ### `dataworks.isAuthenticated`
151
154
 
152
155
  Check if the client has valid credentials.
153
156
 
154
157
  ```typescript
155
- if (client.isAuthenticated) {
156
- await client.ingest(metrics, eventId, dsId);
158
+ if (dataworks.isAuthenticated) {
159
+ await dataworks.ingest(metrics, eventId, dsId);
157
160
  }
158
161
  ```
159
162
 
160
- ### `client.tenant`
163
+ ### `dataworks.tenant`
161
164
 
162
165
  Get the tenant from the authenticated session (or `null`).
163
166
 
164
167
  ```typescript
165
- console.log(`Logged in as tenant: ${client.tenant}`);
168
+ console.log(`Logged in as tenant: ${dataworks.tenant}`);
166
169
  ```
167
170
 
168
171
  ## Validation Utilities
@@ -257,13 +260,13 @@ All async methods throw on failure. Wrap calls in try/catch:
257
260
 
258
261
  ```typescript
259
262
  try {
260
- await client.login("user", "pass");
263
+ await dataworks.login("user", "pass");
261
264
  } catch (err) {
262
265
  // Authentication failed (invalid credentials, network error, etc.)
263
266
  }
264
267
 
265
268
  try {
266
- await client.ingest(metrics, eventId, dsId);
269
+ await dataworks.ingest(metrics, eventId, dsId);
267
270
  } catch (err) {
268
271
  // Ingestion failed (401 expired token, 5xx server error, etc.)
269
272
  }
@@ -285,7 +288,7 @@ A core use case: subscribe to live metrics, apply your own calculations external
285
288
  ### Concept
286
289
 
287
290
  ```
288
- Data Engine → subscribe("heartrate") → Your App → calculate rolling avg → ingest("heartrate_rolling_avg") → Data Engine
291
+ Data Engine → subscribe("dataworks/{datasetDatasourceId}/{eventId}/heartrate") → Your App → calculate rolling avg → ingest("heartrate_rolling_avg_calculated") → Data Engine
289
292
  ```
290
293
 
291
294
  Any metric you ingest is treated the same as raw sensor data — it flows through the enrichment pipeline (avg/min/max/zones), gets stored, and is available via subscriptions and the GraphQL API.
@@ -295,7 +298,7 @@ Any metric you ingest is treated the same as raw sensor data — it flows throug
295
298
  ```typescript
296
299
  import { DataClient } from "@dataworks-technology/data";
297
300
 
298
- const client = new DataClient({
301
+ const dataworks = new DataClient({
299
302
  cognitoEndpoint: "https://cognito-idp.eu-west-1.amazonaws.com/",
300
303
  clientId: "your-client-id",
301
304
  ingestUrl: "https://your-ingest-endpoint.dataworks.live",
@@ -303,13 +306,16 @@ const client = new DataClient({
303
306
  realtimeUrl: "https://your-realtime-endpoint.dataworks.live",
304
307
  });
305
308
 
306
- await client.login("developer", "password");
309
+ await dataworks.login("developer", "password");
307
310
 
308
311
  // 1. Subscribe to raw heart rate data
309
312
  const buffer: number[] = [];
313
+ const datasetDatasourceId = "1";
314
+ const eventId = "1";
315
+ const heartrateChannel = `dataworks/${datasetDatasourceId}/${eventId}/heartrate`;
310
316
 
311
- client.subscribe("dataworks/metrics", (event) => {
312
- if (event.metric !== "heartrate") return;
317
+ dataworks.subscribe(heartrateChannel, (event) => {
318
+ // No metric guard needed here: the channel already filters to heartrate.
313
319
 
314
320
  // 2. Calculate a rolling 3-point average
315
321
  buffer.push(event.value);
@@ -317,11 +323,11 @@ client.subscribe("dataworks/metrics", (event) => {
317
323
  const avg = buffer.reduce((a, b) => a + b, 0) / buffer.length;
318
324
 
319
325
  // 3. Push the derived metric back into the engine
320
- client.ingest(
326
+ dataworks.ingest(
321
327
  [
322
328
  {
323
329
  athleteId: event.athleteId,
324
- metric: "heartrate_rolling_avg",
330
+ metric: "heartrate_rolling_avg_calculated",
325
331
  value: Math.round(avg * 10) / 10,
326
332
  timestamp: event.timestamp,
327
333
  },
@@ -338,12 +344,12 @@ The same flow works from any language. A full working Python demo is included at
338
344
 
339
345
  | Phase | What it does | SDK equivalent |
340
346
  |-------|-------------|----------------|
341
- | 1. Authenticate | Cognito USER_PASSWORD_AUTH | `client.login()` |
342
- | 2. Subscribe | WebSocket → AppSync Events API | `client.subscribe()` |
347
+ | 1. Authenticate | Cognito USER_PASSWORD_AUTH | `dataworks.login()` |
348
+ | 2. Subscribe | WebSocket → AppSync Events API | `dataworks.subscribe()` |
343
349
  | 3. Receive | Catch events on the subscriber | `onEvent` callback |
344
350
  | 4. Calculate | Write to CSV/Google Sheets, compute rolling avg + HR zones | Your business logic |
345
- | 5. Re-ingest | POST enriched metrics back to the Data Engine | `client.ingest()` |
346
- | 6. Report Error | Send error through the error pipeline | `client.reportError()` |
351
+ | 5. Re-ingest | POST enriched metrics back to the Data Engine | `dataworks.ingest()` |
352
+ | 6. Report Error | Send error through the error pipeline | `dataworks.reportError()` |
347
353
 
348
354
  #### Run the demo
349
355
 
@@ -375,7 +381,7 @@ PHASE 5: RE-INGEST ENRICHED METRICS
375
381
  ✓ Ingested (200)
376
382
  ```
377
383
 
378
- The raw `heartrate` values (130–170 bpm) are transformed into `heartrate_rolling_avg` derived metrics and pushed back into the platform. These derived metrics are then available to all consumers (Console, Visual, Moments triggers) just like any other metric.
384
+ The raw `heartrate` values (130–170 bpm) are transformed into `heartrate_rolling_avg_calculated` derived metrics and pushed back into the platform. These derived metrics are then available to all consumers (Console, Visual, Moments triggers) just like any other metric.
379
385
 
380
386
  #### Google Sheets (optional)
381
387
 
@@ -385,7 +391,7 @@ The demo can write to Google Sheets instead of CSV — formulas compute rolling
385
391
 
386
392
  | Derived metric | Calculation | Use case |
387
393
  |---|---|---|
388
- | `heartrate_rolling_avg` | 3-point moving average | Smooth noisy sensor data |
394
+ | `heartrate_rolling_avg_calculated` | 3-point moving average | Smooth noisy sensor data |
389
395
  | `heartrate_zone` | Zone classification (1–5) | Training load analysis |
390
396
  | `speed_efficiency` | Speed / heart rate ratio | Fatigue detection |
391
397
  | `power_to_weight` | Power / athlete weight | Normalised performance |
@@ -396,7 +402,7 @@ The demo can write to Google Sheets instead of CSV — formulas compute rolling
396
402
 
397
403
  Full documentation with guides, examples, and detailed API reference:
398
404
 
399
- **[https://data-docs.dataworks.live](https://data-docs.dataworks.live)**
405
+ **[https://data-sdk-docs.dataworks.live](https://data-sdk-docs.dataworks.live)**
400
406
 
401
407
  ## Development
402
408
 
@@ -408,9 +414,49 @@ This package publishes to **public npm** (`registry.npmjs.org`), not to the inte
408
414
 
409
415
  ```bash
410
416
  bun run build # tsup → dist/ (ESM + CJS + DTS)
417
+ bun run dev # tsup --watch (rebuild on save)
411
418
  bun run test # vitest unit tests (mocked — no infra needed)
412
419
  ```
413
420
 
421
+ ### Local Development
422
+
423
+ To test SDK changes locally before publishing:
424
+
425
+ **Option A — `npm pack` (recommended, simulates real install):**
426
+
427
+ ```bash
428
+ # In packages/sdk/
429
+ bun run build
430
+ npm pack # creates dataworks-technology-data-0.1.4.tgz
431
+
432
+ # In your consumer project (e.g. test/demo/)
433
+ npm install ../../packages/sdk/dataworks-technology-data-0.1.4.tgz
434
+ ```
435
+
436
+ **Option B — `bun link` (faster iteration):**
437
+
438
+ ```bash
439
+ # In packages/sdk/
440
+ bun run build
441
+ bun link
442
+
443
+ # In your consumer project
444
+ bun link @dataworks-technology/data
445
+ ```
446
+
447
+ **Option C — watch mode + link (live reload):**
448
+
449
+ ```bash
450
+ # Terminal 1: packages/sdk/
451
+ bun run dev # rebuilds dist/ on every save
452
+
453
+ # Terminal 2: consumer project
454
+ bun link @dataworks-technology/data
455
+ npx tsx demo.ts # picks up latest build automatically
456
+ ```
457
+
458
+ > **Tip:** After local testing, remember to `bun unlink` or reinstall from npm before committing.
459
+
414
460
  ### Publish
415
461
 
416
462
  Login to npm first (one-time):
@@ -456,7 +502,7 @@ bun x vitest run test/e2e-public-sdk.test.ts
456
502
  | 1 | **Login** | `should authenticate testdeveloper` | USER_PASSWORD_AUTH works with frontend client | AWS Console → Cognito → User Pool → Users → `testdeveloper` exists in `developer` group |
457
503
  | 2 | **Login** | `should extract tenant from JWT` | `custom:tenant` claim is present in ID token | Decode the JWT at [jwt.io](https://jwt.io) — look for `custom:tenant` |
458
504
  | 3 | **Login** | `should include resource server scopes` | Pre-token Lambda injects `dataworks.live/read` and `/write` | AWS Console → Cognito → User Pool → Lambda triggers → Pre token generation V2 is set |
459
- | 4 | **Login** | `should reject invalid credentials` | Bad password returns error, not a token | Try `client.login("testdeveloper", "wrong")` — should throw |
505
+ | 4 | **Login** | `should reject invalid credentials` | Bad password returns error, not a token | Try `dataworks.login("testdeveloper", "wrong")` — should throw |
460
506
  | 5 | **Ingest** | `should ingest valid metrics` | JWT passes API Gateway authoriser, Lambda processes payload | AWS Console → CloudWatch → Log group for the ingest Lambda — look for the metric |
461
507
  | 6 | **Ingest** | `should filter invalid metrics` | Client-side validation drops bad metrics before sending | The `stderr` output shows `Dropping invalid metric` — local validation, no server call for bad data |
462
508
  | 7 | **Ingest** | `should throw when not authenticated` | `ingest()` before `login()` throws immediately | Client-side guard — no network call made |