@cosmoops/connect-sdk 0.6.0 → 0.9.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 (138) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +273 -91
  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 +42 -7
  6. package/dist/cjs/client/components/account-sessions.js +3 -3
  7. package/dist/cjs/client/components/ai-format.js +135 -0
  8. package/dist/cjs/client/components/ai-widgets.js +232 -0
  9. package/dist/cjs/client/components/app-shell.js +9 -8
  10. package/dist/cjs/client/components/apps-grid.js +3 -3
  11. package/dist/cjs/client/components/ask-ai.js +334 -0
  12. package/dist/cjs/client/components/feature-gate.js +2 -2
  13. package/dist/cjs/client/components/integrations-modal.js +1 -1
  14. package/dist/cjs/client/components/logo.js +3 -3
  15. package/dist/cjs/client/components/nav.js +1 -1
  16. package/dist/cjs/client/components/plan-pricing.js +1 -1
  17. package/dist/cjs/client/components/plans.js +6 -6
  18. package/dist/cjs/client/components/readiness.js +3 -3
  19. package/dist/cjs/client/components/side-nav.js +1 -1
  20. package/dist/cjs/client/components/subscribe-dialog.js +2 -2
  21. package/dist/cjs/client/components/subscription.js +1 -1
  22. package/dist/cjs/client/components/usage-meter.js +1 -1
  23. package/dist/cjs/client/components/user-menu.js +31 -8
  24. package/dist/cjs/client/components/workspace-type-gate.js +48 -0
  25. package/dist/cjs/client/index.js +32 -4
  26. package/dist/cjs/client/mark.js +1 -1
  27. package/dist/cjs/client/provider.js +50 -7
  28. package/dist/cjs/client/use-checkout.js +3 -3
  29. package/dist/cjs/errors.js +4 -4
  30. package/dist/cjs/helpers.js +1 -1
  31. package/dist/cjs/index.js +1 -1
  32. package/dist/cjs/next/index.js +2 -2
  33. package/dist/cjs/server/client.js +15 -15
  34. package/dist/cjs/server/handler.js +56 -13
  35. package/dist/cjs/server/http.js +47 -25
  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 +2 -2
  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 +48 -7
  43. package/dist/cjs/server/resources/identity.js +6 -4
  44. package/dist/cjs/server/resources/integrations.js +13 -13
  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 +4 -4
  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 +43 -8
  52. package/dist/esm/client/components/account-sessions.js +3 -3
  53. package/dist/esm/client/components/ai-format.js +129 -0
  54. package/dist/esm/client/components/ai-widgets.js +223 -0
  55. package/dist/esm/client/components/app-shell.js +8 -7
  56. package/dist/esm/client/components/apps-grid.js +3 -3
  57. package/dist/esm/client/components/ask-ai.js +331 -0
  58. package/dist/esm/client/components/feature-gate.js +2 -2
  59. package/dist/esm/client/components/integrations-modal.js +1 -1
  60. package/dist/esm/client/components/logo.js +3 -3
  61. package/dist/esm/client/components/nav.js +1 -1
  62. package/dist/esm/client/components/plan-pricing.js +1 -1
  63. package/dist/esm/client/components/plans.js +6 -6
  64. package/dist/esm/client/components/readiness.js +3 -3
  65. package/dist/esm/client/components/side-nav.js +1 -1
  66. package/dist/esm/client/components/subscribe-dialog.js +2 -2
  67. package/dist/esm/client/components/subscription.js +1 -1
  68. package/dist/esm/client/components/usage-meter.js +1 -1
  69. package/dist/esm/client/components/user-menu.js +31 -8
  70. package/dist/esm/client/components/workspace-type-gate.js +45 -0
  71. package/dist/esm/client/index.js +14 -3
  72. package/dist/esm/client/mark.js +1 -1
  73. package/dist/esm/client/provider.js +48 -7
  74. package/dist/esm/client/use-checkout.js +3 -3
  75. package/dist/esm/errors.js +4 -4
  76. package/dist/esm/helpers.js +1 -1
  77. package/dist/esm/index.js +1 -1
  78. package/dist/esm/next/index.js +2 -2
  79. package/dist/esm/server/client.js +15 -15
  80. package/dist/esm/server/handler.js +56 -13
  81. package/dist/esm/server/http.js +47 -25
  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 +2 -2
  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 +48 -7
  89. package/dist/esm/server/resources/identity.js +6 -4
  90. package/dist/esm/server/resources/integrations.js +13 -13
  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 +4 -4
  94. package/dist/esm/types.js +1 -1
  95. package/dist/theme.css +87 -0
  96. package/dist/types/client/components/access-gate.d.ts +18 -4
  97. package/dist/types/client/components/account-sessions.d.ts +1 -1
  98. package/dist/types/client/components/ai-format.d.ts +24 -0
  99. package/dist/types/client/components/ai-widgets.d.ts +42 -0
  100. package/dist/types/client/components/app-shell.d.ts +25 -9
  101. package/dist/types/client/components/apps-grid.d.ts +1 -1
  102. package/dist/types/client/components/ask-ai.d.ts +73 -0
  103. package/dist/types/client/components/feature-gate.d.ts +1 -1
  104. package/dist/types/client/components/integrations-modal.d.ts +1 -1
  105. package/dist/types/client/components/logo.d.ts +5 -5
  106. package/dist/types/client/components/nav.d.ts +3 -3
  107. package/dist/types/client/components/plan-pricing.d.ts +2 -2
  108. package/dist/types/client/components/readiness.d.ts +2 -2
  109. package/dist/types/client/components/side-nav.d.ts +1 -1
  110. package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
  111. package/dist/types/client/components/usage-meter.d.ts +1 -1
  112. package/dist/types/client/components/user-menu.d.ts +4 -3
  113. package/dist/types/client/components/workspace-type-gate.d.ts +48 -0
  114. package/dist/types/client/index.d.ts +11 -4
  115. package/dist/types/client/mark.d.ts +1 -1
  116. package/dist/types/client/provider.d.ts +52 -9
  117. package/dist/types/client/use-checkout.d.ts +3 -3
  118. package/dist/types/errors.d.ts +4 -4
  119. package/dist/types/helpers.d.ts +1 -1
  120. package/dist/types/index.d.ts +1 -1
  121. package/dist/types/next/index.d.ts +1 -1
  122. package/dist/types/server/client.d.ts +13 -13
  123. package/dist/types/server/handler.d.ts +2 -2
  124. package/dist/types/server/http.d.ts +6 -1
  125. package/dist/types/server/resources/access.d.ts +3 -3
  126. package/dist/types/server/resources/ai.d.ts +2 -2
  127. package/dist/types/server/resources/analytics.d.ts +2 -2
  128. package/dist/types/server/resources/apps.d.ts +4 -4
  129. package/dist/types/server/resources/billing.d.ts +4 -4
  130. package/dist/types/server/resources/drive.d.ts +4 -4
  131. package/dist/types/server/resources/entitlements.d.ts +37 -5
  132. package/dist/types/server/resources/identity.d.ts +2 -2
  133. package/dist/types/server/resources/integrations.d.ts +9 -9
  134. package/dist/types/server/resources/logs.d.ts +3 -3
  135. package/dist/types/server/resources/sessions.d.ts +5 -5
  136. package/dist/types/server/webhooks.d.ts +4 -4
  137. package/dist/types/types.d.ts +235 -61
  138. package/package.json +8 -2
