@contractspec/integration.providers-impls 2.9.0 → 3.0.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.
Files changed (61) hide show
  1. package/README.md +59 -0
  2. package/dist/health.d.ts +1 -0
  3. package/dist/health.js +3 -0
  4. package/dist/impls/async-event-queue.d.ts +8 -0
  5. package/dist/impls/async-event-queue.js +47 -0
  6. package/dist/impls/health/base-health-provider.d.ts +98 -0
  7. package/dist/impls/health/base-health-provider.js +616 -0
  8. package/dist/impls/health/hybrid-health-providers.d.ts +34 -0
  9. package/dist/impls/health/hybrid-health-providers.js +1088 -0
  10. package/dist/impls/health/official-health-providers.d.ts +78 -0
  11. package/dist/impls/health/official-health-providers.js +968 -0
  12. package/dist/impls/health/provider-normalizers.d.ts +28 -0
  13. package/dist/impls/health/provider-normalizers.js +287 -0
  14. package/dist/impls/health/providers.d.ts +2 -0
  15. package/dist/impls/health/providers.js +1094 -0
  16. package/dist/impls/health-provider-factory.d.ts +3 -0
  17. package/dist/impls/health-provider-factory.js +1308 -0
  18. package/dist/impls/index.d.ts +8 -0
  19. package/dist/impls/index.js +2356 -176
  20. package/dist/impls/messaging-github.d.ts +17 -0
  21. package/dist/impls/messaging-github.js +110 -0
  22. package/dist/impls/messaging-slack.d.ts +14 -0
  23. package/dist/impls/messaging-slack.js +80 -0
  24. package/dist/impls/messaging-whatsapp-meta.d.ts +13 -0
  25. package/dist/impls/messaging-whatsapp-meta.js +52 -0
  26. package/dist/impls/messaging-whatsapp-twilio.d.ts +13 -0
  27. package/dist/impls/messaging-whatsapp-twilio.js +82 -0
  28. package/dist/impls/mistral-conversational.d.ts +23 -0
  29. package/dist/impls/mistral-conversational.js +476 -0
  30. package/dist/impls/mistral-conversational.session.d.ts +32 -0
  31. package/dist/impls/mistral-conversational.session.js +206 -0
  32. package/dist/impls/mistral-stt.d.ts +17 -0
  33. package/dist/impls/mistral-stt.js +167 -0
  34. package/dist/impls/provider-factory.d.ts +7 -1
  35. package/dist/impls/provider-factory.js +2338 -176
  36. package/dist/impls/stripe-payments.js +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.js +2360 -174
  39. package/dist/messaging.d.ts +1 -0
  40. package/dist/messaging.js +3 -0
  41. package/dist/node/health.js +2 -0
  42. package/dist/node/impls/async-event-queue.js +46 -0
  43. package/dist/node/impls/health/base-health-provider.js +615 -0
  44. package/dist/node/impls/health/hybrid-health-providers.js +1087 -0
  45. package/dist/node/impls/health/official-health-providers.js +967 -0
  46. package/dist/node/impls/health/provider-normalizers.js +286 -0
  47. package/dist/node/impls/health/providers.js +1093 -0
  48. package/dist/node/impls/health-provider-factory.js +1307 -0
  49. package/dist/node/impls/index.js +2356 -176
  50. package/dist/node/impls/messaging-github.js +109 -0
  51. package/dist/node/impls/messaging-slack.js +79 -0
  52. package/dist/node/impls/messaging-whatsapp-meta.js +51 -0
  53. package/dist/node/impls/messaging-whatsapp-twilio.js +81 -0
  54. package/dist/node/impls/mistral-conversational.js +475 -0
  55. package/dist/node/impls/mistral-conversational.session.js +205 -0
  56. package/dist/node/impls/mistral-stt.js +166 -0
  57. package/dist/node/impls/provider-factory.js +2338 -176
  58. package/dist/node/impls/stripe-payments.js +1 -1
  59. package/dist/node/index.js +2360 -174
  60. package/dist/node/messaging.js +2 -0
  61. package/package.json +204 -12
package/README.md CHANGED
@@ -43,6 +43,65 @@ const factory = new IntegrationProviderFactory();
43
43
  const analytics = await factory.createAnalyticsProvider(context); // key: analytics.posthog
