@nativesquare/soma 0.17.0 → 0.18.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.
@@ -234,7 +234,12 @@ export type StravaWebhookActionArgs = {
234
234
  };
235
235
  clientId: string;
236
236
  clientSecret: string;
237
- autoIngest?: boolean;
237
+ /**
238
+ * Per-event override of the auto-ingest flag. The dispatcher resolves the
239
+ * event name from the payload and looks up the flag here. Defaults to `true`
240
+ * for any event missing from the map.
241
+ */
242
+ autoIngestByEvent?: Partial<Record<StravaWebhookEventName, boolean>>;
238
243
  };
239
244
 
240
245
  /** Result returned by the Strava webhook handler action inside the component. */
@@ -313,21 +318,31 @@ export interface GarminOAuthOptions {
313
318
  ) => Promise<void>;
314
319
  }
315
320
 
321
+ /**
322
+ * Configuration for a single Garmin webhook data type.
323
+ *
324
+ * Pass `true` as a shortcut for "register the route with default processing
325
+ * and `autoIngest: true`". Pass an object to customize per-type behavior.
326
+ */
327
+ export type GarminWebhookEventConfig =
328
+ | true
329
+ | {
330
+ /** Custom logic to run after the payload is processed. */
331
+ handler?: GarminWebhookHandler;
332
+ /**
333
+ * Whether the component should auto-write the transformed data to the
334
+ * Soma database for this data type. When `false`, the payload is still
335
+ * validated and transformed (and surfaced to `handler` / `onEvent`), but
336
+ * the DB write is skipped so the host app can ingest it itself.
337
+ *
338
+ * @default true
339
+ */
340
+ autoIngest?: boolean;
341
+ };
342
+
316
343
  export interface GarminWebhookOptions {
317
344
  /** Base path prefix for all webhook routes. @default "/api/garmin/webhook" */
318
345
  basePath?: string;
319
- /**
320
- * Whether to automatically ingest (upsert) transformed data into the Soma
321
- * database when a webhook payload is received.
322
- *
323
- * When `true` (default), incoming data is validated, transformed, and written
324
- * to the database automatically. When `false`, the webhook still receives and
325
- * validates the payload, but skips the database write — useful when you want
326
- * to handle ingestion yourself via the `onEvent` / per-type callbacks.
327
- *
328
- * @default true
329
- */
330
- autoIngest?: boolean;
331
346
  /** Called after every webhook payload is processed, regardless of data type. */
332
347
  onEvent?: GarminWebhookHandler;
333
348
  /**
@@ -336,21 +351,44 @@ export interface GarminWebhookOptions {
336
351
  * **Only data types listed here get an HTTP route registered.**
337
352
  * Unlisted types are ignored — Garmin receives a 404 if it POSTs to them.
338
353
  *
339
- * Pass a handler function to run custom logic after ingestion,
340
- * or `true` to register the route with default processing only.
354
+ * Pass `true` as a shortcut for default processing with auto-ingest, or
355
+ * an object to attach a handler and/or override `autoIngest`.
341
356
  *
342
357
  * @example
343
358
  * ```ts
344
359
  * events: {
345
- * "activities": async (ctx, event) => { // custom side-effect },
346
- * "sleeps": true, // register route, default processing only
347
- * "dailies": true,
360
+ * activities: { handler: async (ctx, event) => { /* side-effect *\/ } },
361
+ * sleeps: true, // default processing
362
+ * dailies: { autoIngest: false }, // skip DB write
363
+ * "body-compositions": { autoIngest: false, handler: customHandler },
348
364
  * }
349
365
  * ```
350
366
  */
351
- events?: Partial<Record<GarminWebhookEventName, GarminWebhookHandler | true>>;
367
+ events?: Partial<Record<GarminWebhookEventName, GarminWebhookEventConfig>>;
352
368
  }
353
369
 