@@ -27,6 +27,28 @@ function initials(name, email) {
27
27
  function openExternal(url) {
28
28
  window.open(url, "_blank", "noopener,noreferrer");
29
29
  }
30
+ /**
31
+ * Connect's profile page, with the context it needs to offer a way back here.
32
+ *
33
+ * Connect answers `/profile` for any signed-in user, so the bare URL works on
34
+ * its own - these two params only add the "Back to <your app>" banner. It
35
+ * validates `return_to` against this `client_id`'s registered redirect
36
+ * origins and silently drops the banner if they don't match, so a wrong or
37
+ * stale `appUrl`/`clientId` pairing degrades to what it did before rather
38
+ * than erroring.
39
+ *
40
+ * `window.location.href` rather than a configured home URL: the point is to
41
+ * come back to the page they left, and only the browser knows which one that
42
+ * is.
43
+ */
44
+ function profileUrl(appUrl, clientId) {
45
+ const url = new URL("/profile", appUrl);
46
+ url.searchParams.set("client_id", clientId);
47
+ if (typeof window !== "undefined") {
48
+ url.searchParams.set("return_to", window.location.href);
49
+ }
50
+ return url.toString();
51
+ }
30
52
  /**
31
53
  * The member's photo, with their initials underneath it.
32
54
  *
@@ -105,7 +127,7 @@ function DestinationTile({ icon, label, url, }) {
105
127
  * in place, which is why it sits alone in the footer rather than as a fourth
106
128
  * item in the same list as three navigations.
107
129
  *
108
- * The session list is account-wide, not scoped to this service - see
130
+ * The session list is account-wide, not scoped to this application - see
109
131
  * `ConnectUserSession`'s doc comment in `types.ts`. Appearance only renders
110
132
  * when both `theme` and `onThemeChange` are supplied.
111
133
  *
@@ -122,7 +144,7 @@ function DestinationTile({ icon, label, url, }) {
122
144
  * the modal programmatically; sign-out uses `slot="close"` instead.
123
145
  */
124
146
  function ConnectUserMenu({ compact = false, onSignOut, className, theme, onThemeChange, }) {
125
- const { session, isLoading, signOut, appUrl } = (0, provider_js_1.useConnect)();
147
+ const { session, isLoading, signOut, appUrl, clientId } = (0, provider_js_1.useConnect)();
126
148
  if (isLoading) {
127
149
  return ((0, jsx_runtime_1.jsxs)("div", { className: `flex items-center gap-2 ${className ?? ""}`, children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "size-8 shrink-0 rounded-full" }), !compact && (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-4 w-24" })] }));
128
150
  }
@@ -130,13 +152,13 @@ function ConnectUserMenu({ compact = false, onSignOut, className, theme, onTheme
130
152
  if (!user)
131
153
  return null;
132
154
  const label = user.displayName ?? user.email ?? "Account";
133
- const role = session?.serviceRole?.role;
155
+ const role = session?.applicationRole?.role;
134
156
  const planChip = subscriptionChip(session?.subscription ?? null);
135
157
  return ((0, jsx_runtime_1.jsxs)(react_1.Modal, { children: [(0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "tertiary", "aria-label": `Account: ${label}`,
136
158
  // `pl-1` against the default right padding is optical, not sloppy: a
137
159
  // circular avatar needs less inset than a text label to look evenly
138
160
  // seated in the button.
139
- className: `gap-2 pl-1 ${className ?? ""}`, children: [(0, jsx_runtime_1.jsx)(UserAvatar, { user: user, size: "sm" }), !compact && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-foreground", children: label })] }), (0, jsx_runtime_1.jsx)(react_1.Modal.Backdrop, { children: (0, jsx_runtime_1.jsx)(react_1.Modal.Container, { size: "md", scroll: "inside", children: (0, jsx_runtime_1.jsxs)(react_1.Modal.Dialog, { children: [(0, jsx_runtime_1.jsx)(react_1.Modal.CloseTrigger, {}), (0, jsx_runtime_1.jsx)(react_1.Modal.Header, { children: (0, jsx_runtime_1.jsx)(react_1.Modal.Heading, { children: "Account" }) }), (0, jsx_runtime_1.jsxs)(react_1.Modal.Body, { className: "flex flex-col gap-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: `flex items-start gap-3 rounded-xl border border-border ${surfaces_js_1.PANEL_FILL} p-4`, children: [(0, jsx_runtime_1.jsx)(UserAvatar, { user: user, size: "lg" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "truncate text-sm font-semibold text-foreground", children: label }), user.email && (0, jsx_runtime_1.jsx)("p", { className: "truncate text-xs text-muted", children: user.email }), (0, jsx_runtime_1.jsx)("p", { className: "truncate text-xs text-muted", children: user.organizationName }), (role || planChip || !user.emailVerified) && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: [role && ((0, jsx_runtime_1.jsx)(react_1.Chip, { size: "sm", variant: "soft", color: "accent", children: humanizeRole(role) })), planChip, !user.emailVerified && ((0, jsx_runtime_1.jsx)(react_1.Chip, { size: "sm", variant: "soft", color: "warning", children: "Email unverified" }))] }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [(0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.UserRound, { className: surfaces_js_1.ICON, "aria-hidden": "true" }), label: "Profile", url: `${appUrl}/profile` }), (0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CreditCard, { className: surfaces_js_1.ICON, "aria-hidden": "true" }), label: "Billing", url: `${appUrl}/billing` }), (0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(mark_js_1.ConnectMark, { className: surfaces_js_1.ICON }), label: "Connect", url: appUrl })] }), theme && onThemeChange && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-2", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Appearance" }), (0, jsx_runtime_1.jsx)(react_1.ToggleButtonGroup, { fullWidth: true, "aria-label": "Theme", selectionMode: "single", disallowEmptySelection: true, selectedKeys: [theme], onSelectionChange: (keys) => {
161
+ className: `gap-2 pl-1 ${className ?? ""}`, children: [(0, jsx_runtime_1.jsx)(UserAvatar, { user: user, size: "sm" }), !compact && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-foreground", children: label })] }), (0, jsx_runtime_1.jsx)(react_1.Modal.Backdrop, { children: (0, jsx_runtime_1.jsx)(react_1.Modal.Container, { size: "md", scroll: "inside", children: (0, jsx_runtime_1.jsxs)(react_1.Modal.Dialog, { children: [(0, jsx_runtime_1.jsx)(react_1.Modal.CloseTrigger, {}), (0, jsx_runtime_1.jsx)(react_1.Modal.Header, { children: (0, jsx_runtime_1.jsx)(react_1.Modal.Heading, { children: "Account" }) }), (0, jsx_runtime_1.jsxs)(react_1.Modal.Body, { className: "flex flex-col gap-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: `flex items-start gap-3 rounded-xl border border-border ${surfaces_js_1.PANEL_FILL} p-4`, children: [(0, jsx_runtime_1.jsx)(UserAvatar, { user: user, size: "lg" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "truncate text-sm font-semibold text-foreground", children: label }), user.email && (0, jsx_runtime_1.jsx)("p", { className: "truncate text-xs text-muted", children: user.email }), (0, jsx_runtime_1.jsx)("p", { className: "truncate text-xs text-muted", children: user.workspaceName }), (role || planChip || !user.emailVerified) && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: [role && ((0, jsx_runtime_1.jsx)(react_1.Chip, { size: "sm", variant: "soft", color: "accent", children: humanizeRole(role) })), planChip, !user.emailVerified && ((0, jsx_runtime_1.jsx)(react_1.Chip, { size: "sm", variant: "soft", color: "warning", children: "Email unverified" }))] }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [(0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.UserRound, { className: surfaces_js_1.ICON, "aria-hidden": "true" }), label: "Profile", url: profileUrl(appUrl, clientId) }), (0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CreditCard, { className: surfaces_js_1.ICON, "aria-hidden": "true" }), label: "Billing", url: `${appUrl}/billing` }), (0, jsx_runtime_1.jsx)(DestinationTile, { icon: (0, jsx_runtime_1.jsx)(mark_js_1.ConnectMark, { className: surfaces_js_1.ICON }), label: "Connect", url: appUrl })] }), theme && onThemeChange && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-2", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Appearance" }), (0, jsx_runtime_1.jsx)(react_1.ToggleButtonGroup, { fullWidth: true, "aria-label": "Theme", selectionMode: "single", disallowEmptySelection: true, selectedKeys: [theme], onSelectionChange: (keys) => {
140
162
  const [next] = [...keys];
141
163
  if (typeof next === "string")
142
164
  onThemeChange(next);
@@ -157,7 +179,7 @@ function ConnectManageSubscriptionButton({ className }) {
157
179
  * Invoices and payment history, on Connect.
158
180
  *
159
181
  * A deep link rather than a component that lists them, and that is not a
160
- * placeholder: nothing in `/api/v1/service/*` exposes invoices, so an SDK-side
182
+ * placeholder: nothing in `/api/v1/application/*` exposes invoices, so an SDK-side
161
183
  * list would have nothing to read. It is also the right answer regardless -
162
184
  * a GST tax invoice is a legal document with a fixed format, downloadable and
163
185
  * emailed from one place, and a partner-rendered copy of one would be a second
@@ -175,13 +197,14 @@ function ConnectInvoicesButton({ className }) {
175
197
  * `ConnectHomeButton`.
176
198
  *
177
199
  * It was reachable only from inside `ConnectUserMenu`, which meant an app that
178
- * builds its own account menu had to hardcode `${appUrl}/profile` to offer it.
200
+ * builds its own account menu had to hardcode `${appUrl}/profile` to offer it -
201
+ * and got no `return_to`, so the user had no way back.
179
202
  */
180
203
  function ConnectProfileButton({ className }) {
181
- const { session, appUrl } = (0, provider_js_1.useConnect)();
204
+ const { session, appUrl, clientId } = (0, provider_js_1.useConnect)();
182
205
  if (!session?.user)
183
206
  return null;
184
- return ((0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "tertiary", className: className, onPress: () => openExternal(`${appUrl}/profile`), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.UserRound, { className: "size-4 shrink-0" }), "Profile", (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "size-3.5 shrink-0 text-muted" })] }));
207
+ return ((0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "tertiary", className: className, onPress: () => openExternal(profileUrl(appUrl, clientId)), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.UserRound, { className: "size-4 shrink-0" }), "Profile", (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "size-3.5 shrink-0 text-muted" })] }));
185
208
  }
