@cosmoops/connect-sdk 0.3.0 → 0.7.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 (137) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/README.md +215 -6
  3. package/dist/cjs/cli/doctor.js +3 -3
  4. package/dist/cjs/cli/init.js +3 -3
  5. package/dist/cjs/client/components/access-gate.js +162 -0
  6. package/dist/cjs/client/components/account-sessions.js +24 -22
  7. package/dist/cjs/client/components/app-shell.js +157 -0
  8. package/dist/cjs/client/components/apps-grid.js +4 -3
  9. package/dist/cjs/client/components/feature-gate.js +2 -2
  10. package/dist/cjs/client/components/integrations-modal.js +95 -0
  11. package/dist/cjs/client/components/logo.js +3 -3
  12. package/dist/cjs/client/components/motion.js +27 -0
  13. package/dist/cjs/client/components/nav.js +97 -0
  14. package/dist/cjs/client/components/plan-pricing.js +1 -1
  15. package/dist/cjs/client/components/plans.js +42 -40
  16. package/dist/cjs/client/components/readiness.js +6 -4
  17. package/dist/cjs/client/components/side-nav.js +58 -0
  18. package/dist/cjs/client/components/subscribe-dialog.js +2 -2
  19. package/dist/cjs/client/components/subscription.js +3 -2
  20. package/dist/cjs/client/components/surfaces.js +54 -0
  21. package/dist/cjs/client/components/usage-meter.js +4 -3
  22. package/dist/cjs/client/components/user-menu.js +33 -6
  23. package/dist/cjs/client/index.js +30 -2
  24. package/dist/cjs/client/mark.js +1 -1
  25. package/dist/cjs/client/provider.js +60 -8
  26. package/dist/cjs/client/use-active-path.js +77 -0
  27. package/dist/cjs/client/use-checkout.js +3 -3
  28. package/dist/cjs/errors.js +4 -4
  29. package/dist/cjs/helpers.js +1 -1
  30. package/dist/cjs/index.js +1 -1
  31. package/dist/cjs/next/index.js +96 -15
  32. package/dist/cjs/server/client.js +22 -14
  33. package/dist/cjs/server/handler.js +99 -16
  34. package/dist/cjs/server/http.js +1 -1
  35. package/dist/cjs/server/index.js +8 -1
  36. package/dist/cjs/server/resources/access.js +3 -3
  37. package/dist/cjs/server/resources/ai.js +1 -1
  38. package/dist/cjs/server/resources/analytics.js +66 -0
  39. package/dist/cjs/server/resources/apps.js +4 -4
  40. package/dist/cjs/server/resources/billing.js +5 -5
  41. package/dist/cjs/server/resources/drive.js +4 -4
  42. package/dist/cjs/server/resources/entitlements.js +7 -7
  43. package/dist/cjs/server/resources/identity.js +4 -4
  44. package/dist/cjs/server/resources/integrations.js +66 -0
  45. package/dist/cjs/server/resources/logs.js +3 -3
  46. package/dist/cjs/server/resources/sessions.js +6 -6
  47. package/dist/cjs/server/webhooks.js +127 -0
  48. package/dist/cjs/types.js +1 -1
  49. package/dist/esm/cli/doctor.js +3 -3
  50. package/dist/esm/cli/init.js +3 -3
  51. package/dist/esm/client/components/access-gate.js +158 -0
  52. package/dist/esm/client/components/account-sessions.js +24 -22
  53. package/dist/esm/client/components/app-shell.js +154 -0
  54. package/dist/esm/client/components/apps-grid.js +4 -3
  55. package/dist/esm/client/components/feature-gate.js +2 -2
  56. package/dist/esm/client/components/integrations-modal.js +92 -0
  57. package/dist/esm/client/components/logo.js +3 -3
  58. package/dist/esm/client/components/motion.js +21 -0
  59. package/dist/esm/client/components/nav.js +89 -0
  60. package/dist/esm/client/components/plan-pricing.js +1 -1
  61. package/dist/esm/client/components/plans.js +42 -40
  62. package/dist/esm/client/components/readiness.js +6 -4
  63. package/dist/esm/client/components/side-nav.js +53 -0
  64. package/dist/esm/client/components/subscribe-dialog.js +2 -2
  65. package/dist/esm/client/components/subscription.js +3 -2
  66. package/dist/esm/client/components/surfaces.js +51 -0
  67. package/dist/esm/client/components/usage-meter.js +4 -3
  68. package/dist/esm/client/components/user-menu.js +34 -7
  69. package/dist/esm/client/index.js +16 -2
  70. package/dist/esm/client/mark.js +1 -1
  71. package/dist/esm/client/provider.js +59 -8
  72. package/dist/esm/client/use-active-path.js +74 -0
  73. package/dist/esm/client/use-checkout.js +3 -3
  74. package/dist/esm/errors.js +4 -4
  75. package/dist/esm/helpers.js +1 -1
  76. package/dist/esm/index.js +1 -1
  77. package/dist/esm/next/index.js +95 -15
  78. package/dist/esm/server/client.js +22 -14
  79. package/dist/esm/server/handler.js +99 -16
  80. package/dist/esm/server/http.js +1 -1
  81. package/dist/esm/server/index.js +5 -0
  82. package/dist/esm/server/resources/access.js +3 -3
  83. package/dist/esm/server/resources/ai.js +1 -1
  84. package/dist/esm/server/resources/analytics.js +62 -0
  85. package/dist/esm/server/resources/apps.js +4 -4
  86. package/dist/esm/server/resources/billing.js +5 -5
  87. package/dist/esm/server/resources/drive.js +4 -4
  88. package/dist/esm/server/resources/entitlements.js +7 -7
  89. package/dist/esm/server/resources/identity.js +4 -4
  90. package/dist/esm/server/resources/integrations.js +62 -0
  91. package/dist/esm/server/resources/logs.js +3 -3
  92. package/dist/esm/server/resources/sessions.js +6 -6
  93. package/dist/esm/server/webhooks.js +123 -0
  94. package/dist/esm/types.js +1 -1
  95. package/dist/theme.css +28 -0
  96. package/dist/types/client/components/access-gate.d.ts +79 -0
  97. package/dist/types/client/components/account-sessions.d.ts +1 -1
  98. package/dist/types/client/components/app-shell.d.ts +115 -0
  99. package/dist/types/client/components/apps-grid.d.ts +1 -1
  100. package/dist/types/client/components/feature-gate.d.ts +1 -1
  101. package/dist/types/client/components/integrations-modal.d.ts +21 -0
  102. package/dist/types/client/components/logo.d.ts +5 -5
  103. package/dist/types/client/components/motion.d.ts +22 -0
  104. package/dist/types/client/components/nav.d.ts +110 -0
  105. package/dist/types/client/components/plan-pricing.d.ts +2 -2
  106. package/dist/types/client/components/readiness.d.ts +2 -2
  107. package/dist/types/client/components/side-nav.d.ts +31 -0
  108. package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
  109. package/dist/types/client/components/surfaces.d.ts +51 -0
  110. package/dist/types/client/components/usage-meter.d.ts +1 -1
  111. package/dist/types/client/components/user-menu.d.ts +2 -2
  112. package/dist/types/client/index.d.ts +13 -2
  113. package/dist/types/client/mark.d.ts +1 -1
  114. package/dist/types/client/provider.d.ts +44 -9
  115. package/dist/types/client/use-active-path.d.ts +8 -0
  116. package/dist/types/client/use-checkout.d.ts +3 -3
  117. package/dist/types/errors.d.ts +4 -4
  118. package/dist/types/helpers.d.ts +1 -1
  119. package/dist/types/index.d.ts +1 -1
  120. package/dist/types/next/index.d.ts +40 -0
  121. package/dist/types/server/client.d.ts +17 -11
  122. package/dist/types/server/handler.d.ts +2 -2
  123. package/dist/types/server/index.d.ts +7 -0
  124. package/dist/types/server/resources/access.d.ts +3 -3
  125. package/dist/types/server/resources/ai.d.ts +2 -2
  126. package/dist/types/server/resources/analytics.d.ts +31 -0
  127. package/dist/types/server/resources/apps.d.ts +4 -4
  128. package/dist/types/server/resources/billing.d.ts +4 -4
  129. package/dist/types/server/resources/drive.d.ts +4 -4
  130. package/dist/types/server/resources/entitlements.d.ts +4 -4
  131. package/dist/types/server/resources/identity.d.ts +14 -4
  132. package/dist/types/server/resources/integrations.d.ts +40 -0
  133. package/dist/types/server/resources/logs.d.ts +3 -3
  134. package/dist/types/server/resources/sessions.d.ts +5 -5
  135. package/dist/types/server/webhooks.d.ts +67 -0
  136. package/dist/types/types.d.ts +220 -39
  137. package/package.json +10 -4
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Wire types for the `/api/v1/service/*` surface - the service-partner API,
2
+ * Wire types for the `/api/v1/application/*` surface - the application-partner API,
3
3
  * and the only thing this SDK covers.