370
+ /**
371
+ * Configuration for a single Strava webhook event.
372
+ *
373
+ * Pass `true` as a shortcut for "process this event with default behavior and
374
+ * `autoIngest: true`". Pass an object to customize per-event behavior.
375
+ */
376
+ export type StravaWebhookEventConfig =
377
+ | true
378
+ | {
379
+ /** Custom logic to run after the event is processed. */
380
+ handler?: StravaWebhookHandler;
381
+ /**
382
+ * Whether the component should auto-write the transformed data to the
383
+ * Soma database for this event. When `false`, the payload is still
384
+ * fetched and transformed (and surfaced to `handler` / `onEvent`), but
385
+ * the DB write is skipped so the host app can ingest it itself.
386
+ *
387
+ * @default true
388
+ */
389
+ autoIngest?: boolean;
390
+ };
391
+
354
392
  export interface StravaWebhookOptions {
355
393
  /** HTTP path for the webhook endpoint. @default "/api/strava/webhook" */
356
394
  path?: string;
@@ -360,17 +398,6 @@ export interface StravaWebhookOptions {
360
398
  * Falls back to `STRAVA_WEBHOOK_VERIFY_TOKEN` env var.
361
399
  */
362
400
  verifyToken?: string;
363
- /**
364
- * Whether to automatically ingest transformed data into the Soma database.
365
- *
366
- * When `true` (default), fetched data is transformed and written to the
367
- * database automatically. When `false`, the webhook still fetches and
368
- * transforms the data, but skips the database write — useful when you want
369
- * to handle ingestion yourself via the `onEvent` / per-event callbacks.
370
- *
371
- * @default true
372
- */
373
- autoIngest?: boolean;
374
401
  /** Called after every webhook event is processed, regardless of event type. */
375
402
  onEvent?: StravaWebhookHandler;
376
403
  /**
@@ -380,20 +407,34 @@ export interface StravaWebhookOptions {
380
407
  * events to a single endpoint. **Only event types listed here are processed.**
381
408
  * Unlisted event types are silently ignored (200 returned, no processing).
382
409
  *
383
- * Pass a handler function for custom logic after processing,
384
- * or `true` to enable default processing for that event type.
410
+ * Pass `true` as a shortcut for default processing with auto-ingest, or an
411
+ * object to attach a handler and/or override `autoIngest`.
385
412
  *
386
413
  * @example
387
414
  * ```ts
388
415
  * events: {
389
- * "activity-create": async (ctx, event) => { // custom side-effect },
390
- * "activity-update": true, // default processing only
391
- * "athlete-update": true,
416
+ * "activity-create": { handler: async (ctx, event) => { /* side-effect *\/ } },
417
+ * "activity-update": true, // default processing
418
+ * "athlete-update": { autoIngest: false }, // skip DB write
392
419
  * "athlete-deauthorize": true,
393
420
  * }
394
421
  * ```
395
422
  */
396
- events?: Partial<Record<StravaWebhookEventName, StravaWebhookHandler | true>>;
423
+ events?: Partial<Record<StravaWebhookEventName, StravaWebhookEventConfig>>;
424
+ }
425
+
426
+ /**
427
+ * Narrow a `GarminWebhookEventConfig` / `StravaWebhookEventConfig` value into
428
+ * its resolved `{ handler, autoIngest }` pair. `true` becomes a no-handler
429
+ * config with auto-ingest enabled; the object form fills in defaults.
430
+ */
431
+ export function resolveEventConfig<H>(
432
+ entry: true | { handler?: H; autoIngest?: boolean } | undefined,
433
+ ): { handler: H | undefined; autoIngest: boolean } {
434
+ if (entry === undefined || entry === true) {
435
+ return { handler: undefined, autoIngest: true };
436
+ }
437
+ return { handler: entry.handler, autoIngest: entry.autoIngest ?? true };
397
438
  }
398
439
 
399
440
  export interface RegisterRoutesOptions {
@@ -2371,7 +2371,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2371
2371
  "action",
2372
2372
  "internal",
2373
2373
  {
2374
- autoIngest?: boolean;
2374
+ autoIngestByEvent?: Record<string, boolean>;
2375
2375
  clientId: string;
2376
2376
  clientSecret: string;
2377
2377
  payload: any;