186
209
  /** A plain "Open Connect" button, for a footer or a help menu. */
187
210
  function ConnectHomeButton({ className }) {
@@ -0,0 +1,48 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ConnectWorkspaceTypeGate = ConnectWorkspaceTypeGate;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const provider_js_1 = require("../provider.js");
7
+ /**
8
+ * Renders `children` only for a workspace of the given type.
9
+ *
10
+ * ```tsx
11
+ * <ConnectWorkspaceTypeGate type="business">
12
+ * <TeamMembersTable />
13
+ * </ConnectWorkspaceTypeGate>
14
+ * ```
15
+ *
16
+ * The point is dead controls, not access: an `"individual"` workspace has
17
+ * exactly one seat and can never have another, so a members table, an invite
18
+ * button and a seat meter are all things that can only ever fail there.
19
+ * Hiding them is a better answer than letting someone press one and read an
20
+ * error about an account shape they did not choose.
21
+ *
22
+ * This is emphatically **not** the audience gate. It does not know what your
23
+ * application is sold to and will happily render a business-only subtree to a
24
+ * business workspace that has no business being in your application at all -
25
+ * that is `<ConnectAccessGate>`'s job, off the `audience_mismatch` readiness
26
+ * blocker. Use this one *inside* an application both audiences can reach, to
27
+ * vary what each sees.
28
+ *
29
+ * Like every gate in this package it is a **UX gate, not a security
30
+ * boundary**: the browser can ignore it. Anything that must not happen for an
31
+ * individual workspace has to be refused on your server too.
32
+ *
33
+ * Renders `loading` - not `fallback` - while the session is unknown, so a
34
+ * business account never flickers through the individual-account layout.
35
+ */
36
+ function ConnectWorkspaceTypeGate({ type, children, fallback = null, loading = null, }) {
37
+ const { session, isLoading } = (0, provider_js_1.useConnect)();
38
+ const workspaceType = session?.user?.workspaceType ?? null;
39
+ if (isLoading)
40
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: loading });
41
+ // Signed out is not "the other type" - there is no workspace to be a type
42
+ // of yet, and rendering the fallback here would put an individual-account
43
+ // layout in front of a visitor who has not signed in.
44
+ if (!workspaceType)
45
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: loading });
46
+ const accepted = Array.isArray(type) ? type : [type];
47
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: accepted.includes(workspaceType) ? children : fallback });
48
+ }
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.ConnectFeatureGate = exports.useConnectAccessGate = exports.ConnectAccessGate = exports.ConnectReadinessGate = exports.ConnectReadinessBanner = exports.resolveSubscriptionState = exports.ConnectSeatUsage = exports.ConnectTrialBanner = exports.ConnectSubscriptionCard = exports.ConnectNoSubscriptionCard = exports.ConnectSubscriptionGate = exports.ConnectSubscribeDialog = exports.ConnectPlans = exports.ConnectIntegrationsModal = exports.ConnectAppsGrid = exports.gateExemptPaths = exports.isNavItemActive = exports.resolveActivePath = exports.normalizePath = exports.flattenNav = exports.normalizeNav = exports.useActivePath = exports.ConnectSideNav = exports.ConnectAppShell = exports.ConnectAccountSessions = exports.ConnectSignOutButton = exports.ConnectHomeButton = exports.ConnectProfileButton = exports.ConnectInvoicesButton = exports.ConnectManageSubscriptionButton = exports.ConnectUserMenu = exports.ConnectRegisterButton = exports.ConnectLoginButton = exports.ConnectLogo = exports.ConnectMark = exports.isConnectError = exports.ConnectError = exports.normalizePlanFeatures = exports.blockingBlockers = exports.CONNECT_APP_URL = exports.useConnectResource = exports.useConnectIntegrations = exports.useConnectSessions = exports.useConnectAddonUsage = exports.useConnectApps = exports.useConnectPlans = exports.useConnectEntitlements = exports.useConnectUser = exports.useConnect = exports.ConnectProvider = void 0;
5
- exports.resolvePlanGroup = exports.groupPlansByTier = exports.ACTION_LABEL = exports.discountLabel = exports.annualSaving = exports.resolveAction = exports.monthlyOf = exports.formatPrice = exports.buildCheckoutUrl = exports.useConnectCheckout = exports.ConnectPlansPage = exports.ConnectUsageMeter = exports.useConnectFeature = void 0;
4
+ exports.AI_EMPTY_VALUE = exports.aiStatusTone = exports.isNumericAiFormat = exports.formatAiValue = exports.AiSources = exports.AiSteps = exports.AiDetails = exports.AiTimeline = exports.AiMetrics = exports.AiChart = exports.AiTable = exports.ConnectAskAi = exports.ConnectAppsGrid = exports.gateExemptPaths = exports.isNavItemActive = exports.resolveActivePath = exports.normalizePath = exports.flattenNav = exports.normalizeNav = exports.useActivePath = exports.ConnectSideNav = exports.AppShell = exports.ConnectAccountSessions = exports.ConnectSignOutButton = exports.ConnectHomeButton = exports.ConnectProfileButton = exports.ConnectInvoicesButton = exports.ConnectManageSubscriptionButton = exports.ConnectUserMenu = exports.ConnectRegisterButton = exports.ConnectLoginButton = exports.ConnectLogo = exports.ConnectMark = exports.isConnectError = exports.ConnectError = exports.normalizePlanFeatures = exports.blockingBlockers = exports.CONNECT_APP_URL = exports.useConnectResource = exports.useConnectIntegrations = exports.useConnectSessions = exports.useConnectAddonUsage = exports.useConnectApps = exports.useConnectPlans = exports.useConnectEntitlements = exports.useConnectAudience = exports.useConnectWorkspaceType = exports.useConnectUser = exports.useConnect = exports.ConnectProvider = void 0;
5
+ exports.resolvePlanGroup = exports.groupPlansByTier = exports.ACTION_LABEL = exports.discountLabel = exports.annualSaving = exports.resolveAction = exports.monthlyOf = exports.formatPrice = exports.buildCheckoutUrl = exports.useConnectCheckout = exports.ConnectPlansPage = exports.ConnectUsageMeter = exports.ConnectWorkspaceTypeGate = exports.useConnectFeature = exports.ConnectFeatureGate = exports.useConnectAccessGate = exports.ConnectAccessGate = exports.ConnectReadinessGate = exports.ConnectReadinessBanner = exports.resolveSubscriptionState = exports.ConnectSeatUsage = exports.ConnectTrialBanner = exports.ConnectSubscriptionCard = exports.ConnectNoSubscriptionCard = exports.ConnectSubscriptionGate = exports.ConnectSubscribeDialog = exports.ConnectPlans = exports.ConnectIntegrationsModal = exports.AI_TONE_DOT = exports.AI_TONE_CHIP = void 0;
6
6
  /**
7
7
  * Browser half of `@cosmoops/connect-sdk` - React components and hooks.
8
8
  *
@@ -12,13 +12,15 @@ exports.resolvePlanGroup = exports.groupPlansByTier = exports.ACTION_LABEL = exp
12
12
  *
13
13
  * Styling is HeroUI v3 semantic tokens only (`accent`, `muted`, `surface`,
14
14
  * `separator`, ...), never a hardcoded colour - so these components inherit
15
- * whatever theme the host service platform already configured, and one theme
15
+ * whatever theme the host application platform already configured, and one theme
16
16
  * change lands identically in all of them.
17
17
  */