4
4
  *
5
5
  * Hand-written rather than generated so the published package carries no
@@ -16,11 +16,20 @@ export interface ConnectUser {
16
16
  email: string | null;
17
17
  emailVerified: boolean;
18
18
  displayName: string | null;
19
- organizationId: string;
20
- organizationName: string;
19
+ /**
20
+ * The member's profile picture, or `null` when they have not set one.
21
+ *
22
+ * Deliberately nullable rather than a generated placeholder: only you know
23
+ * what your fallback should look like. `<ConnectUserMenu>` renders initials
24
+ * via `<Avatar.Fallback>`, which also covers the URL loading slowly or
25
+ * failing outright - so pair the two rather than branching on `null`.
26
+ */
27
+ photoUrl: string | null;
28
+ workspaceId: string;
29
+ workspaceName: string;
21
30
  }
22
31
  export type SubscriptionStatus = "created" | "authenticated" | "active" | "paused" | "cancelled";
23
- /** The compact subscription block returned alongside identity - `null` when the org has never subscribed to this service. */
32
+ /** The compact subscription block returned alongside identity - `null` when the workspace has never subscribed to this application. */
24
33
  export interface SessionSubscription {
25
34
  planId: string;
26
35
  status: SubscriptionStatus;
@@ -29,11 +38,11 @@ export interface SessionSubscription {
29
38
  isTrialing: boolean;
30
39
  }
31
40
  /**
32
- * What this member may do on *your* service - resolved for your `client_id`,
33
- * not their org-wide roles. `role` is `null` when their granted permissions
41
+ * What this member may do on *your* application - resolved for your `client_id`,
42
+ * not their workspace-wide roles. `role` is `null` when their granted permissions
34
43
  * match no single defined role, including when they have no access at all.
35
44
  */
36
- export interface ServiceRole {
45
+ export interface ApplicationRole {
37
46
  role: string | null;
38
47
  granted: string[];
39
48
  }
@@ -48,12 +57,12 @@ export interface TokenResponse {
48
57
  sessionTokenExpiresIn: number;
49
58
  user: ConnectUser;
50
59
  subscription: SessionSubscription | null;
51
- serviceRole: ServiceRole;
60
+ applicationRole: ApplicationRole;
52
61
  }
53
62
  export interface UserResponse {
54
63
  user: ConnectUser;
55
64
  subscription: SessionSubscription | null;
56
- serviceRole: ServiceRole;
65
+ applicationRole: ApplicationRole;
57
66
  /** ISO 8601. Refresh proactively off this rather than waiting for a 401. */
58
67
  sessionExpiresAt: string;
59
68
  }
@@ -74,28 +83,28 @@ export interface IdTokenClaims {
74
83
  export type LogoutScope = "device" | "all";
75
84
  export interface UserRolesResponse {
76
85
  userId: string;
77
- organizationId: string;
86
+ workspaceId: string;
78
87
  role: string | null;
79
88
  granted: string[];
80
89
  }
81
- export interface ServicePermission {
90
+ export interface ApplicationPermission {
82
91
  id: string;
83
92
  label: string;
84
93
  description: string;
85
94
  }
86
- export interface ServiceRoleDefinition {
95
+ export interface ApplicationRoleDefinition {
87
96
  key: string;
88
97
  name: string;
89
98
  description: string;
90
99
  permissions: string[];
91
100
  }
92
101
  export interface RolesResponse {
93
- serviceId: string;
94
- serviceKey: string | null;
95
- permissionCatalog: ServicePermission[];
96
- roles: ServiceRoleDefinition[];
102
+ applicationId: string;
103
+ applicationKey: string | null;
104
+ permissionCatalog: ApplicationPermission[];
105
+ roles: ApplicationRoleDefinition[];
97
106
  }
98
- export type ReadinessBlockerCode = "subscription_missing" | "subscription_inactive" | "audience_mismatch" | "verification_required" | "verification_pending" | "verification_rejected" | "verification_expired" | "payment_method_missing" | "seat_limit_reached" | "organization_not_found" | "onboarding_approval_pending" | "onboarding_approval_rejected";
107
+ export type ReadinessBlockerCode = "subscription_missing" | "subscription_inactive" | "audience_mismatch" | "verification_required" | "verification_pending" | "verification_rejected" | "verification_expired" | "payment_method_missing" | "seat_limit_reached" | "workspace_not_found" | "onboarding_approval_pending" | "onboarding_approval_rejected" | "workspace_suspended" | "payment_retry_pending";
99
108
  export interface ReadinessBlocker {
100
109
  /**
101
110
  * Branch on this. Typed as a union for the codes that exist today, widened
@@ -108,10 +117,12 @@ export interface ReadinessBlocker {
108
117
  message: string;
109
118
  /** Where in Connect the customer resolves this. `null` when nothing they do helps (e.g. a review in progress). */
110
119
  resolveUrl: string | null;
120
+ /** When this blocker resolves itself automatically - currently only set on `payment_retry_pending`, the deadline dunning suspends the subscription. `undefined`/`null` for every other code. */
121
+ graceEndsAt?: string | null;
111
122
  }
112
123
  export interface ReadinessResponse {
113
- organizationId: string;
114
- serviceId: string;
124
+ workspaceId: string;
125
+ applicationId: string;
115
126
  /** `false` if any blocker is `"blocking"`. */
116
127
  ready: boolean;
117
128
  readiness: {
@@ -148,7 +159,7 @@ export interface PlanAddon {
148
159
  *
149
160
  * Note the asymmetry with `SubscribedPlan.features`, which is bare
150
161
  * `string[]` and stays that way. That field is a gating contract - your
151
- * backend calls `hasFeature(orgId, "campaign-module")` against it, and
162
+ * backend calls `hasFeature(workspaceId, "campaign-module")` against it, and
152
163
  * `ConnectFeatureGate` matches on it - so turning it into objects would break
153
164
  * every check for a label nobody gates on. This one exists to be rendered,
154
165
  * and rendering a bare key puts "campaign-module" on a pricing card where it
@@ -159,7 +170,7 @@ export interface PlanAddon {
159
170
  export interface PlanFeature {
160
171
  /** The same value `SubscribedPlan.features` holds and `hasFeature` gates on. */
161
172
  key: string;
162
- /** Human label. Falls back to `key` for a plan predating the service's feature catalog. */
173
+ /** Human label. Falls back to `key` for a plan predating the application's feature catalog. */
163
174
  name: string;
164
175
  /** Empty string when the catalog carries no description. */
165
176
  description: string;
@@ -242,15 +253,15 @@ export interface SubscriptionDetail {
242
253
  appliedDiscount: AppliedDiscount | null;
243
254
  }
244
255
  export interface SubscriptionResponse {
245
- organizationId: string;
246
- serviceId: string;
256
+ workspaceId: string;
257
+ applicationId: string;
247
258
  /** Equivalent to `subscription?.status === "active"`. */
248
259
  hasActiveSubscription: boolean;
249
260
  subscription: SubscriptionDetail | null;
250
261
  /** `null` exactly when `subscription` is. */
251
262
  plan: SubscribedPlan | null;
252
263
  }
253
- /** One consumable add-on's remaining balance on an organization's subscription. */
264
+ /** One consumable add-on's remaining balance on a workspace's subscription. */
254
265
  export interface AddonUsage {
255
266
  addonId: string;
256
267
  name: string;
@@ -273,10 +284,10 @@ export interface AddonUsage {
273
284
  maxOverageUnits: number | null;
274
285
  }
275
286
  export interface AddonUsageResponse {
276
- organizationId: string;
277
- serviceId: string;
287
+ workspaceId: string;
288
+ applicationId: string;
278
289
  /**
279
- * Empty when the organization has no subscription, the plan has no
290
+ * Empty when the workspace has no subscription, the plan has no
280
291
  * consumable add-ons, or none are selected. All three mean "nothing to
281
292
  * meter" and none is an error.
282
293
  *
@@ -290,7 +301,7 @@ export interface AddonUsageResponse {
290
301
  resetsAt: string | null;
291
302
  }
292
303
  export interface ConsumeAddonInput {
293
- organizationId: string;
304
+ workspaceId: string;
294
305
  addonId: string;
295
306
  /** Whole units of the add-on's `unit`. */
296
307
  quantity: number;
@@ -347,8 +358,8 @@ export interface WriteLogInput {
347
358
  * `sessionToken` - the same one the token exchange handed you.
348
359
  *
349
360
  * **There is no `userId` to send, deliberately.** The token is verified and
350
- * checked to have been minted for *your* service before anything is
351
- * attributed, exactly as `serviceId` comes from your API key rather than
361
+ * checked to have been minted for *your* application before anything is
362
+ * attributed, exactly as `applicationId` comes from your API key rather than
352
363
  * your body. An actor a caller could type is not an actor worth recording.
353
364
  *
354
365
  * Omit it for genuine server-to-server events with no user behind them.
@@ -373,10 +384,10 @@ export interface ChatMessage {
373
384
  role: "user" | "assistant" | "system";
374
385
  [field: string]: unknown;
375
386
  }
376
- export interface OrganizationApp {
377
- serviceId: string;
378
- /** Stable, human-readable key - branch on this, not `serviceId`, which is per-environment. */
379
- serviceKey: string | null;
387
+ export interface WorkspaceApp {
388
+ applicationId: string;
389
+ /** Stable, human-readable key - branch on this, not `applicationId`, which is per-environment. */
390
+ applicationKey: string | null;
380
391
  name: string;
381
392
  /** Plain text, HTML already stripped server-side. */
382
393
  description: string;
@@ -384,9 +395,9 @@ export interface OrganizationApp {
384
395
  iconUrl: string | null;
385
396
  /** A `lucide-react` icon name from Connect's curated set. */
386
397
  icon: string;
387
- /** Where a tile navigates. `null` when the service registered no site. */
398
+ /** Where a tile navigates. `null` when the application registered no site. */
388
399
  launchUrl: string | null;
389
- /** True for the service whose API key made the call - render it as the active tile. */
400
+ /** True for the application whose API key made the call - render it as the active tile. */
390
401
  isCurrent: boolean;
391
402
  /** Launchable but not healthy (paused, or cancelling at period end) - badge it, do not hide it. */
392
403
  needsAttention: boolean;
@@ -402,9 +413,9 @@ export interface SessionDevice {
402
413
  }
403
414
  /**
404
415
  * One login to the Connect account behind the `sessionToken` you called with -
405
- * not scoped to this service. A Connect session is one browser's login to
406
- * Connect itself, and it fans out to every partner service's own session -
407
- * Connect has no per-service session concept to filter by. `sessions.list()`
416
+ * not scoped to this application. A Connect session is one browser's login to
417
+ * Connect itself, and it fans out to every partner application's own session -
418
+ * Connect has no per-application session concept to filter by. `sessions.list()`
408
419
  * returns every one of them, exactly like Connect's own account settings
409
420
  * page does for the user themselves.
410
421
  */
@@ -432,3 +443,173 @@ export interface RevokeOtherSessionsResponse {
432
443
  }
433
444
  /** Host-controlled - the SDK has no theme provider of its own. See `ConnectUserMenuProps.theme`. */
434
445
  export type ThemeMode = "light" | "dark" | "system";
446
+ /**
447
+ * `not_connected` never travels over the wire as a persisted state - it's
448
+ * what `ListWorkspaceIntegrationsUseCase` reports for a toolkit this
449
+ * workspace has no `IntegrationConnection` record for at all.
450
+ */
451
+ export type IntegrationConnectionStatus = "not_connected" | "pending" | "active" | "failed" | "disconnected" | "expired";
452
+ /**
453
+ * A Composio-hosted third-party toolkit (Google Calendar, Slack, Twitter/X,
454
+ * ...) this workspace can see - only ever one a platform admin enabled in
455
+ * Connect's own Console, joined with this workspace's own connection status.
456
+ * Connections are workspace-shared: one covers every member, the way a Slack app
457
+ * install is shared rather than per-user.
458
+ */
459
+ export interface IntegrationToolkit {
460
+ slug: string;
461
+ name: string;
462
+ description: string;
463
+ category: string | null;
464
+ logoUrl: string | null;
465
+ status: IntegrationConnectionStatus;
466
+ }
467
+ export interface IntegrationsListResponse {
468
+ toolkits: IntegrationToolkit[];
469
+ }
470
+ /** The connection isn't active yet when this returns - see `IntegrationsResource.initiateConnect`'s doc comment. */
471
+ export interface InitiateIntegrationConnectionResponse {
472
+ /** Send the browser here to complete the provider's OAuth screen. */
473
+ redirectUrl: string;
474
+ connectionId: string;
475
+ }
476
+ export interface DisconnectIntegrationResponse {
477
+ success: true;
478
+ }
479
+ export interface ExecuteIntegrationActionResponse {
480
+ data: unknown;
481
+ successful: boolean;
482
+ }
483
+ /**
484
+ * The metrics Connect can report for your application.
485
+ *
486
+ * Hand-written here rather than imported from Connect's own registry, like
487
+ * every other wire type in this file, so the published package carries none of
488
+ * Connect's internals. `conformance.test.ts` type-checks these against the
489
+ * server DTOs, so drift fails the build in Connect's repo rather than in a
490
+ * partner's integration.
491
+ */
492
+ export type ConnectMetric = "usage.events" | "usage.active_users" | "api.requests" | "api.errors" | "billing.mrr_paise" | "billing.active_subscriptions" | "metering.addon_consumed";
493
+ export interface AnalyticsPoint {
494
+ /** `YYYY-MM-DD`, UTC. */
495
+ day: string;
496
+ /**
497
+ * **`null` is not zero.** It means the metric was not measurable that day -
498
+ * `usage.active_users` is a distinct count that only exists after Connect's
499
+ * nightly rollup, so today's is always `null`, as is any future day. Render
500
+ * it as a gap or a dash, never as a zero.
501
+ */
502
+ value: number | null;
503
+ }
504
+ export interface AnalyticsSeries {
505
+ metric: ConnectMetric;
506
+ points: AnalyticsPoint[];
507
+ /** Sum across measurable days only, or `null` if no day in the range was measurable. */
508
+ total: number | null;
509
+ /** True when at least one day was not measurable - caveat the total when this is set. */
510
+ partial: boolean;
511
+ }
512
+ export interface AnalyticsResponse {
513
+ from: string;
514
+ to: string;
515
+ series: AnalyticsSeries[];
516
+ }
517
+ export interface AnalyticsQuery {
518
+ metrics: ConnectMetric[];
519
+ /** Inclusive `YYYY-MM-DD`, UTC. The range must be shorter than 90 days. */
520
+ from: string;
521
+ to: string;
522
+ }
523
+ /** One event you push into Connect's analytics pipeline. */
524
+ export interface EmitEventInput {
525
+ /**
526
+ * Dot-namespaced and lowercase, e.g. `checkout.completed`. Prefixes Connect
527
+ * emits itself - `api.`, `billing.`, `addon.`, `subscription.`, `connect.` -
528
+ * are rejected, so your events can never inflate a metered number.
529
+ */
530
+ name: string;
531
+ /** Defaults to now. Clamped server-side to within 48 hours. */
532
+ occurredAt?: string | Date;
533
+ /** Attributes the event to the signed-in user and their workspace. */
534
+ sessionToken?: string;
535
+ /** A whole number in the smallest unit of `unit` - paise, bytes, milliseconds. */
536
+ value?: number;
537
+ unit?: string;
538
+ props?: Record<string, unknown>;
539
+ }
540
+ export interface EmitEventsResponse {
541
+ /** False when the call failed outright - see `AnalyticsResource.emit`. */
542
+ delivered: boolean;
543
+ accepted: number;
544
+ attributed: number;
545
+ }
546
+ /**
547
+ * Every event Connect will POST to your webhook endpoint.
548
+ *
549
+ * Additive only - Connect adds event types, never renames one - so a
550
+ * `switch` that does not handle a future type is safe, and
551
+ * `createConnectWebhookHandler` simply ignores anything you have not
552
+ * registered a handler for.
553
+ */
554
+ export type ConnectWebhookEventType = "workspace.deletion_scheduled" | "workspace.deletion_cancelled" | "workspace.deleted" | "subscription.cancelled";
555
+ /**
556
+ * A workspace's deletion has been confirmed and the grace window is running.
557
+ *
558
+ * Access is *already* denied - readiness reports
559
+ * `workspace_pending_deletion` from this moment - so treat this as "stop
560
+ * writing", not "start planning". `purgeAfter` is what makes this event worth
561
+ * having: the customer's data still exists until then, so an export or a
562
+ * wind-down can run on the same clock rather than after everything is gone.
563
+ */
564
+ export interface WorkspaceDeletionScheduledEvent {
565
+ workspaceId: string;
566
+ /** ISO-8601. When Connect destroys the workspace. */
567
+ purgeAfter: string;
568
+ requestedBy: "owner" | "platform_admin";
569
+ graceDays: number;
570
+ }
571
+ /**
572
+ * The deletion was withdrawn and the workspace is live again.
573
+ *
574
+ * **Handle this one.** It is the event integrations forget, and its absence
575
+ * is the worst failure of the set: an application that froze a workspace on
576
+ * `workspace.deletion_scheduled` and never unfreezes leaves a paying
577
+ * customer locked out of something that has no idea anything changed.
578
+ */
579
+ export interface WorkspaceDeletionCancelledEvent {
580
+ workspaceId: string;
581
+ }
582
+ /** The grace window closed and Connect purged the workspace. Purge your own copy. */
583
+ export interface WorkspaceDeletedEvent {
584
+ workspaceId: string;
585
+ /** ISO-8601. */
586
+ purgedAt: string;
587
+ }
588
+ /** A subscription ended. Fires on its own, not only as part of a deletion. */
589
+ export interface SubscriptionCancelledEvent {
590
+ workspaceId: string;
591
+ subscriptionId: string;
592
+ applicationId: string;
593
+ }
594
+ /** Maps each event type to the shape of its `data`. */
595
+ export interface ConnectWebhookEventMap {
596
+ "workspace.deletion_scheduled": WorkspaceDeletionScheduledEvent;
597
+ "workspace.deletion_cancelled": WorkspaceDeletionCancelledEvent;
598
+ "workspace.deleted": WorkspaceDeletedEvent;
599
+ "subscription.cancelled": SubscriptionCancelledEvent;
600
+ }
601
+ /** The envelope, as it arrives on the wire. */
602
+ export interface ConnectWebhookEnvelope<T extends ConnectWebhookEventType = ConnectWebhookEventType> {
603
+ /**
604
+ * Unique per delivery. **Dedupe on this.** Delivery is at-least-once and
605
+ * unordered: a partner that assumes exactly-once, or assumes order, will
606
+ * eventually be wrong.
607
+ */
608
+ id: string;
609
+ type: T;
610
+ /** ISO-8601. */
611
+ createdAt: string;
612
+ /** Bumped only for a breaking payload change - never for a new event type. */
613
+ apiVersion: string;
614
+ data: ConnectWebhookEventMap[T];
615
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmoops/connect-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.7.0",
4
4
  "description": "Official server-side SDK for the CosmoOps Connect platform API - Login with Connect, entitlements, billing and metering.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "commonjs",
@@ -47,7 +47,8 @@
47
47
  "node": ">=18"
48
48
  },
49
49
  "files": [
50
- "dist"
50
+ "dist",
51
+ "CHANGELOG.md"
51
52
  ],
52
53
  "keywords": [
53
54
  "cosmoops",
@@ -82,6 +83,7 @@
82
83
  "@types/react": "^19",
83
84
  "@types/react-dom": "^19",
84
85
  "lucide-react": "^0.545.0",
86
+ "motion": "^13.1.1",
85
87
  "react": "19.2.8",
86
88
  "react-dom": "19.2.8",
87
89
  "storybook": "^10.5.10",
@@ -94,8 +96,9 @@
94
96
  "peerDependencies": {
95
97
  "@heroui/react": ">=3.2.0",
96
98
  "lucide-react": ">=0.400.0",
97
- "react": ">=18",
98
- "react-dom": ">=18"
99
+ "motion": ">=12",
100
+ "react": ">=19",
101
+ "react-dom": ">=19"
99
102
  },
100
103
  "peerDependenciesMeta": {
101
104
  "@heroui/react": {
@@ -104,6 +107,9 @@
104
107
  "lucide-react": {
105
108
  "optional": true
106
109
  },
110
+ "motion": {
111
+ "optional": true
112
+ },
107
113
  "react": {
108
114
  "optional": true
109
115
  },