@cosmoops/connect-sdk 0.6.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 (116) hide show
  1. package/dist/cjs/cli/doctor.js +3 -3
  2. package/dist/cjs/cli/init.js +3 -3
  3. package/dist/cjs/client/components/access-gate.js +3 -3
  4. package/dist/cjs/client/components/account-sessions.js +3 -3
  5. package/dist/cjs/client/components/app-shell.js +2 -2
  6. package/dist/cjs/client/components/apps-grid.js +3 -3
  7. package/dist/cjs/client/components/feature-gate.js +2 -2
  8. package/dist/cjs/client/components/integrations-modal.js +1 -1
  9. package/dist/cjs/client/components/logo.js +3 -3
  10. package/dist/cjs/client/components/plan-pricing.js +1 -1
  11. package/dist/cjs/client/components/plans.js +6 -6
  12. package/dist/cjs/client/components/readiness.js +3 -3
  13. package/dist/cjs/client/components/subscribe-dialog.js +2 -2
  14. package/dist/cjs/client/components/subscription.js +1 -1
  15. package/dist/cjs/client/components/usage-meter.js +1 -1
  16. package/dist/cjs/client/components/user-menu.js +4 -4
  17. package/dist/cjs/client/index.js +1 -1
  18. package/dist/cjs/client/mark.js +1 -1
  19. package/dist/cjs/client/provider.js +7 -7
  20. package/dist/cjs/client/use-checkout.js +3 -3
  21. package/dist/cjs/errors.js +4 -4
  22. package/dist/cjs/helpers.js +1 -1
  23. package/dist/cjs/index.js +1 -1
  24. package/dist/cjs/next/index.js +2 -2
  25. package/dist/cjs/server/client.js +15 -15
  26. package/dist/cjs/server/handler.js +13 -13
  27. package/dist/cjs/server/http.js +1 -1
  28. package/dist/cjs/server/resources/access.js +3 -3
  29. package/dist/cjs/server/resources/ai.js +1 -1
  30. package/dist/cjs/server/resources/analytics.js +2 -2
  31. package/dist/cjs/server/resources/apps.js +4 -4
  32. package/dist/cjs/server/resources/billing.js +5 -5
  33. package/dist/cjs/server/resources/drive.js +4 -4
  34. package/dist/cjs/server/resources/entitlements.js +7 -7
  35. package/dist/cjs/server/resources/identity.js +4 -4
  36. package/dist/cjs/server/resources/integrations.js +13 -13
  37. package/dist/cjs/server/resources/logs.js +3 -3
  38. package/dist/cjs/server/resources/sessions.js +6 -6
  39. package/dist/cjs/server/webhooks.js +4 -4
  40. package/dist/cjs/types.js +1 -1
  41. package/dist/esm/cli/doctor.js +3 -3
  42. package/dist/esm/cli/init.js +3 -3
  43. package/dist/esm/client/components/access-gate.js +3 -3
  44. package/dist/esm/client/components/account-sessions.js +3 -3
  45. package/dist/esm/client/components/app-shell.js +2 -2
  46. package/dist/esm/client/components/apps-grid.js +3 -3
  47. package/dist/esm/client/components/feature-gate.js +2 -2
  48. package/dist/esm/client/components/integrations-modal.js +1 -1
  49. package/dist/esm/client/components/logo.js +3 -3
  50. package/dist/esm/client/components/plan-pricing.js +1 -1
  51. package/dist/esm/client/components/plans.js +6 -6
  52. package/dist/esm/client/components/readiness.js +3 -3
  53. package/dist/esm/client/components/subscribe-dialog.js +2 -2
  54. package/dist/esm/client/components/subscription.js +1 -1
  55. package/dist/esm/client/components/usage-meter.js +1 -1
  56. package/dist/esm/client/components/user-menu.js +4 -4
  57. package/dist/esm/client/index.js +1 -1
  58. package/dist/esm/client/mark.js +1 -1
  59. package/dist/esm/client/provider.js +7 -7
  60. package/dist/esm/client/use-checkout.js +3 -3
  61. package/dist/esm/errors.js +4 -4
  62. package/dist/esm/helpers.js +1 -1
  63. package/dist/esm/index.js +1 -1
  64. package/dist/esm/next/index.js +2 -2
  65. package/dist/esm/server/client.js +15 -15
  66. package/dist/esm/server/handler.js +13 -13
  67. package/dist/esm/server/http.js +1 -1
  68. package/dist/esm/server/resources/access.js +3 -3
  69. package/dist/esm/server/resources/ai.js +1 -1
  70. package/dist/esm/server/resources/analytics.js +2 -2
  71. package/dist/esm/server/resources/apps.js +4 -4
  72. package/dist/esm/server/resources/billing.js +5 -5
  73. package/dist/esm/server/resources/drive.js +4 -4
  74. package/dist/esm/server/resources/entitlements.js +7 -7
  75. package/dist/esm/server/resources/identity.js +4 -4
  76. package/dist/esm/server/resources/integrations.js +13 -13
  77. package/dist/esm/server/resources/logs.js +3 -3
  78. package/dist/esm/server/resources/sessions.js +6 -6
  79. package/dist/esm/server/webhooks.js +4 -4
  80. package/dist/esm/types.js +1 -1
  81. package/dist/types/client/components/access-gate.d.ts +1 -1
  82. package/dist/types/client/components/account-sessions.d.ts +1 -1
  83. package/dist/types/client/components/app-shell.d.ts +4 -4
  84. package/dist/types/client/components/apps-grid.d.ts +1 -1
  85. package/dist/types/client/components/feature-gate.d.ts +1 -1
  86. package/dist/types/client/components/integrations-modal.d.ts +1 -1
  87. package/dist/types/client/components/logo.d.ts +5 -5
  88. package/dist/types/client/components/plan-pricing.d.ts +2 -2
  89. package/dist/types/client/components/readiness.d.ts +2 -2
  90. package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
  91. package/dist/types/client/components/usage-meter.d.ts +1 -1
  92. package/dist/types/client/components/user-menu.d.ts +2 -2
  93. package/dist/types/client/index.d.ts +1 -1
  94. package/dist/types/client/mark.d.ts +1 -1
  95. package/dist/types/client/provider.d.ts +9 -9
  96. package/dist/types/client/use-checkout.d.ts +3 -3
  97. package/dist/types/errors.d.ts +4 -4
  98. package/dist/types/helpers.d.ts +1 -1
  99. package/dist/types/index.d.ts +1 -1
  100. package/dist/types/next/index.d.ts +1 -1
  101. package/dist/types/server/client.d.ts +13 -13
  102. package/dist/types/server/handler.d.ts +2 -2
  103. package/dist/types/server/resources/access.d.ts +3 -3
  104. package/dist/types/server/resources/ai.d.ts +2 -2
  105. package/dist/types/server/resources/analytics.d.ts +2 -2
  106. package/dist/types/server/resources/apps.d.ts +4 -4
  107. package/dist/types/server/resources/billing.d.ts +4 -4
  108. package/dist/types/server/resources/drive.d.ts +4 -4
  109. package/dist/types/server/resources/entitlements.d.ts +4 -4
  110. package/dist/types/server/resources/identity.d.ts +2 -2
  111. package/dist/types/server/resources/integrations.d.ts +9 -9
  112. package/dist/types/server/resources/logs.d.ts +3 -3
  113. package/dist/types/server/resources/sessions.d.ts +5 -5
  114. package/dist/types/server/webhooks.d.ts +4 -4
  115. package/dist/types/types.d.ts +61 -61
  116. package/package.json +1 -1