18
18
  var provider_js_1 = require("./provider.js");
19
19
  Object.defineProperty(exports, "ConnectProvider", { enumerable: true, get: function () { return provider_js_1.ConnectProvider; } });
20
20
  Object.defineProperty(exports, "useConnect", { enumerable: true, get: function () { return provider_js_1.useConnect; } });
21
21
  Object.defineProperty(exports, "useConnectUser", { enumerable: true, get: function () { return provider_js_1.useConnectUser; } });
22
+ Object.defineProperty(exports, "useConnectWorkspaceType", { enumerable: true, get: function () { return provider_js_1.useConnectWorkspaceType; } });
23
+ Object.defineProperty(exports, "useConnectAudience", { enumerable: true, get: function () { return provider_js_1.useConnectAudience; } });
22
24
  Object.defineProperty(exports, "useConnectEntitlements", { enumerable: true, get: function () { return provider_js_1.useConnectEntitlements; } });
23
25
  Object.defineProperty(exports, "useConnectPlans", { enumerable: true, get: function () { return provider_js_1.useConnectPlans; } });
24
26
  Object.defineProperty(exports, "useConnectApps", { enumerable: true, get: function () { return provider_js_1.useConnectApps; } });
@@ -59,7 +61,7 @@ Object.defineProperty(exports, "ConnectAccountSessions", { enumerable: true, get
59
61
  // reaching for a sidebar wants to find the launcher and the account menu in
60
62
  // the same breath, since the shell already mounts both.
61
63
  var app_shell_js_1 = require("./components/app-shell.js");
62
- Object.defineProperty(exports, "ConnectAppShell", { enumerable: true, get: function () { return app_shell_js_1.ConnectAppShell; } });
64
+ Object.defineProperty(exports, "AppShell", { enumerable: true, get: function () { return app_shell_js_1.AppShell; } });
63
65
  var side_nav_js_1 = require("./components/side-nav.js");
64
66
  Object.defineProperty(exports, "ConnectSideNav", { enumerable: true, get: function () { return side_nav_js_1.ConnectSideNav; } });
65
67
  var use_active_path_js_1 = require("./use-active-path.js");
@@ -77,6 +79,30 @@ Object.defineProperty(exports, "isNavItemActive", { enumerable: true, get: funct
77
79
  Object.defineProperty(exports, "gateExemptPaths", { enumerable: true, get: function () { return nav_js_1.gateExemptPaths; } });
78
80
  var apps_grid_js_1 = require("./components/apps-grid.js");
79
81
  Object.defineProperty(exports, "ConnectAppsGrid", { enumerable: true, get: function () { return apps_grid_js_1.ConnectAppsGrid; } });
82
+ // `AppShell askAi` mounts this; exported for an app that wants the panel
83
+ // without the frame, or wants it somewhere other than the shell's flex row
84
+ // (at which point it overlays rather than pushes - see its doc comment).
85
+ var ask_ai_js_1 = require("./components/ask-ai.js");
86
+ Object.defineProperty(exports, "ConnectAskAi", { enumerable: true, get: function () { return ask_ai_js_1.ConnectAskAi; } });
87
+ // The seven widgets an Ask AI answer can draw, and the formatter they share -
88
+ // exported so a partner rendering Connect's chat somewhere else entirely (a
89
+ // support console, an embedded assistant) gets the same table, chart and metric
90
+ // tiles rather than reimplementing them from the wire types.
91
+ var ai_widgets_js_1 = require("./components/ai-widgets.js");
92
+ Object.defineProperty(exports, "AiTable", { enumerable: true, get: function () { return ai_widgets_js_1.AiTable; } });
93
+ Object.defineProperty(exports, "AiChart", { enumerable: true, get: function () { return ai_widgets_js_1.AiChart; } });
94
+ Object.defineProperty(exports, "AiMetrics", { enumerable: true, get: function () { return ai_widgets_js_1.AiMetrics; } });
95
+ Object.defineProperty(exports, "AiTimeline", { enumerable: true, get: function () { return ai_widgets_js_1.AiTimeline; } });
96
+ Object.defineProperty(exports, "AiDetails", { enumerable: true, get: function () { return ai_widgets_js_1.AiDetails; } });
97
+ Object.defineProperty(exports, "AiSteps", { enumerable: true, get: function () { return ai_widgets_js_1.AiSteps; } });
98
+ Object.defineProperty(exports, "AiSources", { enumerable: true, get: function () { return ai_widgets_js_1.AiSources; } });
99
+ var ai_format_js_1 = require("./components/ai-format.js");
100
+ Object.defineProperty(exports, "formatAiValue", { enumerable: true, get: function () { return ai_format_js_1.formatAiValue; } });
101
+ Object.defineProperty(exports, "isNumericAiFormat", { enumerable: true, get: function () { return ai_format_js_1.isNumericAiFormat; } });
102
+ Object.defineProperty(exports, "aiStatusTone", { enumerable: true, get: function () { return ai_format_js_1.aiStatusTone; } });
103
+ Object.defineProperty(exports, "AI_EMPTY_VALUE", { enumerable: true, get: function () { return ai_format_js_1.AI_EMPTY_VALUE; } });
104
+ Object.defineProperty(exports, "AI_TONE_CHIP", { enumerable: true, get: function () { return ai_format_js_1.AI_TONE_CHIP; } });
105
+ Object.defineProperty(exports, "AI_TONE_DOT", { enumerable: true, get: function () { return ai_format_js_1.AI_TONE_DOT; } });
80
106
  var integrations_modal_js_1 = require("./components/integrations-modal.js");
81
107
  Object.defineProperty(exports, "ConnectIntegrationsModal", { enumerable: true, get: function () { return integrations_modal_js_1.ConnectIntegrationsModal; } });
82
108
  var plans_js_1 = require("./components/plans.js");
@@ -104,6 +130,8 @@ Object.defineProperty(exports, "useConnectAccessGate", { enumerable: true, get:
104
130
  var feature_gate_js_1 = require("./components/feature-gate.js");
105
131
  Object.defineProperty(exports, "ConnectFeatureGate", { enumerable: true, get: function () { return feature_gate_js_1.ConnectFeatureGate; } });
106
132
  Object.defineProperty(exports, "useConnectFeature", { enumerable: true, get: function () { return feature_gate_js_1.useConnectFeature; } });
133
+ var workspace_type_gate_js_1 = require("./components/workspace-type-gate.js");
134
+ Object.defineProperty(exports, "ConnectWorkspaceTypeGate", { enumerable: true, get: function () { return workspace_type_gate_js_1.ConnectWorkspaceTypeGate; } });
107
135
  var usage_meter_js_1 = require("./components/usage-meter.js");
108
136
  Object.defineProperty(exports, "ConnectUsageMeter", { enumerable: true, get: function () { return usage_meter_js_1.ConnectUsageMeter; } });
109
137
  var plans_page_js_1 = require("./components/plans-page.js");
@@ -7,7 +7,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  * The Connect mark - concentric rings on a solid accent badge.
8
8
  *
9
9
  * Painted from `--accent` / `--accent-foreground`, the same HeroUI tokens the
10
- * host app themes, so the badge tracks whatever palette a service platform has
10
+ * host app themes, so the badge tracks whatever palette an application platform has
11
11
  * configured rather than carrying a hardcoded CosmoOps green into someone
12
12
  * else's brand.
13
13
  */
@@ -5,6 +5,8 @@ exports.CONNECT_APP_URL = void 0;
5
5
  exports.ConnectProvider = ConnectProvider;
6
6
  exports.useConnect = useConnect;
7
7
  exports.useConnectUser = useConnectUser;
8
+ exports.useConnectWorkspaceType = useConnectWorkspaceType;
9
+ exports.useConnectAudience = useConnectAudience;
8
10
  exports.useConnectEntitlements = useConnectEntitlements;
9
11
  exports.useConnectAddonUsage = useConnectAddonUsage;
10
12
  exports.useConnectPlans = useConnectPlans;
@@ -124,6 +126,20 @@ function ConnectProvider({ clientId = "", basePath = "/api/connect", redirectUri
124
126
  const invalidateResource = (0, react_1.useCallback)((path) => {
125
127
  cache.current.delete(`${basePath}${path}`);
126
128
  }, [basePath]);
129
+ const streamResource = (0, react_1.useCallback)(async (path, body, options) => {
130
+ const response = await (fetchImpl ?? globalThis.fetch)(`${basePath}${path}`, {
131
+ method: "POST",
132
+ credentials: "same-origin",
133
+ headers: { accept: "text/event-stream", "content-type": "application/json" },
134
+ body: JSON.stringify(body),
135
+ signal: options?.signal,
136
+ });
137
+ if (!response.ok) {
138
+ const envelope = await response.json().catch(() => null);
139
+ throw new Error(envelope?.error?.message ?? `Connect bridge returned ${response.status}`);
140
+ }
141
+ return response;
142
+ }, [basePath, fetchImpl]);
127
143
  const refresh = (0, react_1.useCallback)(async () => {
128
144
  cache.current.clear();
129
145
  try {
@@ -135,7 +151,7 @@ function ConnectProvider({ clientId = "", basePath = "/api/connect", redirectUri
135
151
  // error, so a Login button still renders rather than the UI hanging on
136
152
  // skeletons forever.
137
153
  setResult({
138
- session: { user: null, subscription: null, serviceRole: null },
154
+ session: { user: null, subscription: null, applicationRole: null, audience: null },
139
155
  error: cause instanceof Error ? cause.message : "Could not reach Connect",
140
156
  });
141
157
  }
@@ -184,7 +200,7 @@ function ConnectProvider({ clientId = "", basePath = "/api/connect", redirectUri
184
200
  credentials: "same-origin",
185
201
  }).catch(() => { });
186
202
  cache.current.clear();
187
- setResult({ session: { user: null, subscription: null, serviceRole: null }, error: null });
203
+ setResult({ session: { user: null, subscription: null, applicationRole: null, audience: null }, error: null });
188
204
  }, [basePath, fetchImpl]);
189
205
  const value = (0, react_1.useMemo)(() => ({
190
206
  clientId,
@@ -198,6 +214,7 @@ function ConnectProvider({ clientId = "", basePath = "/api/connect", redirectUri
198
214
  fetchResource,
199
215
  mutateResource,
200
216
  invalidateResource,
217
+ streamResource,
201
218
  }), [
202
219
  clientId,
203
220
  appUrl,
@@ -210,6 +227,7 @@ function ConnectProvider({ clientId = "", basePath = "/api/connect", redirectUri
210
227
  fetchResource,
211
228
  mutateResource,
212
229
  invalidateResource,
230
+ streamResource,
213
231
  ]);
214
232
  return (0, jsx_runtime_1.jsx)(ConnectContext.Provider, { value: value, children: children });
215
233
  }
@@ -224,6 +242,31 @@ function useConnect() {
224
242
  function useConnectUser() {
225
243
  return useConnect().session?.user ?? null;
226
244
  }
245
+ /**
246
+ * Whether the signed-in workspace is a one-seat personal account or a team -
247
+ * `null` while the session is loading or signed out.
248
+ *
249
+ * Branch on this to stop rendering team UI at a solo account: a members
250
+ * table, an invite button and a seat meter are all dead controls on an
251
+ * `"individual"` workspace, which has exactly one seat and cannot gain
252
+ * another. `<ConnectWorkspaceTypeGate>` is the declarative form.
253
+ */
254
+ function useConnectWorkspaceType() {
255
+ return useConnect().session?.user?.workspaceType ?? null;
256
+ }
257
+ /**
258
+ * Whether this account is the kind your application is sold to - `null` while
259
+ * the session is loading or signed out.
260
+ *
261
+ * `audience.matches === false` is a hard block, not a hint: readiness reports
262
+ * `audience_mismatch` and subscribing is refused. `<ConnectAccessGate>`
263
+ * already blocks the shell on it, so reach for this only when you need the
264
+ * verdict somewhere the gate does not run - a marketing page, say, or a
265
+ * sign-up CTA you would rather not show to an account that cannot complete it.
266
+ */
267
+ function useConnectAudience() {
268
+ return useConnect().session?.audience ?? null;
269
+ }
227
270
  /** Readiness gates and the live subscription, fetched on first use. */
228
271
  function useConnectEntitlements() {
229
272
  return useConnectResource("/entitlements");
@@ -231,28 +274,28 @@ function useConnectEntitlements() {
231
274
  /**
232
275
  * What is left of every consumable add-on on this workspace's subscription.
233
276
  *
234
- * The read half of `client.billing.consumeAddon` - a service that meters its
277
+ * The read half of `client.billing.consumeAddon` - an application that meters its
235
278
  * own end users had no way to show them what remained until this existed.
236
279
  * Empty `addons` means there is nothing to meter, which is not an error.
237
280
  */
238
281
  function useConnectAddonUsage() {
239
282
  return useConnectResource("/addons");
240
283
  }
241
- /** This service's plan catalog. */
284
+ /** This application's plan catalog. */
242
285
  function useConnectPlans() {
243
286
  return useConnectResource("/plans");
244
287
  }
245
- /** The apps this organization can open. */
288
+ /** The apps this workspace can open. */
246
289
  function useConnectApps() {
247
290
  return useConnectResource("/apps");
248
291
  }
249
- /** Enabled Composio-hosted toolkits and this organization's connection status for each. */
292
+ /** Enabled Composio-hosted toolkits and this workspace's connection status for each. */
250
293
  function useConnectIntegrations() {
251
294
  return useConnectResource("/integrations");
252
295
  }
253
296
  /**
254
297
  * This Connect account's own login sessions - account-wide, not scoped to
255
- * this service, see `SessionsListResponse`'s doc comment. The component
298
+ * this application, see `SessionsListResponse`'s doc comment. The component
256
299
  * that calls this is also the one that must own any revoke actions and call
257
300
  * the returned `refetch()` afterward - see `mutateResource`'s doc comment
258
301
  * for why nothing does that automatically.
@@ -157,15 +157,15 @@ function buildCancelUrl({ appUrl, subscriptionId }) {
157
157
  * The Connect URL that completes a subscribe or a plan change.
158
158
  *
159
159
  * Both land on a modal Connect renders over the relevant page (an intercepted
160
- * parallel route - `app/@modal/(.)services/...` and
160
+ * parallel route - `app/@modal/(.)applications/...` and
161
161
  * `app/@modal/(.)billing/...`), so the customer arrives already looking at the
162
162
  * confirmation for the plan they picked here, not at a catalogue they have to
163
163
  * find it in again.
164
164
  */
165
- function buildCheckoutUrl({ appUrl, serviceId, planId, subscriptionId, coupon, }) {
165
+ function buildCheckoutUrl({ appUrl, applicationId, planId, subscriptionId, coupon, }) {
166
166
  const path = subscriptionId
167
167
  ? `/billing/subscriptions/${encodeURIComponent(subscriptionId)}/change-plan/${encodeURIComponent(planId)}`
168
- : `/services/${encodeURIComponent(serviceId)}/subscribe/${encodeURIComponent(planId)}`;
168
+ : `/applications/${encodeURIComponent(applicationId)}/subscribe/${encodeURIComponent(planId)}`;
169
169
  const url = new URL(path, appUrl);
170
170
  if (coupon?.trim())
171
171
  url.searchParams.set("coupon", coupon.trim());
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConnectError = void 0;
4
4
  exports.isConnectError = isConnectError;
5
5
  /**
6
- * Every failure the Connect service API can report, as one class.
6
+ * Every failure the Connect application API can report, as one class.
7
7
  *
8
8
  * The API speaks two error dialects and this collapses them: the
9
- * `/api/v1/service/*` endpoints use `{ error: { code, message } }`, while the
9
+ * `/api/v1/application/*` endpoints use `{ error: { code, message } }`, while the
10
10
  * three `/sso/*` ones use OAuth2's `{ error, error_description }` (RFC 6749
11
11
  * §5.2). Both land here with `code` populated, so integrating code branches on
12
12
  * one field either way.
@@ -45,7 +45,7 @@ class ConnectError extends Error {
45
45
  * Whether the user's Connect sign-in is over and they need to go back
46
46
  * through `identity.authorizeUrl()`. Collapses every session-side failure,
47
47
  * matching how the API reports them - unknown, expired, revoked, or issued
48
- * to a different service all arrive as one `invalid_token`.
48
+ * to a different application all arrive as one `invalid_token`.
49
49
  */
50
50
  get isSessionExpired() {
51
51
  return this.code === "invalid_token";
@@ -59,7 +59,7 @@ class ConnectError extends Error {
59
59
  * guessing keys. These two are the exception: reaching them required
60
60
  * presenting a key whose hash matched, so you already hold it, and what you
61
61
  * need to know is that no retry and no scope change will fix this - the key
62
- * has to be reissued from the service's Integration tab.
62
+ * has to be reissued from the application's Integration tab.
63
63
  *
64
64
  * Worth alerting on. It is the one failure that will not resolve itself and
65
65
  * takes down every call your integration makes.
@@ -16,7 +16,7 @@ function blockingBlockers(readiness) {
16
16
  * Coerces either wire shape into `PlanFeature[]`.
17
17
  *
18
18
  * A bare key becomes `{ key, name: key, description: "" }` - the same
19
- * fallback the server applies for a plan older than its service's feature
19
+ * fallback the server applies for a plan older than its application's feature
20
20
  * catalog, so an un-upgraded Connect renders exactly what it always did
21
21
  * rather than a column of blanks.
22
22
  *
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizePlanFeatures = exports.blockingBlockers = exports.isConnectError = exports.ConnectError = void 0;
4
4
  /**
5
5
  * `@cosmoops/connect-sdk` - the official client for the CosmoOps Connect
6
- * **service-partner API** (`/api/v1/service/*`).
6
+ * **application-partner API** (`/api/v1/application/*`).
7
7
  *
8
8
  * This root entry is the isomorphic surface: wire types, the error class, and
9
9
  * pure helpers. It pulls in neither Node-only code nor React, so it is safe to
@@ -82,7 +82,7 @@ const handler_js_1 = require("../server/handler.js");
82
82
  * | `CONNECT_SESSION_COOKIE` | no | session cookie name |
83
83
  *
84
84
  * Register `{your origin}/api/connect/callback` as a redirect URI in the
85
- * service's Integration tab. That is the only step this cannot do for you.
85
+ * application's Integration tab. That is the only step this cannot do for you.
86
86
  *
87
87
  * No `next.config.ts` changes needed either, including `transpilePackages`:
88
88
  * `dist/` is already ES2022 with `"use client"` hoisted to the top of every
@@ -317,7 +317,7 @@ async function getConnectSession(request, options = {}) {
317
317
  * A thin wrapper, not a framework of its own - reach for `getConnectSession`
318
318
  * plus your own check when "not signed in" isn't "redirect to sign-in"
319
319
  * (an API route returning 401, say). Role and entitlement checks stay
320
- * outside this function on purpose: `session.serviceRole.granted` and
320
+ * outside this function on purpose: `session.applicationRole.granted` and
321
321
  * `connect.entitlements.*` are one line each on top of the session this
322
322
  * already gives you, and where that line redirects (a plans page, a
323
323
  * "forbidden" screen) is a decision only your app can make - see
@@ -14,7 +14,7 @@ const analytics_js_1 = require("./resources/analytics.js");
14
14
  const otp_js_1 = require("./resources/otp.js");
15
15
  const sessions_js_1 = require("./resources/sessions.js");
16
16
  exports.DEFAULT_BASE_URL = "https://connect.cosmoops.com";
17
- const SERVICE_API_PREFIX = "/api/v1/service";
17
+ const APPLICATION_API_PREFIX = "/api/v1/application";
18
18
  /**
19
19
  * Refuses to build a client in a browser.
20
20
  *
@@ -43,9 +43,9 @@ function assertNotBrowser() {
43
43
  "in browser code instead; it talks to your own origin and holds no credential.");
44
44
  }
45
45
  /**
46
- * The CosmoOps Connect service-partner API.
46
+ * The CosmoOps Connect application-partner API.
47
47
  *
48
- * Covers `/api/v1/service/*` and nothing else - the surface a service platform
48
+ * Covers `/api/v1/application/*` and nothing else - the surface an application platform
49
49
  * integrates against. Connect's internal API is not part of this package and
50
50
  * never will be.
51
51
  *
@@ -56,7 +56,7 @@ function assertNotBrowser() {
56
56
  * });
57
57
  *
58
58
  * const session = await connect.identity.exchangeCode({ code, redirectUri });
59
- * const { ready } = await connect.entitlements.getReadiness(session.user.organizationId);
59
+ * const { ready } = await connect.entitlements.getReadiness(session.user.workspaceId);
60
60
  * ```
61
61
  *
62
62
  * Every failure throws a `ConnectError` carrying a stable `code`. Nothing here
@@ -65,27 +65,27 @@ function assertNotBrowser() {
65
65
  class ConnectClient {
66
66
  /** "Login with Connect" - the OAuth2 handshake and the session after it. */
67
67
  identity;
68
- /** What a signed-in member may do on your service. */
68
+ /** What a signed-in member may do on your application. */
69
69
  access;
70
- /** The services an organization can open - for a launcher grid. */
70
+ /** The applications a workspace can open - for a launcher grid. */
71
71
  apps;
72
- /** Whether a workspace may use your service, and on what plan. */
72
+ /** Whether a workspace may use your application, and on what plan. */
73
73
  entitlements;
74
74
  /** Your plan catalog, and metering usage against add-on balances. */
75
75
  billing;
76
- /** Files in an organization's Drive. */
76
+ /** Files in a workspace's Drive. */
77
77
  drive;
78
78
  /** RAG chat and structured extraction. */
79
79
  ai;
80
80
  /** WhatsApp/SMS phone verification. */
81
81
  otp;
82
- /** Feature events into the Console's audit log, filterable to your service. */
82
+ /** Feature events into the Console's audit log, filterable to your application. */
83
83
  logs;
84
- /** Emit product events and read back this service's aggregated numbers. */
84
+ /** Emit product events and read back this application's aggregated numbers. */
85
85
  analytics;
86
- /** This Connect account's own login sessions - account-wide, not scoped to this service. Requires the `sessions:manage` scope. */
86
+ /** This Connect account's own login sessions - account-wide, not scoped to this application. Requires the `sessions:manage` scope. */
87
87
  sessions;
88
- /** Composio-hosted third-party connections (Google Calendar, Slack, ...) an organization has connected. */
88
+ /** Composio-hosted third-party connections (Google Calendar, Slack, ...) a workspace has connected. */
89
89
  integrations;
90
90
  constructor(options) {
91
91
  assertNotBrowser();
@@ -94,7 +94,7 @@ class ConnectClient {
94
94
  }
95
95
  const appBaseUrl = (options.baseUrl ?? exports.DEFAULT_BASE_URL).replace(/\/+$/, "");
96
96
  const transport = {
97
- baseUrl: `${appBaseUrl}${SERVICE_API_PREFIX}`,
97
+ baseUrl: `${appBaseUrl}${APPLICATION_API_PREFIX}`,
98
98
  apiKey: options.apiKey,
99
99
  timeoutMs: options.timeoutMs ?? 20_000,
100
100
  maxRetries: options.maxRetries ?? 2,
@@ -102,7 +102,7 @@ class ConnectClient {
102
102
  userAgent: `cosmoops-connect-sdk/${exports.SDK_VERSION}`,
103
103
  };
104
104
  // `authorizeUrl` points at the app, not the API prefix - it is a browser
105
- // redirect, not a service call, so identity takes both.
105
+ // redirect, not an application call, so identity takes both.
106
106
  this.identity = new identity_js_1.IdentityResource(transport, options.clientId ?? null, appBaseUrl);
107
107
  this.access = new access_js_1.AccessResource(transport);
108
108
  this.apps = new apps_js_1.AppsResource(transport);
@@ -119,4 +119,4 @@ class ConnectClient {
119
119
  }
120
120
  exports.ConnectClient = ConnectClient;
121
121
  /** Kept in step with `package.json` by `sdk.test.ts`. */
122
- exports.SDK_VERSION = "0.6.0";
122
+ exports.SDK_VERSION = "0.9.0";