44
44
  ```
45
45
 
46
+ ## Health integrations
47
+
48
+ This package ships health/wearables providers routed by a transport strategy:
49
+
50
+ - Official provider APIs/MCP (Whoop, Apple Health bridge, Oura, Strava, Garmin, Fitbit)
51
+ - Aggregator API/MCP (Open Wearables)
52
+ - Unofficial automation fallback (opt-in and allow-list gated)
53
+
54
+ Factory usage:
55
+
56
+ ```ts
57
+ import { IntegrationProviderFactory } from "@contractspec/integration.providers-impls/impls/provider-factory";
58
+
59
+ const factory = new IntegrationProviderFactory();
60
+ const healthProvider = await factory.createHealthProvider(context); // key: health.*
61
+ ```
62
+
63
+ Connection config example:
64
+
65
+ ```json
66
+ {
67
+ "defaultTransport": "official-api",
68
+ "strategyOrder": [
69
+ "official-api",
70
+ "official-mcp",
71
+ "aggregator-api",
72
+ "aggregator-mcp",
73
+ "unofficial"
74
+ ],
75
+ "allowUnofficial": false,
76
+ "unofficialAllowList": ["health.peloton"],
77
+ "apiBaseUrl": "https://api.provider.example",
78
+ "mcpUrl": "https://mcp.provider.example",
79
+ "oauthTokenUrl": "https://api.provider.example/oauth/token"
80
+ }
81
+ ```
82
+
83
+ Secret payload example (`secretRef` target value):
84
+
85
+ ```json
86
+ {
87
+ "apiKey": "provider-api-key",
88
+ "accessToken": "oauth-access-token",
89
+ "refreshToken": "oauth-refresh-token",
90
+ "clientId": "oauth-client-id",
91
+ "clientSecret": "oauth-client-secret",
92
+ "tokenExpiresAt": "2026-02-01T00:00:00.000Z",
93
+ "mcpAccessToken": "mcp-access-token",
94
+ "webhookSecret": "webhook-signature-secret"
95
+ }
96
+ ```
97
+
98
+ Notes:
99
+
100
+ - Unofficial routing is disabled unless `allowUnofficial: true`.
101
+ - When `unofficialAllowList` is provided, only listed `health.*` keys can use unofficial routing.
102
+ - Unofficial routing expects MCP transport (`mcpUrl`) plus either `mcpAccessToken` or automation credentials.
103
+ - If a selected strategy is unavailable, the resolver falls through `strategyOrder`.
104
+
46
105
  ## Supabase integrations
47
106
 
48
107
  This package now ships two Supabase providers:
@@ -0,0 +1 @@
1
+ export * from '@contractspec/lib.contracts-integrations';
package/dist/health.js ADDED
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ // src/health.ts
3
+ export * from "@contractspec/lib.contracts-integrations";
@@ -0,0 +1,8 @@
1
+ export declare class AsyncEventQueue<T> implements AsyncIterable<T> {
2
+ private readonly values;
3
+ private readonly waiters;
4
+ private done;
5
+ push(value: T): void;
6
+ close(): void;
7
+ [Symbol.asyncIterator](): AsyncIterator<T>;
8
+ }
@@ -0,0 +1,47 @@
1
+ // @bun
2
+ // src/impls/async-event-queue.ts
3
+ class AsyncEventQueue {
4
+ values = [];
5
+ waiters = [];
6
+ done = false;
7
+ push(value) {
8
+ if (this.done) {
9
+ return;
10
+ }
11
+ const waiter = this.waiters.shift();
12
+ if (waiter) {
13
+ waiter({ value, done: false });
14
+ return;
15
+ }
16
+ this.values.push(value);
17
+ }
18
+ close() {
19
+ if (this.done) {
20
+ return;
21
+ }
22
+ this.done = true;
23
+ for (const waiter of this.waiters) {
24
+ waiter({ value: undefined, done: true });
25
+ }
26
+ this.waiters.length = 0;
27
+ }
28
+ [Symbol.asyncIterator]() {
29
+ return {
30
+ next: async () => {
31
+ const value = this.values.shift();
32
+ if (value != null) {
33
+ return { value, done: false };
34
+ }
35
+ if (this.done) {
36
+ return { value: undefined, done: true };
37
+ }
38
+ return new Promise((resolve) => {
39
+ this.waiters.push(resolve);
40
+ });
41
+ }
42
+ };
43
+ }
44
+ }
45
+ export {
46
+ AsyncEventQueue
47
+ };
@@ -0,0 +1,98 @@
1
+ import type { HealthActivity, HealthBiometric, HealthConnectionStatus, HealthDataSource, HealthListActivitiesParams, HealthListActivitiesResult, HealthListBiometricsParams, HealthListBiometricsResult, HealthListNutritionParams, HealthListNutritionResult, HealthListSleepParams, HealthListSleepResult, HealthListWorkoutsParams, HealthListWorkoutsResult, HealthNutrition, HealthProvider, HealthSleep, HealthSyncRequest, HealthSyncResult, HealthWebhookEvent, HealthWebhookRequest, HealthWorkout } from '../../health';
2
+ import type { HealthTransportStrategy } from '@contractspec/integration.runtime/runtime';
3
+ type UnknownRecord = Record<string, unknown>;
4
+ interface OAuthOptions {
5
+ tokenUrl?: string;
6
+ refreshToken?: string;
7
+ clientId?: string;
8
+ clientSecret?: string;
9
+ tokenExpiresAt?: string;
10
+ }
11
+ export interface BaseHealthProviderOptions {
12
+ providerKey: string;
13
+ transport: HealthTransportStrategy;
14
+ apiBaseUrl?: string;
15
+ mcpUrl?: string;
16
+ apiKey?: string;
17
+ accessToken?: string;
18
+ mcpAccessToken?: string;
19
+ webhookSecret?: string;
20
+ webhookSignatureHeader?: string;
21
+ route?: 'primary' | 'fallback';
22
+ aggregatorKey?: string;
23
+ oauth?: OAuthOptions;
24
+ fetchFn?: typeof fetch;
25
+ }
26
+ interface DatasetFetchConfig<P, T> {
27
+ apiPath?: string;
28
+ mcpTool: string;
29
+ listKeys?: readonly string[];
30
+ method?: 'GET' | 'POST';
31
+ buildQuery?: (params: P) => UnknownRecord;
32
+ buildBody?: (params: P) => UnknownRecord;
33
+ mapItem: (item: UnknownRecord, params: P) => T | undefined;
34
+ }
35
+ interface ConnectionStatusConfig {
36
+ apiPath?: string;
37
+ mcpTool: string;
38
+ }
39
+ export declare class HealthProviderCapabilityError extends Error {
40
+ readonly code = "NOT_SUPPORTED";
41
+ constructor(message: string);
42
+ }
43
+ export declare class BaseHealthProvider implements HealthProvider {
44
+ protected readonly providerKey: string;
45
+ protected readonly transport: HealthTransportStrategy;
46
+ private readonly apiBaseUrl?;
47
+ private readonly mcpUrl?;
48
+ private readonly apiKey?;
49
+ private accessToken?;
50
+ private refreshToken?;
51
+ private readonly mcpAccessToken?;
52
+ private readonly webhookSecret?;
53
+ private readonly webhookSignatureHeader;
54
+ private readonly route;
55
+ private readonly aggregatorKey?;
56
+ private readonly oauth;
57
+ private readonly fetchFn;
58
+ private mcpRequestId;
59
+ constructor(options: BaseHealthProviderOptions);
60
+ listActivities(_params: HealthListActivitiesParams): Promise<HealthListActivitiesResult>;
61
+ listWorkouts(_params: HealthListWorkoutsParams): Promise<HealthListWorkoutsResult>;
62
+ listSleep(_params: HealthListSleepParams): Promise<HealthListSleepResult>;
63
+ listBiometrics(_params: HealthListBiometricsParams): Promise<HealthListBiometricsResult>;
64
+ listNutrition(_params: HealthListNutritionParams): Promise<HealthListNutritionResult>;
65
+ getConnectionStatus(params: {
66
+ tenantId: string;
67
+ connectionId: string;
68
+ }): Promise<HealthConnectionStatus>;
69
+ syncActivities(params: HealthSyncRequest): Promise<HealthSyncResult>;
70
+ syncWorkouts(params: HealthSyncRequest): Promise<HealthSyncResult>;
71
+ syncSleep(params: HealthSyncRequest): Promise<HealthSyncResult>;
72
+ syncBiometrics(params: HealthSyncRequest): Promise<HealthSyncResult>;
73
+ syncNutrition(params: HealthSyncRequest): Promise<HealthSyncResult>;
74
+ parseWebhook(request: HealthWebhookRequest): Promise<HealthWebhookEvent>;
75
+ verifyWebhook(request: HealthWebhookRequest): Promise<boolean>;
76
+ protected fetchActivities(params: HealthListActivitiesParams, config: DatasetFetchConfig<HealthListActivitiesParams, HealthActivity>): Promise<HealthListActivitiesResult>;
77
+ protected fetchWorkouts(params: HealthListWorkoutsParams, config: DatasetFetchConfig<HealthListWorkoutsParams, HealthWorkout>): Promise<HealthListWorkoutsResult>;
78
+ protected fetchSleep(params: HealthListSleepParams, config: DatasetFetchConfig<HealthListSleepParams, HealthSleep>): Promise<HealthListSleepResult>;
79
+ protected fetchBiometrics(params: HealthListBiometricsParams, config: DatasetFetchConfig<HealthListBiometricsParams, HealthBiometric>): Promise<HealthListBiometricsResult>;
80
+ protected fetchNutrition(params: HealthListNutritionParams, config: DatasetFetchConfig<HealthListNutritionParams, HealthNutrition>): Promise<HealthListNutritionResult>;
81
+ protected fetchConnectionStatus(params: {
82
+ tenantId: string;
83
+ connectionId: string;
84
+ }, config: ConnectionStatusConfig): Promise<HealthConnectionStatus>;
85
+ protected currentSource(): HealthDataSource;
86
+ protected providerSlug(): string;
87
+ protected unsupported(capability: string): HealthProviderCapabilityError;
88
+ private syncFromList;
89
+ private fetchList;
90
+ private fetchPayload;
91
+ private isMcpTransport;
92
+ private requestApi;
93
+ private callMcpTool;
94
+ private authorizationHeaders;
95
+ private refreshAccessToken;
96
+ private readResponsePayload;
97
+ }
98
+ export {};