@@ -41,7 +41,7 @@ function ordered(sessions) {
41
41
  }
42
42
  /**
43
43
  * One row's revoke action, confirmed before it fires - revoking a session
44
- * ends every partner-service sign-in from that same browser, not just this
44
+ * ends every partner-application sign-in from that same browser, not just this
45
45
  * one. Closes on confirm, not on response - the same convention every
46
46
  * destructive confirmation in this codebase follows - so the dialog itself
47
47
  * needs no async/pending state of its own; the row simply disappears once
@@ -55,11 +55,11 @@ function ordered(sessions) {
55
55
  */
56
56
  function RevokeRow({ session, onRevoke }) {
57
57
  const label = deviceLabel(session);
58
- return (_jsxs(AlertDialog, { children: [_jsx(Button, { isIconOnly: true, size: "sm", variant: "tertiary", className: "shrink-0 text-muted hover:text-danger", "aria-label": `Sign out ${label}`, children: _jsx(LogOut, { className: "size-4" }) }), _jsx(AlertDialog.Backdrop, { children: _jsx(AlertDialog.Container, { children: _jsxs(AlertDialog.Dialog, { className: "sm:max-w-100", children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger" }), _jsx(AlertDialog.Heading, { children: "Sign out this device?" })] }), _jsx(AlertDialog.Body, { children: _jsxs("p", { className: "text-sm text-muted", children: ["This ends every sign-in from ", label, ", on every service, not just this one."] }) }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "secondary", className: "text-xs", children: "Cancel" }), _jsx(Button, { slot: "close", variant: "danger", className: "text-xs", onPress: onRevoke, children: "Sign out" })] })] }) }) })] }));
58
+ return (_jsxs(AlertDialog, { children: [_jsx(Button, { isIconOnly: true, size: "sm", variant: "tertiary", className: "shrink-0 text-muted hover:text-danger", "aria-label": `Sign out ${label}`, children: _jsx(LogOut, { className: "size-4" }) }), _jsx(AlertDialog.Backdrop, { children: _jsx(AlertDialog.Container, { children: _jsxs(AlertDialog.Dialog, { className: "sm:max-w-100", children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger" }), _jsx(AlertDialog.Heading, { children: "Sign out this device?" })] }), _jsx(AlertDialog.Body, { children: _jsxs("p", { className: "text-sm text-muted", children: ["This ends every sign-in from ", label, ", on every application, not just this one."] }) }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "secondary", className: "text-xs", children: "Cancel" }), _jsx(Button, { slot: "close", variant: "danger", className: "text-xs", onPress: onRevoke, children: "Sign out" })] })] }) }) })] }));
59
59
  }
60
60
  /**
61
61
  * Every device signed into this Connect account - not scoped to this
62
- * service, see `ConnectUserSession`'s doc comment. Owns the one
62
+ * application, see `ConnectUserSession`'s doc comment. Owns the one
63
63
  * `useConnectSessions()` call for this modal; every revoke action here
64
64
  * mutates through it and re-reads the list itself, since nothing else
65
65
  * invalidates it automatically - see `mutateResource`'s doc comment.
@@ -64,12 +64,12 @@ function BrandLink({ name, icon, homeHref, collapsed, renderLink, }) {
64
64
  });
65
65
  }
66
66
  /**
67
- * The application frame every CosmoOps service platform runs inside: a
67
+ * The application frame every CosmoOps application platform runs inside: a
68
68
  * collapsible sidebar, a top bar carrying the app launcher and the account
69
69
  * menu, and your pages in the middle.
70
70
  *
71
71
  * This is the piece each partner was otherwise writing by hand, and writing
72
- * slightly differently - which is how a family of services stops looking like
72
+ * slightly differently - which is how a family of applications stops looking like
73
73
  * one product. Everything that should be identical across platforms (the
74
74
  * lockup, the rail geometry, the active-route treatment, the launcher, the
75
75
  * account menu, the access gate) lives here; everything that genuinely
@@ -19,7 +19,7 @@ function AppTile({ app }) {
19
19
  }
20
20
  /**
21
21
  * The Google-style app launcher: a grid icon in your top bar that opens a
22
- * modal of every Connect service this organization can actually open.
22
+ * modal of every Connect application this workspace can actually open.
23
23
  *
24
24
  * Only launchable apps appear, so no tile is a dead end - a paused
25
25
  * subscription still shows, badged, because a dunning cycle should not make a
@@ -36,9 +36,9 @@ export function ConnectAppsGrid({ className, label = "Switch app" }) {
36
36
  if (sessionLoading || !session?.user)
37
37
  return null;
38
38
  const apps = data?.apps ?? [];
39
- return (_jsx(MotionProvider, { children: _jsxs(Modal, { children: [_jsx(Button, { isIconOnly: true, variant: "primary", "aria-label": label, className: className, children: _jsx(LayoutGrid, { className: "size-5" }) }), _jsx(Modal.Backdrop, { children: _jsx(Modal.Container, { children: _jsxs(Modal.Dialog, { className: "sm:max-w-md", children: [_jsx(Modal.CloseTrigger, {}), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: "Your apps" }) }), _jsxs(Modal.Body, { children: [isLoading && (_jsx("div", { className: "grid grid-cols-3 gap-2", children: Array.from({ length: 6 }, (_, index) => (_jsxs("div", { className: "flex flex-col items-center gap-2 p-3", children: [_jsx(Skeleton, { className: "size-12 rounded-xl" }), _jsx(Skeleton, { className: "h-3 w-14" })] }, index))) })), !isLoading && error && (_jsx("p", { className: "py-6 text-center text-sm text-danger", children: "Could not load your apps." })), !isLoading && !error && apps.length === 0 && (_jsx("p", { className: "py-6 text-center text-sm text-muted", children: "No other apps yet. Anything this workspace subscribes to shows up here." })), !isLoading && !error && apps.length > 0 && (_jsx(m.div, { className: "grid grid-cols-3 gap-2", variants: { show: { transition: { staggerChildren: 0.04 } } }, initial: "hidden", animate: "show", children: apps.map((app) => (_jsx(m.div, { variants: { hidden: { opacity: 0, y: 8 }, show: { opacity: 1, y: 0, transition: ENTER } }, children: _jsx(AppTile, { app: app }) }, app.serviceId))) }))] }), _jsx(Modal.Footer, { children: _jsx(ConnectBrowseAllLink, {}) })] }) }) })] }) }));
39
+ return (_jsx(MotionProvider, { children: _jsxs(Modal, { children: [_jsx(Button, { isIconOnly: true, variant: "primary", "aria-label": label, className: className, children: _jsx(LayoutGrid, { className: "size-5" }) }), _jsx(Modal.Backdrop, { children: _jsx(Modal.Container, { children: _jsxs(Modal.Dialog, { className: "sm:max-w-md", children: [_jsx(Modal.CloseTrigger, {}), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: "Your apps" }) }), _jsxs(Modal.Body, { children: [isLoading && (_jsx("div", { className: "grid grid-cols-3 gap-2", children: Array.from({ length: 6 }, (_, index) => (_jsxs("div", { className: "flex flex-col items-center gap-2 p-3", children: [_jsx(Skeleton, { className: "size-12 rounded-xl" }), _jsx(Skeleton, { className: "h-3 w-14" })] }, index))) })), !isLoading && error && (_jsx("p", { className: "py-6 text-center text-sm text-danger", children: "Could not load your apps." })), !isLoading && !error && apps.length === 0 && (_jsx("p", { className: "py-6 text-center text-sm text-muted", children: "No other apps yet. Anything this workspace subscribes to shows up here." })), !isLoading && !error && apps.length > 0 && (_jsx(m.div, { className: "grid grid-cols-3 gap-2", variants: { show: { transition: { staggerChildren: 0.04 } } }, initial: "hidden", animate: "show", children: apps.map((app) => (_jsx(m.div, { variants: { hidden: { opacity: 0, y: 8 }, show: { opacity: 1, y: 0, transition: ENTER } }, children: _jsx(AppTile, { app: app }) }, app.applicationId))) }))] }), _jsx(Modal.Footer, { children: _jsx(ConnectBrowseAllLink, {}) })] }) }) })] }) }));
40
40
  }
41
41
  function ConnectBrowseAllLink() {
42
42
  const { appUrl } = useConnect();
43
- return (_jsxs(Button, { variant: "tertiary", className: "w-full", onPress: () => window.open(`${appUrl}/services`, "_blank", "noopener,noreferrer"), children: ["Browse all services", _jsx(ExternalLink, { className: "size-3.5 text-muted" })] }));
43
+ return (_jsxs(Button, { variant: "tertiary", className: "w-full", onPress: () => window.open(`${appUrl}/applications`, "_blank", "noopener,noreferrer"), children: ["Browse all applications", _jsx(ExternalLink, { className: "size-3.5 text-muted" })] }));
44
44
  }
@@ -38,7 +38,7 @@ export function useConnectFeature(feature) {
38
38
  *
39
39
  * Like every gate in this package, it is a **UX gate, not a security
40
40
  * boundary**: the entitlement is read through your own origin and the browser
41
- * can ignore it. Check `client.entitlements.hasFeature(orgId, feature)` on the
41
+ * can ignore it. Check `client.entitlements.hasFeature(workspaceId, feature)` on the
42
42
  * server before doing the thing the feature unlocks.
43
43
  *
44
44
  * Renders `loading` - not `fallback` - while the answer is unknown, so a paying
@@ -53,5 +53,5 @@ export function ConnectFeatureGate({ feature, children, fallback, loading = null
53
53
  return _jsx(_Fragment, { children: children });
54
54
  if (fallback !== undefined)
55
55
  return _jsx(_Fragment, { children: fallback });
56
- return (_jsx(ConnectNoSubscriptionCard, { plansHref: plansHref, title: title ?? "Not included in your plan", description: description ?? "This part of the service is on a higher plan. Compare plans to see what unlocks it.", className: className }));
56
+ return (_jsx(ConnectNoSubscriptionCard, { plansHref: plansHref, title: title ?? "Not included in your plan", description: description ?? "This part of the application is on a higher plan. Compare plans to see what unlocks it.", className: className }));
57
57
  }
@@ -42,7 +42,7 @@ function ToolkitTile({ toolkit, isPending, onConnect, onDisconnect }) {
42
42
  _jsx("img", { src: toolkit.logoUrl, alt: "", className: "size-full object-cover" })) : (_jsx(Puzzle, { className: "size-6 text-muted", "aria-hidden": "true" })), toolkit.status === "failed" && (_jsx("span", { className: "absolute -right-0.5 -top-0.5 flex size-4 items-center justify-center rounded-full bg-danger text-danger-foreground", children: _jsx(AlertCircle, { className: "size-3", "aria-hidden": "true" }) }))] }), _jsx("span", { className: "line-clamp-2 text-center text-xs font-medium text-foreground", children: toolkit.name }), _jsx(Chip, { size: "sm", variant: "soft", color: STATUS_COLOR[toolkit.status], children: STATUS_LABEL[toolkit.status] }), _jsxs("div", { className: "flex w-full flex-col gap-1.5 pt-1", children: [CAN_CONNECT.has(toolkit.status) && (_jsx(Button, { size: "sm", variant: "secondary", className: "w-full text-xs", isPending: isPending, isDisabled: isPending, onPress: onConnect, children: "Connect" })), toolkit.status === "active" && (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "secondary", className: "w-full text-xs", isPending: isPending, isDisabled: isPending, onPress: onConnect, children: "Reconnect" }), _jsxs(AlertDialog, { isOpen: confirmingDisconnect, onOpenChange: setConfirmingDisconnect, children: [_jsx(Button, { size: "sm", variant: "tertiary", className: "w-full text-xs text-danger", isDisabled: isPending, children: "Disconnect" }), _jsx(AlertDialog.Backdrop, { children: _jsx(AlertDialog.Container, { children: _jsxs(AlertDialog.Dialog, { className: "sm:max-w-100", children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger" }), _jsxs(AlertDialog.Heading, { children: ["Disconnect ", toolkit.name, "?"] })] }), _jsx(AlertDialog.Body, { children: _jsx("p", { className: "text-sm text-muted", children: "Every member loses this connection immediately - it can be reconnected later." }) }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "secondary", className: "text-xs", children: "Cancel" }), _jsx(Button, { slot: "close", variant: "danger", className: "text-xs", onPress: onDisconnect, children: "Disconnect" })] })] }) }) })] })] })), toolkit.status === "pending" && (_jsx(Button, { size: "sm", variant: "tertiary", className: "w-full text-xs text-danger", isDisabled: isPending, onPress: onDisconnect, children: "Cancel" }))] })] }));
43
43
  }
44
44
  /**
45
- * A grid of every Composio-hosted toolkit this organization can connect -
45
+ * A grid of every Composio-hosted toolkit this workspace can connect -
46
46
  * Google Calendar, Slack, Twitter/X, whatever a platform admin enabled in
47
47
  * Connect's own Console. Each tile carries its own connect/reconnect/
48
48
  * disconnect action and its own pending state, independent of every other
@@ -2,10 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { ConnectMark } from "../mark.js";
4
4
  /**
5
- * The shared platform lockup: a service's own glyph on the CosmoOps badge,
6
- * `cosmo·ops` beside it, and the service name underneath.
5
+ * The shared platform lockup: an application's own glyph on the CosmoOps badge,
6
+ * `cosmo·ops` beside it, and the application name underneath.
7
7
  *
8
- * This is what makes a family of service platforms look like one product. Each
8
+ * This is what makes a family of application platforms look like one product. Each
9
9
  * platform passes only what differs - its `name` and its `icon` - and inherits
10
10
  * the mark geometry, the wordmark treatment, the separator, and the accent from
11
11
  * one place. Change the lockup here and every platform follows.
@@ -4,7 +4,7 @@
4
4
  * an upgrade while the card behind it said downgrade would be worse than
5
5
  * either label being wrong on its own.
6
6
  *
7
- * Mirrors `packages/data/src/services/catalog.ts` and
7
+ * Mirrors `packages/data/src/applications/catalog.ts` and
8
8
  * `packages/data/src/payments/plan-change.ts`, which are the copies Connect's
9
9
  * own UI uses and which decide which use-case actually runs. The duplication
10
10
  * is deliberate and load-bearing: this package carries no dependency on
@@ -44,7 +44,7 @@ export function ConnectPlans({ planIds, hideCoupon = false, className }) {
44
44
  /** The plan under review in the confirmation dialog, or `null` when it is closed. */
45
45
  const [pending, setPending] = useState(null);
46
46
  const subscription = entitlements?.subscription ?? null;
47
- const serviceId = subscription?.serviceId ?? null;
47
+ const applicationId = subscription?.applicationId ?? null;
48
48
  const allPlans = useMemo(() => {
49
49
  const plans = catalog?.plans ?? [];
50
50
  if (!planIds)
@@ -82,12 +82,12 @@ export function ConnectPlans({ planIds, hideCoupon = false, className }) {
82
82
  * then would misreport a completed checkout as an abandoned one.
83
83
  */
84
84
  function startCheckout(plan) {
85
- if (!serviceId)
85
+ if (!applicationId)
86
86
  return;
87
87
  checkout.start({
88
88
  url: buildCheckoutUrl({
89
89
  appUrl,
90
- serviceId,
90
+ applicationId,
91
91
  planId: plan.id,
92
92
  subscriptionId: subscription?.subscription?.id ?? null,
93
93
  coupon,
@@ -116,7 +116,7 @@ export function ConnectPlans({ planIds, hideCoupon = false, className }) {
116
116
  return null;
117
117
  const action = resolveAction(plan, subscription);
118
118
  // "Current" belongs to the tier, not just the exact price point: an
119
- // org on Growth annual looking at monthly pricing is still on the
119
+ // workspace on Growth annual looking at monthly pricing is still on the
120
120
  // Growth tier, and marking only the row it literally subscribes to
121
121
  // would leave its own card unmarked half the time.
122
122
  const isCurrentTier = subscription?.plan != null &&
@@ -134,8 +134,8 @@ export function ConnectPlans({ planIds, hideCoupon = false, className }) {
134
134
  ? "primary"
135
135
  : "secondary",
136
136
  // Disabled while a hand-off is in flight, not just on the
137
- // card that started it: the org has one subscription per
138
- // service, so a second checkout opened against a different
137
+ // card that started it: the workspace has one subscription per
138
+ // application, so a second checkout opened against a different
139
139
  // plan would race the first and one of them would be
140
140
  // rejected on arrival.
141
141
  isDisabled: isCurrent || checkout.status === "waiting", onPress: () => setPending({ plan, action }), children: [ACTION_LABEL[action], !isCurrent && _jsx(ExternalLink, { className: "size-3.5" })] }) })] }) }, tier.planGroup));
@@ -29,7 +29,7 @@ function actionLabel(blocker) {
29
29
  return ACTION_LABELS[blocker.code] ?? "Resolve on Connect";
30
30
  }
31
31
  /**
32
- * Every gate between this workspace and your service, with the way out of each.
32
+ * Every gate between this workspace and your application, with the way out of each.
33
33
  *
34
34
  * This is the component that keeps a blocked customer from staring at a broken
35
35
  * app. `getReadiness` resolves subscription state, KYC/KYB, a chargeable
@@ -37,7 +37,7 @@ function actionLabel(blocker) {
37
37
  * `resolveUrl` into the exact Connect screen that fixes it** - so being blocked
38
38
  * comes with somewhere to go rather than a refusal.
39
39
  *
40
- * Render it high on any page your service gates. It draws nothing at all when
40
+ * Render it high on any page your application gates. It draws nothing at all when
41
41
  * the workspace is ready, so it is safe to leave mounted permanently.
42
42
  *
43
43
  * Two deliberate refusals:
@@ -72,7 +72,7 @@ function BlockerRow({ blocker }) {
72
72
  return (_jsxs("div", { className: `flex flex-wrap items-center justify-between gap-3 rounded-lg px-3 py-2 text-sm ${inProgress || !isBlocking ? "bg-surface text-muted" : "bg-danger-soft text-danger"}`, children: [_jsxs("span", { className: "flex items-center gap-2", children: [inProgress || !isBlocking ? (_jsx(Info, { className: "size-4 shrink-0", "aria-hidden": "true" })) : (_jsx(AlertTriangle, { className: "size-4 shrink-0", "aria-hidden": "true" })), blocker.message] }), blocker.resolveUrl && !inProgress && (_jsxs(Button, { variant: "secondary", onPress: () => window.open(blocker.resolveUrl, "_blank", "noopener,noreferrer"), children: [actionLabel(blocker), _jsx(ExternalLink, { className: "size-3.5" })] }))] }));
73
73
  }
74
74
  function ReadyRow({ className }) {
75
- return (_jsx("p", { className: `text-sm text-muted ${className ?? ""}`, children: "This workspace is cleared to use every part of the service." }));
75
+ return (_jsx("p", { className: `text-sm text-muted ${className ?? ""}`, children: "This workspace is cleared to use every part of the application." }));
76
76
  }
77
77
  /**
78
78
  * Renders `children` only once the workspace clears every blocking gate.
@@ -34,7 +34,7 @@ const HEADING = {
34
34
  * The authoritative price is computed by Connect against the real cart:
35
35
  * proration is priced against the actual cycle, a coupon is validated
36
36
  * against the plan it is being applied to, trial eligibility depends on
37
- * whether this organization has ever subscribed to this service before, and
37
+ * whether this workspace has ever subscribed to this application before, and
38
38
  * an accumulated credit is deducted. None of that is knowable from the
39
39
  * partner's origin, so this component states the list price and says where
40
40
  * the final figure comes from rather than quietly guessing at one.
@@ -47,7 +47,7 @@ export function ConnectSubscribeDialog({ plan, action, current, coupon, onClose,
47
47
  // member and the one most in need of it: the two prices differ by an order
48
48
  // of magnitude, and showing only the new one reads as a price rise.
49
49
  const isChange = action === "upgrade" || action === "downgrade" || isIntervalSwitch;
50
- return (_jsx(Modal.Backdrop, { isOpen: plan !== null, onOpenChange: (open) => !open && onClose(), children: _jsx(Modal.Container, { size: "sm", children: _jsxs(Modal.Dialog, { children: [_jsx(Modal.CloseTrigger, { onPress: onClose }), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: HEADING[action] }) }), plan && (_jsxs(_Fragment, { children: [_jsxs(Modal.Body, { className: "flex flex-col gap-4", children: [isChange && currentPlan ? (_jsxs("div", { className: "flex items-center gap-3 text-sm", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-muted", children: currentPlan.name }), _jsxs("p", { className: "text-xs text-muted", children: [formatPrice(currentPlan.price), "/", currentPlan.billingInterval === "annual" ? "yr" : "mo"] })] }), _jsx(ArrowRight, { className: "size-4 shrink-0 text-muted", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate font-medium text-foreground", children: plan.name }), _jsxs("p", { className: "text-xs text-muted", children: [formatPrice(plan.price), "/", plan.billingInterval === "annual" ? "yr" : "mo"] })] })] })) : (_jsxs("div", { children: [_jsx("p", { className: "font-medium text-foreground", children: plan.name }), plan.description && _jsx("p", { className: "text-xs text-muted", children: plan.description })] })), _jsxs("div", { className: "flex flex-col gap-1 border-t border-separator pt-3 text-sm", children: [_jsxs("div", { className: "flex justify-between text-muted", children: [_jsx("span", { children: plan.name }), _jsx("span", { children: formatPrice(plan.price) })] }), _jsxs("div", { className: "flex justify-between text-muted", children: [_jsxs("span", { children: ["GST (", plan.gstRate, "%)"] }), _jsx("span", { children: formatPrice(withGst(plan.price, plan.gstRate) - plan.price) })] }), _jsxs("div", { className: "flex justify-between border-t border-separator pt-1 font-semibold text-foreground", children: [_jsxs("span", { children: ["Per ", cadenceOf(plan)] }), _jsx("span", { children: formatPrice(withGst(plan.price, plan.gstRate)) })] }), plan.billingInterval === "annual" && (_jsxs("p", { className: "text-xs text-muted", children: ["Works out to ", formatPrice(monthlyOf(withGst(plan.price, plan.gstRate), "annual")), " a month, billed yearly."] }))] }), plan.trialDays ? (_jsxs("p", { className: "text-xs text-accent", children: [plan.trialDays, "-day free trial, if this workspace has not subscribed to this service before."] })) : null, coupon?.trim() ? (_jsxs("p", { className: "text-xs text-muted", children: ["Coupon ", _jsx("span", { className: "font-mono text-foreground", children: coupon.trim() }), " is carried over and validated on Connect."] })) : null, _jsxs("div", { className: "flex gap-2 rounded-lg bg-surface p-3 text-xs text-muted", children: [_jsx(Info, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": "true" }), _jsxs("div", { className: "flex flex-col gap-1", children: [action === "subscribe" && (_jsx("p", { children: "Payment is completed on Connect, where your card or UPI mandate is set up and the tax invoice is issued. This page updates by itself once it is done." })), action === "upgrade" && (_jsxs("p", { children: ["Connect prices the difference for the days left in your current cycle and collects just that amount now. From the next cycle you are billed the ", plan.name, " rate."] })), action === "downgrade" && (_jsx("p", { children: "You keep what you have paid for. Connect works out the unused part of this cycle and applies it as credit or a refund, depending on how this service is configured." })), isIntervalSwitch && (
50
+ return (_jsx(Modal.Backdrop, { isOpen: plan !== null, onOpenChange: (open) => !open && onClose(), children: _jsx(Modal.Container, { size: "sm", children: _jsxs(Modal.Dialog, { children: [_jsx(Modal.CloseTrigger, { onPress: onClose }), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: HEADING[action] }) }), plan && (_jsxs(_Fragment, { children: [_jsxs(Modal.Body, { className: "flex flex-col gap-4", children: [isChange && currentPlan ? (_jsxs("div", { className: "flex items-center gap-3 text-sm", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-muted", children: currentPlan.name }), _jsxs("p", { className: "text-xs text-muted", children: [formatPrice(currentPlan.price), "/", currentPlan.billingInterval === "annual" ? "yr" : "mo"] })] }), _jsx(ArrowRight, { className: "size-4 shrink-0 text-muted", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate font-medium text-foreground", children: plan.name }), _jsxs("p", { className: "text-xs text-muted", children: [formatPrice(plan.price), "/", plan.billingInterval === "annual" ? "yr" : "mo"] })] })] })) : (_jsxs("div", { children: [_jsx("p", { className: "font-medium text-foreground", children: plan.name }), plan.description && _jsx("p", { className: "text-xs text-muted", children: plan.description })] })), _jsxs("div", { className: "flex flex-col gap-1 border-t border-separator pt-3 text-sm", children: [_jsxs("div", { className: "flex justify-between text-muted", children: [_jsx("span", { children: plan.name }), _jsx("span", { children: formatPrice(plan.price) })] }), _jsxs("div", { className: "flex justify-between text-muted", children: [_jsxs("span", { children: ["GST (", plan.gstRate, "%)"] }), _jsx("span", { children: formatPrice(withGst(plan.price, plan.gstRate) - plan.price) })] }), _jsxs("div", { className: "flex justify-between border-t border-separator pt-1 font-semibold text-foreground", children: [_jsxs("span", { children: ["Per ", cadenceOf(plan)] }), _jsx("span", { children: formatPrice(withGst(plan.price, plan.gstRate)) })] }), plan.billingInterval === "annual" && (_jsxs("p", { className: "text-xs text-muted", children: ["Works out to ", formatPrice(monthlyOf(withGst(plan.price, plan.gstRate), "annual")), " a month, billed yearly."] }))] }), plan.trialDays ? (_jsxs("p", { className: "text-xs text-accent", children: [plan.trialDays, "-day free trial, if this workspace has not subscribed to this application before."] })) : null, coupon?.trim() ? (_jsxs("p", { className: "text-xs text-muted", children: ["Coupon ", _jsx("span", { className: "font-mono text-foreground", children: coupon.trim() }), " is carried over and validated on Connect."] })) : null, _jsxs("div", { className: "flex gap-2 rounded-lg bg-surface p-3 text-xs text-muted", children: [_jsx(Info, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": "true" }), _jsxs("div", { className: "flex flex-col gap-1", children: [action === "subscribe" && (_jsx("p", { children: "Payment is completed on Connect, where your card or UPI mandate is set up and the tax invoice is issued. This page updates by itself once it is done." })), action === "upgrade" && (_jsxs("p", { children: ["Connect prices the difference for the days left in your current cycle and collects just that amount now. From the next cycle you are billed the ", plan.name, " rate."] })), action === "downgrade" && (_jsx("p", { children: "You keep what you have paid for. Connect works out the unused part of this cycle and applies it as credit or a refund, depending on how this application is configured." })), isIntervalSwitch && (
51
51
  // Not a proration. The cycle you are on ends, so this is
52
52
  // the one action where the amount collected can exceed a
53
53
  // single cycle's list price - or be nothing at all, with
@@ -55,7 +55,7 @@ function useSubscriptionState() {
55
55
  * Rendered on its own it is just a card; `ConnectSubscriptionGate` is the usual
56
56
  * way in, since it picks this only when there is genuinely nothing to show.
57
57
  */
58
- export function ConnectNoSubscriptionCard({ plansHref = DEFAULT_PLANS_HREF, title = "You're not on a plan yet", description = "Pick a plan to unlock the full service. You can change or cancel it whenever you like.", className, }) {
58
+ export function ConnectNoSubscriptionCard({ plansHref = DEFAULT_PLANS_HREF, title = "You're not on a plan yet", description = "Pick a plan to unlock the full application. You can change or cancel it whenever you like.", className, }) {
59
59
  return (_jsxs(Card, { className: className, children: [_jsxs(Card.Header, { children: [_jsx(Card.Title, { children: title }), _jsx(Card.Description, { children: description })] }), _jsx(Card.Footer, { children: _jsxs(ConnectLinkButton, { href: plansHref, variant: "primary", children: ["See plans", _jsx(ArrowRight, { className: "size-3.5" })] }) })] }));
60
60
  }
61
61
  /**
@@ -16,7 +16,7 @@ function formatDate(iso) {
16
16
  *
17
17
  * Reads the balance Connect actually debits, so the number here and the number
18
18
  * `consumeAddon` enforces cannot disagree. Before the `addons:read` endpoint
19
- * existed this component was impossible to write honestly: a service could
19
+ * existed this component was impossible to write honestly: an application could
20
20
  * spend an allowance down on every request and the only thing the API exposed
21
21
  * was the list of add-on *ids* on the subscription.
22
22
  *
@@ -97,7 +97,7 @@ function DestinationTile({ icon, label, url, }) {
97
97
  * in place, which is why it sits alone in the footer rather than as a fourth
98
98
  * item in the same list as three navigations.
99
99
  *
100
- * The session list is account-wide, not scoped to this service - see
100
+ * The session list is account-wide, not scoped to this application - see
101
101
  * `ConnectUserSession`'s doc comment in `types.ts`. Appearance only renders
102
102
  * when both `theme` and `onThemeChange` are supplied.
103
103
  *
@@ -122,13 +122,13 @@ export function ConnectUserMenu({ compact = false, onSignOut, className, theme,
122
122
  if (!user)
123
123
  return null;
124
124
  const label = user.displayName ?? user.email ?? "Account";
125
- const role = session?.serviceRole?.role;
125
+ const role = session?.applicationRole?.role;
126
126
  const planChip = subscriptionChip(session?.subscription ?? null);
127
127
  return (_jsxs(Modal, { children: [_jsxs(Button, { variant: "tertiary", "aria-label": `Account: ${label}`,
128
128
  // `pl-1` against the default right padding is optical, not sloppy: a
129
129
  // circular avatar needs less inset than a text label to look evenly
130
130
  // seated in the button.
131
- className: `gap-2 pl-1 ${className ?? ""}`, children: [_jsx(UserAvatar, { user: user, size: "sm" }), !compact && _jsx("span", { className: "text-sm font-medium text-foreground", children: label })] }), _jsx(Modal.Backdrop, { children: _jsx(Modal.Container, { size: "md", scroll: "inside", children: _jsxs(Modal.Dialog, { children: [_jsx(Modal.CloseTrigger, {}), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: "Account" }) }), _jsxs(Modal.Body, { className: "flex flex-col gap-5", children: [_jsxs("div", { className: `flex items-start gap-3 rounded-xl border border-border ${PANEL_FILL} p-4`, children: [_jsx(UserAvatar, { user: user, size: "lg" }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("p", { className: "truncate text-sm font-semibold text-foreground", children: label }), user.email && _jsx("p", { className: "truncate text-xs text-muted", children: user.email }), _jsx("p", { className: "truncate text-xs text-muted", children: user.organizationName }), (role || planChip || !user.emailVerified) && (_jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: [role && (_jsx(Chip, { size: "sm", variant: "soft", color: "accent", children: humanizeRole(role) })), planChip, !user.emailVerified && (_jsx(Chip, { size: "sm", variant: "soft", color: "warning", children: "Email unverified" }))] }))] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-2", children: [_jsx(DestinationTile, { icon: _jsx(UserRound, { className: ICON, "aria-hidden": "true" }), label: "Profile", url: `${appUrl}/profile` }), _jsx(DestinationTile, { icon: _jsx(CreditCard, { className: ICON, "aria-hidden": "true" }), label: "Billing", url: `${appUrl}/billing` }), _jsx(DestinationTile, { icon: _jsx(ConnectMark, { className: ICON }), label: "Connect", url: appUrl })] }), theme && onThemeChange && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Appearance" }), _jsx(ToggleButtonGroup, { fullWidth: true, "aria-label": "Theme", selectionMode: "single", disallowEmptySelection: true, selectedKeys: [theme], onSelectionChange: (keys) => {
131
+ className: `gap-2 pl-1 ${className ?? ""}`, children: [_jsx(UserAvatar, { user: user, size: "sm" }), !compact && _jsx("span", { className: "text-sm font-medium text-foreground", children: label })] }), _jsx(Modal.Backdrop, { children: _jsx(Modal.Container, { size: "md", scroll: "inside", children: _jsxs(Modal.Dialog, { children: [_jsx(Modal.CloseTrigger, {}), _jsx(Modal.Header, { children: _jsx(Modal.Heading, { children: "Account" }) }), _jsxs(Modal.Body, { className: "flex flex-col gap-5", children: [_jsxs("div", { className: `flex items-start gap-3 rounded-xl border border-border ${PANEL_FILL} p-4`, children: [_jsx(UserAvatar, { user: user, size: "lg" }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("p", { className: "truncate text-sm font-semibold text-foreground", children: label }), user.email && _jsx("p", { className: "truncate text-xs text-muted", children: user.email }), _jsx("p", { className: "truncate text-xs text-muted", children: user.workspaceName }), (role || planChip || !user.emailVerified) && (_jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: [role && (_jsx(Chip, { size: "sm", variant: "soft", color: "accent", children: humanizeRole(role) })), planChip, !user.emailVerified && (_jsx(Chip, { size: "sm", variant: "soft", color: "warning", children: "Email unverified" }))] }))] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-2", children: [_jsx(DestinationTile, { icon: _jsx(UserRound, { className: ICON, "aria-hidden": "true" }), label: "Profile", url: `${appUrl}/profile` }), _jsx(DestinationTile, { icon: _jsx(CreditCard, { className: ICON, "aria-hidden": "true" }), label: "Billing", url: `${appUrl}/billing` }), _jsx(DestinationTile, { icon: _jsx(ConnectMark, { className: ICON }), label: "Connect", url: appUrl })] }), theme && onThemeChange && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Appearance" }), _jsx(ToggleButtonGroup, { fullWidth: true, "aria-label": "Theme", selectionMode: "single", disallowEmptySelection: true, selectedKeys: [theme], onSelectionChange: (keys) => {
132
132
  const [next] = [...keys];
133
133
  if (typeof next === "string")
134
134
  onThemeChange(next);
@@ -149,7 +149,7 @@ export function ConnectManageSubscriptionButton({ className }) {
149
149
  * Invoices and payment history, on Connect.
150
150
  *
151
151
  * A deep link rather than a component that lists them, and that is not a
152
- * placeholder: nothing in `/api/v1/service/*` exposes invoices, so an SDK-side
152
+ * placeholder: nothing in `/api/v1/application/*` exposes invoices, so an SDK-side
153
153
  * list would have nothing to read. It is also the right answer regardless -
154
154
  * a GST tax invoice is a legal document with a fixed format, downloadable and
155
155
  * emailed from one place, and a partner-rendered copy of one would be a second
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Styling is HeroUI v3 semantic tokens only (`accent`, `muted`, `surface`,
10
10
  * `separator`, ...), never a hardcoded colour - so these components inherit
11
- * whatever theme the host service platform already configured, and one theme
11
+ * whatever theme the host application platform already configured, and one theme
12
12
  * change lands identically in all of them.
13
13
  */
14
14
  export { ConnectProvider, useConnect, useConnectUser, useConnectEntitlements, useConnectPlans, useConnectApps, useConnectAddonUsage, useConnectSessions, useConnectIntegrations, useConnectResource, CONNECT_APP_URL, } from "./provider.js";
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  * The Connect mark - concentric rings on a solid accent badge.
5
5
  *
6
6
  * Painted from `--accent` / `--accent-foreground`, the same HeroUI tokens the
7
- * host app themes, so the badge tracks whatever palette a service platform has
7
+ * host app themes, so the badge tracks whatever palette an application platform has
8
8
  * configured rather than carrying a hardcoded CosmoOps green into someone
9
9
  * else's brand.
10
10
  */
@@ -122,7 +122,7 @@ export function ConnectProvider({ clientId = "", basePath = "/api/connect", redi
122
122
  // error, so a Login button still renders rather than the UI hanging on
123
123
  // skeletons forever.
124
124
  setResult({
125
- session: { user: null, subscription: null, serviceRole: null },
125
+ session: { user: null, subscription: null, applicationRole: null },
126
126
  error: cause instanceof Error ? cause.message : "Could not reach Connect",
127
127
  });
128
128
  }
@@ -171,7 +171,7 @@ export function ConnectProvider({ clientId = "", basePath = "/api/connect", redi
171
171
  credentials: "same-origin",
172
172
  }).catch(() => { });
173
173
  cache.current.clear();
174
- setResult({ session: { user: null, subscription: null, serviceRole: null }, error: null });
174
+ setResult({ session: { user: null, subscription: null, applicationRole: null }, error: null });
175
175
  }, [basePath, fetchImpl]);
176
176
  const value = useMemo(() => ({
177
177
  clientId,
@@ -218,28 +218,28 @@ export function useConnectEntitlements() {
218
218
  /**
219
219
  * What is left of every consumable add-on on this workspace's subscription.
220
220
  *
221
- * The read half of `client.billing.consumeAddon` - a service that meters its
221
+ * The read half of `client.billing.consumeAddon` - an application that meters its
222
222
  * own end users had no way to show them what remained until this existed.
223
223
  * Empty `addons` means there is nothing to meter, which is not an error.
224
224
  */
225
225
  export function useConnectAddonUsage() {
226
226
  return useConnectResource("/addons");
227
227
  }
228
- /** This service's plan catalog. */
228
+ /** This application's plan catalog. */
229
229
  export function useConnectPlans() {
230
230
  return useConnectResource("/plans");
231
231
  }
232
- /** The apps this organization can open. */
232
+ /** The apps this workspace can open. */
233
233
  export function useConnectApps() {
234
234
  return useConnectResource("/apps");
235
235
  }
236
- /** Enabled Composio-hosted toolkits and this organization's connection status for each. */
236
+ /** Enabled Composio-hosted toolkits and this workspace's connection status for each. */
237
237
  export function useConnectIntegrations() {
238
238
  return useConnectResource("/integrations");
239
239
  }
240
240
  /**
241
241
  * This Connect account's own login sessions - account-wide, not scoped to
242
- * this service, see `SessionsListResponse`'s doc comment. The component
242
+ * this application, see `SessionsListResponse`'s doc comment. The component
243
243
  * that calls this is also the one that must own any revoke actions and call
244
244
  * the returned `refetch()` afterward - see `mutateResource`'s doc comment
245
245
  * for why nothing does that automatically.
@@ -152,15 +152,15 @@ export function buildCancelUrl({ appUrl, subscriptionId }) {
152
152
  * The Connect URL that completes a subscribe or a plan change.
153
153
  *
154
154
  * Both land on a modal Connect renders over the relevant page (an intercepted
155
- * parallel route - `app/@modal/(.)services/...` and
155
+ * parallel route - `app/@modal/(.)applications/...` and
156
156
  * `app/@modal/(.)billing/...`), so the customer arrives already looking at the
157
157
  * confirmation for the plan they picked here, not at a catalogue they have to
158
158
  * find it in again.
159
159
  */
160
- export function buildCheckoutUrl({ appUrl, serviceId, planId, subscriptionId, coupon, }) {
160
+ export function buildCheckoutUrl({ appUrl, applicationId, planId, subscriptionId, coupon, }) {
161
161
  const path = subscriptionId
162
162
  ? `/billing/subscriptions/${encodeURIComponent(subscriptionId)}/change-plan/${encodeURIComponent(planId)}`
163
- : `/services/${encodeURIComponent(serviceId)}/subscribe/${encodeURIComponent(planId)}`;
163
+ : `/applications/${encodeURIComponent(applicationId)}/subscribe/${encodeURIComponent(planId)}`;
164
164
  const url = new URL(path, appUrl);
165
165
  if (coupon?.trim())
166
166
  url.searchParams.set("coupon", coupon.trim());
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Every failure the Connect service API can report, as one class.
2
+ * Every failure the Connect application API can report, as one class.
3
3
  *
4
4
  * The API speaks two error dialects and this collapses them: the
5
- * `/api/v1/service/*` endpoints use `{ error: { code, message } }`, while the
5
+ * `/api/v1/application/*` endpoints use `{ error: { code, message } }`, while the
6
6
  * three `/sso/*` ones use OAuth2's `{ error, error_description }` (RFC 6749
7
7
  * §5.2). Both land here with `code` populated, so integrating code branches on
8
8
  * one field either way.
@@ -41,7 +41,7 @@ export class ConnectError extends Error {
41
41
  * Whether the user's Connect sign-in is over and they need to go back
42
42
  * through `identity.authorizeUrl()`. Collapses every session-side failure,
43
43
  * matching how the API reports them - unknown, expired, revoked, or issued
44
- * to a different service all arrive as one `invalid_token`.
44
+ * to a different application all arrive as one `invalid_token`.
45
45
  */
46
46
  get isSessionExpired() {
47
47
  return this.code === "invalid_token";
@@ -55,7 +55,7 @@ export class ConnectError extends Error {
55
55
  * guessing keys. These two are the exception: reaching them required
56
56
  * presenting a key whose hash matched, so you already hold it, and what you
57
57
  * need to know is that no retry and no scope change will fix this - the key
58
- * has to be reissued from the service's Integration tab.
58
+ * has to be reissued from the application's Integration tab.
59
59
  *
60
60
  * Worth alerting on. It is the one failure that will not resolve itself and
61
61
  * takes down every call your integration makes.
@@ -12,7 +12,7 @@ export function blockingBlockers(readiness) {
12
12
  * Coerces either wire shape into `PlanFeature[]`.
13
13
  *
14
14
  * A bare key becomes `{ key, name: key, description: "" }` - the same
15
- * fallback the server applies for a plan older than its service's feature
15
+ * fallback the server applies for a plan older than its application's feature
16
16
  * catalog, so an un-upgraded Connect renders exactly what it always did
17
17
  * rather than a column of blanks.
18
18
  *
package/dist/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `@cosmoops/connect-sdk` - the official client for the CosmoOps Connect
3
- * **service-partner API** (`/api/v1/service/*`).
3
+ * **application-partner API** (`/api/v1/application/*`).
4
4
  *
5
5
  * This root entry is the isomorphic surface: wire types, the error class, and
6
6
  * pure helpers. It pulls in neither Node-only code nor React, so it is safe to
@@ -38,7 +38,7 @@ import { createConnectHandler } from "../server/handler.js";
38
38
  * | `CONNECT_SESSION_COOKIE` | no | session cookie name |
39
39
  *
40
40
  * Register `{your origin}/api/connect/callback` as a redirect URI in the
41
- * service's Integration tab. That is the only step this cannot do for you.
41
+ * application's Integration tab. That is the only step this cannot do for you.
42
42
  *
43
43
  * No `next.config.ts` changes needed either, including `transpilePackages`:
44
44
  * `dist/` is already ES2022 with `"use client"` hoisted to the top of every
@@ -287,7 +287,7 @@ export async function getConnectSession(request, options = {}) {
287
287
  * A thin wrapper, not a framework of its own - reach for `getConnectSession`
288
288
  * plus your own check when "not signed in" isn't "redirect to sign-in"
289
289
  * (an API route returning 401, say). Role and entitlement checks stay
290
- * outside this function on purpose: `session.serviceRole.granted` and
290
+ * outside this function on purpose: `session.applicationRole.granted` and
291
291
  * `connect.entitlements.*` are one line each on top of the session this
292
292
  * already gives you, and where that line redirects (a plans page, a
293
293
  * "forbidden" screen) is a decision only your app can make - see
@@ -11,7 +11,7 @@ import { AnalyticsResource } from "./resources/analytics.js";
11
11
  import { OtpResource } from "./resources/otp.js";
12
12
  import { SessionsResource } from "./resources/sessions.js";
13
13
  export const DEFAULT_BASE_URL = "https://connect.cosmoops.com";
14
- const SERVICE_API_PREFIX = "/api/v1/service";
14
+ const APPLICATION_API_PREFIX = "/api/v1/application";
15
15
  /**
16
16
  * Refuses to build a client in a browser.
17
17
  *
@@ -40,9 +40,9 @@ function assertNotBrowser() {
40
40
  "in browser code instead; it talks to your own origin and holds no credential.");
41
41
  }
42
42
  /**
43
- * The CosmoOps Connect service-partner API.
43
+ * The CosmoOps Connect application-partner API.
44
44
  *
45
- * Covers `/api/v1/service/*` and nothing else - the surface a service platform
45
+ * Covers `/api/v1/application/*` and nothing else - the surface an application platform
46
46
  * integrates against. Connect's internal API is not part of this package and
47
47
  * never will be.
48
48
  *
@@ -53,7 +53,7 @@ function assertNotBrowser() {
53
53
  * });
54
54
  *
55
55
  * const session = await connect.identity.exchangeCode({ code, redirectUri });
56
- * const { ready } = await connect.entitlements.getReadiness(session.user.organizationId);
56
+ * const { ready } = await connect.entitlements.getReadiness(session.user.workspaceId);
57
57
  * ```
58
58
  *
59
59
  * Every failure throws a `ConnectError` carrying a stable `code`. Nothing here
@@ -62,27 +62,27 @@ function assertNotBrowser() {
62
62
  export class ConnectClient {
63
63
  /** "Login with Connect" - the OAuth2 handshake and the session after it. */
64
64
  identity;
65
- /** What a signed-in member may do on your service. */
65
+ /** What a signed-in member may do on your application. */
66
66
  access;
67
- /** The services an organization can open - for a launcher grid. */
67
+ /** The applications a workspace can open - for a launcher grid. */
68
68
  apps;
69
- /** Whether a workspace may use your service, and on what plan. */
69
+ /** Whether a workspace may use your application, and on what plan. */
70
70
  entitlements;
71
71
  /** Your plan catalog, and metering usage against add-on balances. */
72
72
  billing;
73
- /** Files in an organization's Drive. */
73
+ /** Files in a workspace's Drive. */
74
74
  drive;
75
75
  /** RAG chat and structured extraction. */
76
76
  ai;
77
77
  /** WhatsApp/SMS phone verification. */
78
78
  otp;
79
- /** Feature events into the Console's audit log, filterable to your service. */
79
+ /** Feature events into the Console's audit log, filterable to your application. */
80
80
  logs;
81
- /** Emit product events and read back this service's aggregated numbers. */
81
+ /** Emit product events and read back this application's aggregated numbers. */
82
82
  analytics;
83
- /** This Connect account's own login sessions - account-wide, not scoped to this service. Requires the `sessions:manage` scope. */
83
+ /** This Connect account's own login sessions - account-wide, not scoped to this application. Requires the `sessions:manage` scope. */
84
84
  sessions;
85
- /** Composio-hosted third-party connections (Google Calendar, Slack, ...) an organization has connected. */
85
+ /** Composio-hosted third-party connections (Google Calendar, Slack, ...) a workspace has connected. */
86
86
  integrations;
87
87
  constructor(options) {
88
88
  assertNotBrowser();
@@ -91,7 +91,7 @@ export class ConnectClient {
91
91
  }
92
92
  const appBaseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
93
93
  const transport = {
94
- baseUrl: `${appBaseUrl}${SERVICE_API_PREFIX}`,
94
+ baseUrl: `${appBaseUrl}${APPLICATION_API_PREFIX}`,
95
95
  apiKey: options.apiKey,
96
96
  timeoutMs: options.timeoutMs ?? 20_000,
97
97
  maxRetries: options.maxRetries ?? 2,
@@ -99,7 +99,7 @@ export class ConnectClient {
99
99
  userAgent: `cosmoops-connect-sdk/${SDK_VERSION}`,
100
100
  };
101
101
  // `authorizeUrl` points at the app, not the API prefix - it is a browser
102
- // redirect, not a service call, so identity takes both.
102
+ // redirect, not an application call, so identity takes both.
103
103
  this.identity = new IdentityResource(transport, options.clientId ?? null, appBaseUrl);
104
104
  this.access = new AccessResource(transport);
105
105
  this.apps = new AppsResource(transport);
@@ -115,4 +115,4 @@ export class ConnectClient {
115
115
  }
116
116
  }
117
117
  /** Kept in step with `package.json` by `sdk.test.ts`. */
118
- export const SDK_VERSION = "0.6.0";
118
+ export const SDK_VERSION = "0.7.0";