@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.
- package/dist/cjs/cli/doctor.js +3 -3
- package/dist/cjs/cli/init.js +3 -3
- package/dist/cjs/client/components/access-gate.js +3 -3
- package/dist/cjs/client/components/account-sessions.js +3 -3
- package/dist/cjs/client/components/app-shell.js +2 -2
- package/dist/cjs/client/components/apps-grid.js +3 -3
- package/dist/cjs/client/components/feature-gate.js +2 -2
- package/dist/cjs/client/components/integrations-modal.js +1 -1
- package/dist/cjs/client/components/logo.js +3 -3
- package/dist/cjs/client/components/plan-pricing.js +1 -1
- package/dist/cjs/client/components/plans.js +6 -6
- package/dist/cjs/client/components/readiness.js +3 -3
- package/dist/cjs/client/components/subscribe-dialog.js +2 -2
- package/dist/cjs/client/components/subscription.js +1 -1
- package/dist/cjs/client/components/usage-meter.js +1 -1
- package/dist/cjs/client/components/user-menu.js +4 -4
- package/dist/cjs/client/index.js +1 -1
- package/dist/cjs/client/mark.js +1 -1
- package/dist/cjs/client/provider.js +7 -7
- package/dist/cjs/client/use-checkout.js +3 -3
- package/dist/cjs/errors.js +4 -4
- package/dist/cjs/helpers.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/next/index.js +2 -2
- package/dist/cjs/server/client.js +15 -15
- package/dist/cjs/server/handler.js +13 -13
- package/dist/cjs/server/http.js +1 -1
- package/dist/cjs/server/resources/access.js +3 -3
- package/dist/cjs/server/resources/ai.js +1 -1
- package/dist/cjs/server/resources/analytics.js +2 -2
- package/dist/cjs/server/resources/apps.js +4 -4
- package/dist/cjs/server/resources/billing.js +5 -5
- package/dist/cjs/server/resources/drive.js +4 -4
- package/dist/cjs/server/resources/entitlements.js +7 -7
- package/dist/cjs/server/resources/identity.js +4 -4
- package/dist/cjs/server/resources/integrations.js +13 -13
- package/dist/cjs/server/resources/logs.js +3 -3
- package/dist/cjs/server/resources/sessions.js +6 -6
- package/dist/cjs/server/webhooks.js +4 -4
- package/dist/cjs/types.js +1 -1
- package/dist/esm/cli/doctor.js +3 -3
- package/dist/esm/cli/init.js +3 -3
- package/dist/esm/client/components/access-gate.js +3 -3
- package/dist/esm/client/components/account-sessions.js +3 -3
- package/dist/esm/client/components/app-shell.js +2 -2
- package/dist/esm/client/components/apps-grid.js +3 -3
- package/dist/esm/client/components/feature-gate.js +2 -2
- package/dist/esm/client/components/integrations-modal.js +1 -1
- package/dist/esm/client/components/logo.js +3 -3
- package/dist/esm/client/components/plan-pricing.js +1 -1
- package/dist/esm/client/components/plans.js +6 -6
- package/dist/esm/client/components/readiness.js +3 -3
- package/dist/esm/client/components/subscribe-dialog.js +2 -2
- package/dist/esm/client/components/subscription.js +1 -1
- package/dist/esm/client/components/usage-meter.js +1 -1
- package/dist/esm/client/components/user-menu.js +4 -4
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/client/mark.js +1 -1
- package/dist/esm/client/provider.js +7 -7
- package/dist/esm/client/use-checkout.js +3 -3
- package/dist/esm/errors.js +4 -4
- package/dist/esm/helpers.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/next/index.js +2 -2
- package/dist/esm/server/client.js +15 -15
- package/dist/esm/server/handler.js +13 -13
- package/dist/esm/server/http.js +1 -1
- package/dist/esm/server/resources/access.js +3 -3
- package/dist/esm/server/resources/ai.js +1 -1
- package/dist/esm/server/resources/analytics.js +2 -2
- package/dist/esm/server/resources/apps.js +4 -4
- package/dist/esm/server/resources/billing.js +5 -5
- package/dist/esm/server/resources/drive.js +4 -4
- package/dist/esm/server/resources/entitlements.js +7 -7
- package/dist/esm/server/resources/identity.js +4 -4
- package/dist/esm/server/resources/integrations.js +13 -13
- package/dist/esm/server/resources/logs.js +3 -3
- package/dist/esm/server/resources/sessions.js +6 -6
- package/dist/esm/server/webhooks.js +4 -4
- package/dist/esm/types.js +1 -1
- package/dist/types/client/components/access-gate.d.ts +1 -1
- package/dist/types/client/components/account-sessions.d.ts +1 -1
- package/dist/types/client/components/app-shell.d.ts +4 -4
- package/dist/types/client/components/apps-grid.d.ts +1 -1
- package/dist/types/client/components/feature-gate.d.ts +1 -1
- package/dist/types/client/components/integrations-modal.d.ts +1 -1
- package/dist/types/client/components/logo.d.ts +5 -5
- package/dist/types/client/components/plan-pricing.d.ts +2 -2
- package/dist/types/client/components/readiness.d.ts +2 -2
- package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
- package/dist/types/client/components/usage-meter.d.ts +1 -1
- package/dist/types/client/components/user-menu.d.ts +2 -2
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/mark.d.ts +1 -1
- package/dist/types/client/provider.d.ts +9 -9
- package/dist/types/client/use-checkout.d.ts +3 -3
- package/dist/types/errors.d.ts +4 -4
- package/dist/types/helpers.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/next/index.d.ts +1 -1
- package/dist/types/server/client.d.ts +13 -13
- package/dist/types/server/handler.d.ts +2 -2
- package/dist/types/server/resources/access.d.ts +3 -3
- package/dist/types/server/resources/ai.d.ts +2 -2
- package/dist/types/server/resources/analytics.d.ts +2 -2
- package/dist/types/server/resources/apps.d.ts +4 -4
- package/dist/types/server/resources/billing.d.ts +4 -4
- package/dist/types/server/resources/drive.d.ts +4 -4
- package/dist/types/server/resources/entitlements.d.ts +4 -4
- package/dist/types/server/resources/identity.d.ts +2 -2
- package/dist/types/server/resources/integrations.d.ts +9 -9
- package/dist/types/server/resources/logs.d.ts +3 -3
- package/dist/types/server/resources/sessions.d.ts +5 -5
- package/dist/types/server/webhooks.d.ts +4 -4
- package/dist/types/types.d.ts +61 -61
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
46
|
+
* The CosmoOps Connect application-partner API.
|
|
47
47
|
*
|
|
48
|
-
* Covers `/api/v1/
|
|
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.
|
|
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
|
|
68
|
+
/** What a signed-in member may do on your application. */
|
|
69
69
|
access;
|
|
70
|
-
/** The
|
|
70
|
+
/** The applications a workspace can open - for a launcher grid. */
|
|
71
71
|
apps;
|
|
72
|
-
/** Whether a workspace may use your
|
|
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
|
|
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
|
|
82
|
+
/** Feature events into the Console's audit log, filterable to your application. */
|
|
83
83
|
logs;
|
|
84
|
-
/** Emit product events and read back this
|
|
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
|
|
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, ...)
|
|
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}${
|
|
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
|
|
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.
|
|
122
|
+
exports.SDK_VERSION = "0.7.0";
|
|
@@ -94,9 +94,9 @@ function redirect(location, cookies = []) {
|
|
|
94
94
|
* export { handler as GET, handler as POST };
|
|
95
95
|
* ```
|
|
96
96
|
*
|
|
97
|
-
* Every route resolves the
|
|
97
|
+
* Every route resolves the workspace from the caller's *own* session, never
|
|
98
98
|
* from a query parameter. A browser must not be able to ask about an
|
|
99
|
-
*
|
|
99
|
+
* workspace it is not signed into, and a client-supplied `workspaceId`
|
|
100
100
|
* is exactly that hole.
|
|
101
101
|
*/
|
|
102
102
|
function createConnectHandler(options) {
|
|
@@ -163,7 +163,7 @@ function createConnectHandler(options) {
|
|
|
163
163
|
}
|
|
164
164
|
return token;
|
|
165
165
|
}
|
|
166
|
-
/** Signed-in identity plus the
|
|
166
|
+
/** Signed-in identity plus the workspace it belongs to - the first read every other route needs. */
|
|
167
167
|
async function whoami(request) {
|
|
168
168
|
return client.identity.getUser(await requireToken(request));
|
|
169
169
|
}
|
|
@@ -173,32 +173,32 @@ function createConnectHandler(options) {
|
|
|
173
173
|
// Signed out is a normal state for a page rendering a Login button, not
|
|
174
174
|
// an error - `user: null` rather than a 401 the client must catch.
|
|
175
175
|
if (!token)
|
|
176
|
-
return json({ user: null, subscription: null,
|
|
176
|
+
return json({ user: null, subscription: null, applicationRole: null });
|
|
177
177
|
return json(await client.identity.getUser(token));
|
|
178
178
|
},
|
|
179
179
|
"GET /entitlements": async (request) => {
|
|
180
180
|
const { user } = await whoami(request);
|
|
181
181
|
const [readiness, subscription] = await Promise.all([
|
|
182
|
-
client.entitlements.getReadiness(user.
|
|
183
|
-
client.entitlements.getSubscription(user.
|
|
182
|
+
client.entitlements.getReadiness(user.workspaceId),
|
|
183
|
+
client.entitlements.getSubscription(user.workspaceId),
|
|
184
184
|
]);
|
|
185
185
|
return json({ readiness, subscription });
|
|
186
186
|
},
|
|
187
187
|
"GET /plans": async () => json(await client.billing.listPlans()),
|
|
188
|
-
//
|
|
188
|
+
// Workspace comes from the caller's own session, same as every other
|
|
189
189
|
// route here - a browser must not be able to ask what another workspace
|
|
190
190
|
// has left.
|
|
191
191
|
"GET /addons": async (request) => {
|
|
192
192
|
const { user } = await whoami(request);
|
|
193
|
-
return json(await client.billing.getAddonUsage(user.
|
|
193
|
+
return json(await client.billing.getAddonUsage(user.workspaceId));
|
|
194
194
|
},
|
|
195
195
|
"GET /apps": async (request) => {
|
|
196
196
|
const { user } = await whoami(request);
|
|
197
|
-
return json({ apps: await client.apps.list(user.
|
|
197
|
+
return json({ apps: await client.apps.list(user.workspaceId) });
|
|
198
198
|
},
|
|
199
199
|
"GET /integrations": async (request) => {
|
|
200
200
|
const { user } = await whoami(request);
|
|
201
|
-
return json({ toolkits: await client.integrations.list(user.
|
|
201
|
+
return json({ toolkits: await client.integrations.list(user.workspaceId) });
|
|
202
202
|
},
|
|
203
203
|
"POST /integrations/connect": async (request) => {
|
|
204
204
|
const { user } = await whoami(request);
|
|
@@ -211,7 +211,7 @@ function createConnectHandler(options) {
|
|
|
211
211
|
endpoint: "POST /integrations/connect",
|
|
212
212
|
});
|
|
213
213
|
}
|
|
214
|
-
return json(await client.integrations.initiateConnect(user.
|
|
214
|
+
return json(await client.integrations.initiateConnect(user.workspaceId, body.toolkitSlug, body.returnUrl));
|
|
215
215
|
},
|
|
216
216
|
"POST /integrations/disconnect": async (request) => {
|
|
217
217
|
const { user } = await whoami(request);
|
|
@@ -224,10 +224,10 @@ function createConnectHandler(options) {
|
|
|
224
224
|
endpoint: "POST /integrations/disconnect",
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
|
-
await client.integrations.disconnect(user.
|
|
227
|
+
await client.integrations.disconnect(user.workspaceId, body.toolkitSlug);
|
|
228
228
|
return json({ ok: true });
|
|
229
229
|
},
|
|
230
|
-
// Account-wide, not scoped to this
|
|
230
|
+
// Account-wide, not scoped to this application - see `SessionsResource`'s
|
|
231
231
|
// doc comment. `requireToken` alone identifies the caller; the target
|
|
232
232
|
// `sessionId` on the revoke routes travels in the JSON body, not the
|
|
233
233
|
// URL, so the exact-match routes table above never needs a dynamic
|
package/dist/cjs/server/http.js
CHANGED
|
@@ -44,7 +44,7 @@ function parseRetryAfterMs(response) {
|
|
|
44
44
|
return Number.isFinite(seconds) ? Math.max(0, seconds) * 1000 : null;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Both error dialects, one shape. `/api/v1/
|
|
47
|
+
* Both error dialects, one shape. `/api/v1/application/*` answers
|
|
48
48
|
* `{ error: { code, message } }`; the `/sso/*` endpoints answer OAuth2's
|
|
49
49
|
* `{ error, error_description }`.
|
|
50
50
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AccessResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
|
-
/** What a signed-in member may do on your
|
|
5
|
+
/** What a signed-in member may do on your application, and the role catalog behind it. */
|
|
6
6
|
class AccessResource {
|
|
7
7
|
transport;
|
|
8
8
|
constructor(transport) {
|
|
@@ -17,10 +17,10 @@ class AccessResource {
|
|
|
17
17
|
return (0, http_js_1.request)(this.transport, {
|
|
18
18
|
method: "GET",
|
|
19
19
|
path: `/rbac/users/${(0, http_js_1.pathSegment)(userId, "userId")}/roles`,
|
|
20
|
-
query: {
|
|
20
|
+
query: { workspaceId: input.workspaceId },
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
/** Your
|
|
23
|
+
/** Your application's own permission catalog and role definitions - the definitions `getUserRoles` resolves against. */
|
|
24
24
|
listRoles() {
|
|
25
25
|
return (0, http_js_1.request)(this.transport, { method: "GET", path: "/roles" });
|
|
26
26
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AiResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
|
-
/** RAG chat and structured extraction against
|
|
5
|
+
/** RAG chat and structured extraction against a workspace's data. */
|
|
6
6
|
class AiResource {
|
|
7
7
|
transport;
|
|
8
8
|
constructor(transport) {
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AnalyticsResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
5
|
/**
|
|
6
|
-
* Your
|
|
6
|
+
* Your application's own analytics: emit product events, and read back the daily
|
|
7
7
|
* numbers Connect aggregates from them.
|
|
8
8
|
*
|
|
9
|
-
* There is no way to name
|
|
9
|
+
* There is no way to name an application in either call. The scope is always the one
|
|
10
10
|
* your API key belongs to - that is the endpoint's security model, not an
|
|
11
11
|
* omission.
|
|
12
12
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AppsResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
|
-
/** The
|
|
5
|
+
/** The applications a workspace can open - the data behind a launcher grid. */
|
|
6
6
|
class AppsResource {
|
|
7
7
|
transport;
|
|
8
8
|
constructor(transport) {
|
|
@@ -10,13 +10,13 @@ class AppsResource {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* Launchable apps only, so a grid tile is never a dead end. The calling
|
|
13
|
-
*
|
|
13
|
+
* application is included and flagged `isCurrent` rather than filtered out.
|
|
14
14
|
*/
|
|
15
|
-
async list(
|
|
15
|
+
async list(workspaceId) {
|
|
16
16
|
const result = await (0, http_js_1.request)(this.transport, {
|
|
17
17
|
method: "GET",
|
|
18
18
|
path: "/apps",
|
|
19
|
-
query: {
|
|
19
|
+
query: { workspaceId },
|
|
20
20
|
});
|
|
21
21
|
// `?? []` for the same reason `billing.listPlans` has it: this is a
|
|
22
22
|
// collection every caller immediately maps or measures, and a body without
|
|
@@ -10,7 +10,7 @@ class BillingResource {
|
|
|
10
10
|
this.transport = transport;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Your
|
|
13
|
+
* Your application's active plans - render live pricing instead of hardcoding it.
|
|
14
14
|
*
|
|
15
15
|
* `features` is normalised on the way out: Connect used to send bare keys
|
|
16
16
|
* and now sends `{ key, name, description }`, and this SDK is versioned
|
|
@@ -28,7 +28,7 @@ class BillingResource {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* What is left of every consumable add-on on
|
|
31
|
+
* What is left of every consumable add-on on a workspace's
|
|
32
32
|
* subscription - the read half of `consumeAddon`.
|
|
33
33
|
*
|
|
34
34
|
* Needs a key scoped to `addons:read`, which is separate from
|
|
@@ -38,10 +38,10 @@ class BillingResource {
|
|
|
38
38
|
* Returns an empty `addons` array rather than throwing when there is
|
|
39
39
|
* nothing to meter, so a caller can render it unconditionally.
|
|
40
40
|
*/
|
|
41
|
-
async getAddonUsage(
|
|
41
|
+
async getAddonUsage(workspaceId) {
|
|
42
42
|
const response = await (0, http_js_1.request)(this.transport, {
|
|
43
43
|
method: "GET",
|
|
44
|
-
path: `/addons/
|
|
44
|
+
path: `/addons/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
|
|
45
45
|
});
|
|
46
46
|
// Normalised, not passed through: the promise above resolves for any 2xx,
|
|
47
47
|
// and `ConnectUsageMeter` reads `addons` straight off it. A body without
|
|
@@ -52,7 +52,7 @@ class BillingResource {
|
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Debit a consumable add-on's per-cycle balance on behalf of an
|
|
55
|
-
*
|
|
55
|
+
* workspace's users. Call it at whatever cadence your usage happens.
|
|
56
56
|
*
|
|
57
57
|
* An `Idempotency-Key` is always sent, generated per call when you do not
|
|
58
58
|
* supply one: a balance cannot be un-spent, so a retried consume without a
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DriveResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
|
-
/** Files in
|
|
5
|
+
/** Files in a workspace's Drive - upload, and signed URLs to read back. */
|
|
6
6
|
class DriveResource {
|
|
7
7
|
transport;
|
|
8
8
|
constructor(transport) {
|
|
@@ -12,7 +12,7 @@ class DriveResource {
|
|
|
12
12
|
const form = new FormData();
|
|
13
13
|
const fileName = input.fileName ?? input.file.name ?? "upload";
|
|
14
14
|
form.set("file", input.file, fileName);
|
|
15
|
-
form.set("
|
|
15
|
+
form.set("workspaceId", input.workspaceId);
|
|
16
16
|
if (input.parentId)
|
|
17
17
|
form.set("parentId", input.parentId);
|
|
18
18
|
return (0, http_js_1.request)(this.transport, { method: "POST", path: "/drive/files", multipart: form });
|
|
@@ -22,7 +22,7 @@ class DriveResource {
|
|
|
22
22
|
const result = await (0, http_js_1.request)(this.transport, {
|
|
23
23
|
method: "GET",
|
|
24
24
|
path: `/drive/files/${(0, http_js_1.pathSegment)(fileId, "fileId")}/url`,
|
|
25
|
-
query: {
|
|
25
|
+
query: { workspaceId: input.workspaceId },
|
|
26
26
|
});
|
|
27
27
|
return result.url;
|
|
28
28
|
}
|
|
@@ -31,7 +31,7 @@ class DriveResource {
|
|
|
31
31
|
const result = await (0, http_js_1.request)(this.transport, {
|
|
32
32
|
method: "GET",
|
|
33
33
|
path: `/drive/files/${(0, http_js_1.pathSegment)(fileId, "fileId")}/preview-url`,
|
|
34
|
-
query: {
|
|
34
|
+
query: { workspaceId: input.workspaceId, size: input.size },
|
|
35
35
|
});
|
|
36
36
|
return result.url;
|
|
37
37
|
}
|
|
@@ -12,7 +12,7 @@ class EntitlementsResource {
|
|
|
12
12
|
this.transport = transport;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Every gate Connect owns between
|
|
15
|
+
* Every gate Connect owns between a workspace and your application -
|
|
16
16
|
* subscription, KYC/KYB, a chargeable payment method, seat headroom -
|
|
17
17
|
* resolved in one call.
|
|
18
18
|
*
|
|
@@ -20,17 +20,17 @@ class EntitlementsResource {
|
|
|
20
20
|
* Connect screen that fixes it, so you can route them somewhere useful
|
|
21
21
|
* instead of refusing them with nowhere to go.
|
|
22
22
|
*/
|
|
23
|
-
getReadiness(
|
|
23
|
+
getReadiness(workspaceId) {
|
|
24
24
|
return (0, http_js_1.request)(this.transport, {
|
|
25
25
|
method: "GET",
|
|
26
|
-
path: `/onboarding/
|
|
26
|
+
path: `/onboarding/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
/** The live plan and subscription, including `plan.features`. */
|
|
30
|
-
getSubscription(
|
|
30
|
+
getSubscription(workspaceId) {
|
|
31
31
|
return (0, http_js_1.request)(this.transport, {
|
|
32
32
|
method: "GET",
|
|
33
|
-
path: `/subscriptions/
|
|
33
|
+
path: `/subscriptions/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
@@ -41,8 +41,8 @@ class EntitlementsResource {
|
|
|
41
41
|
* all: "not entitled" is the same answer either way, and a feature gate
|
|
42
42
|
* should not need a try/catch around it.
|
|
43
43
|
*/
|
|
44
|
-
async hasFeature(
|
|
45
|
-
const result = await this.getSubscription(
|
|
44
|
+
async hasFeature(workspaceId, feature) {
|
|
45
|
+
const result = await this.getSubscription(workspaceId);
|
|
46
46
|
return result.hasActiveSubscription && (result.plan?.features.includes(feature) ?? false);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -70,7 +70,7 @@ class IdentityResource {
|
|
|
70
70
|
sessionTokenExpiresIn: wire.session_token_expires_in,
|
|
71
71
|
user: wire.user,
|
|
72
72
|
subscription: wire.subscription,
|
|
73
|
-
|
|
73
|
+
applicationRole: wire.applicationRole,
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
@@ -140,7 +140,7 @@ class IdentityResource {
|
|
|
140
140
|
return {
|
|
141
141
|
user: wire.user,
|
|
142
142
|
subscription: wire.subscription,
|
|
143
|
-
|
|
143
|
+
applicationRole: wire.applicationRole,
|
|
144
144
|
sessionExpiresAt: wire.session_expires_at,
|
|
145
145
|
};
|
|
146
146
|
}
|
|
@@ -149,7 +149,7 @@ class IdentityResource {
|
|
|
149
149
|
* rest of its ~15-day life. Discard your own copy of `sessionToken` too;
|
|
150
150
|
* this does not do that for you.
|
|
151
151
|
*
|
|
152
|
-
* `scope` defaults to `"device"`: this sign-in, every other
|
|
152
|
+
* `scope` defaults to `"device"`: this sign-in, every other application signed
|
|
153
153
|
* into from the same browser, and Connect's own session on that one device.
|
|
154
154
|
* `"all"` ends every session on every device - an explicit "sign out
|
|
155
155
|
* everywhere" action only.
|
|
@@ -181,7 +181,7 @@ class IdentityResource {
|
|
|
181
181
|
throw new errors_js_1.ConnectError({
|
|
182
182
|
status: 0,
|
|
183
183
|
code: "missing_client_id",
|
|
184
|
-
message: "identity.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this
|
|
184
|
+
message: "identity.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this application's Integration tab, under Connect client.",
|
|
185
185
|
endpoint: "identity",
|
|
186
186
|
});
|
|
187
187
|
}
|
|
@@ -4,8 +4,8 @@ exports.IntegrationsResource = void 0;
|
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
5
|
/**
|
|
6
6
|
* Composio-hosted third-party connections (Google Calendar, Slack,
|
|
7
|
-
* Twitter/X, ...)
|
|
8
|
-
* here - your
|
|
7
|
+
* Twitter/X, ...) a workspace has connected. Connect proxies every call
|
|
8
|
+
* here - your application never sees or holds the underlying OAuth token, which
|
|
9
9
|
* stays with Composio.
|
|
10
10
|
*/
|
|
11
11
|
class IntegrationsResource {
|
|
@@ -13,12 +13,12 @@ class IntegrationsResource {
|
|
|
13
13
|
constructor(transport) {
|
|
14
14
|
this.transport = transport;
|
|
15
15
|
}
|
|
16
|
-
/** Enabled toolkits and this
|
|
17
|
-
async list(
|
|
16
|
+
/** Enabled toolkits and this workspace's connection status for each. */
|
|
17
|
+
async list(workspaceId) {
|
|
18
18
|
const result = await (0, http_js_1.request)(this.transport, {
|
|
19
19
|
method: "GET",
|
|
20
20
|
path: "/integrations",
|
|
21
|
-
query: {
|
|
21
|
+
query: { workspaceId },
|
|
22
22
|
});
|
|
23
23
|
// `?? []` for the same reason `AppsResource.list` has it - a collection
|
|
24
24
|
// every caller immediately maps or measures.
|
|
@@ -35,31 +35,31 @@ class IntegrationsResource {
|
|
|
35
35
|
* itself. Reconnecting a disconnected/failed toolkit calls this same
|
|
36
36
|
* method - there is no separate reconnect.
|
|
37
37
|
*
|
|
38
|
-
* Meant to be called on behalf of a signed-in
|
|
38
|
+
* Meant to be called on behalf of a signed-in workspace admin (this is what the
|
|
39
39
|
* bridge's fixed `POST /integrations/connect` route does), not as a bare
|
|
40
40
|
* background action with no admin present to complete the OAuth screen.
|
|
41
41
|
*/
|
|
42
|
-
async initiateConnect(
|
|
42
|
+
async initiateConnect(workspaceId, toolkitSlug, returnUrl) {
|
|
43
43
|
return (0, http_js_1.request)(this.transport, {
|
|
44
44
|
method: "POST",
|
|
45
45
|
path: "/integrations/connect",
|
|
46
|
-
json: {
|
|
46
|
+
json: { workspaceId, toolkitSlug, returnUrl },
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
/** Idempotent - disconnecting a toolkit that was never connected, or is already disconnected, is a success. */
|
|
50
|
-
async disconnect(
|
|
50
|
+
async disconnect(workspaceId, toolkitSlug) {
|
|
51
51
|
return (0, http_js_1.request)(this.transport, {
|
|
52
52
|
method: "POST",
|
|
53
53
|
path: "/integrations/disconnect",
|
|
54
|
-
json: {
|
|
54
|
+
json: { workspaceId, toolkitSlug },
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
-
/** Calls a Composio action against this
|
|
58
|
-
async execute(
|
|
57
|
+
/** Calls a Composio action against this workspace's connected account for the named toolkit. */
|
|
58
|
+
async execute(workspaceId, input) {
|
|
59
59
|
return (0, http_js_1.request)(this.transport, {
|
|
60
60
|
method: "POST",
|
|
61
61
|
path: "/integrations/actions/execute",
|
|
62
|
-
json: {
|
|
62
|
+
json: { workspaceId, ...input },
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LogsResource = void 0;
|
|
4
4
|
const http_js_1 = require("../http.js");
|
|
5
|
-
/** Push feature events into the Console's audit log, filterable to your
|
|
5
|
+
/** Push feature events into the Console's audit log, filterable to your application. */
|
|
6
6
|
class LogsResource {
|
|
7
7
|
transport;
|
|
8
8
|
constructor(transport) {
|
|
@@ -14,9 +14,9 @@ class LogsResource {
|
|
|
14
14
|
* reported through the return value.
|
|
15
15
|
*
|
|
16
16
|
* Pass `sessionToken` to attribute the event to the end user it belongs to.
|
|
17
|
-
* Both scopes on the stored entry come from something verified - the
|
|
17
|
+
* Both scopes on the stored entry come from something verified - the application
|
|
18
18
|
* from your API key, the user from that token, which Connect checks was
|
|
19
|
-
* minted for your
|
|
19
|
+
* minted for your application before attributing anything. `attributed` in the
|
|
20
20
|
* result says whether it resolved; a `false` there still means the line was
|
|
21
21
|
* stored, just without a user on it.
|
|
22
22
|
*/
|
|
@@ -8,11 +8,11 @@ const http_js_1 = require("../http.js");
|
|
|
8
8
|
* timestamps - the same list Connect's own account settings page shows the
|
|
9
9
|
* user themselves.
|
|
10
10
|
*
|
|
11
|
-
* **Account-wide, not scoped to this
|
|
12
|
-
* browser's login to Connect, and it fans out to every partner
|
|
13
|
-
* `sessionToken` - Connect has no per-
|
|
11
|
+
* **Account-wide, not scoped to this application.** A Connect session is one
|
|
12
|
+
* browser's login to Connect, and it fans out to every partner application's own
|
|
13
|
+
* `sessionToken` - Connect has no per-application session concept to filter by.
|
|
14
14
|
* `list()` returns every session on the account, including ones that
|
|
15
|
-
* originated from a completely different, unrelated
|
|
15
|
+
* originated from a completely different, unrelated application. Requires the
|
|
16
16
|
* `sessions:manage` scope on your API key - unlike `identity`'s base `sso`
|
|
17
17
|
* capability, this is never granted to a zero-scope legacy key by default.
|
|
18
18
|
*
|
|
@@ -38,7 +38,7 @@ class SessionsResource {
|
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Ends one specific session by id - not necessarily the one `sessionToken`
|
|
41
|
-
* itself was minted from. Cascades to every partner-
|
|
41
|
+
* itself was minted from. Cascades to every partner-application sign-in that
|
|
42
42
|
* originated from that same browser, same as Connect's own "sign out this
|
|
43
43
|
* device".
|
|
44
44
|
*/
|
|
@@ -72,7 +72,7 @@ class SessionsResource {
|
|
|
72
72
|
throw new errors_js_1.ConnectError({
|
|
73
73
|
status: 0,
|
|
74
74
|
code: "missing_client_id",
|
|
75
|
-
message: "sessions.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this
|
|
75
|
+
message: "sessions.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this application's Integration tab, under Connect client.",
|
|
76
76
|
endpoint: "sessions",
|
|
77
77
|
});
|
|
78
78
|
}
|
|
@@ -58,10 +58,10 @@ function verifyConnectWebhook(rawBody, signatureHeader, secret, now = new Date()
|
|
|
58
58
|
* export const POST = createConnectWebhookHandler({
|
|
59
59
|
* secret: process.env.CONNECT_WEBHOOK_SECRET!,
|
|
60
60
|
* on: {
|
|
61
|
-
* "
|
|
62
|
-
* freeze(
|
|
63
|
-
* "
|
|
64
|
-
* "
|
|
61
|
+
* "workspace.deletion_scheduled": ({ workspaceId, purgeAfter }) =>
|
|
62
|
+
* freeze(workspaceId, purgeAfter),
|
|
63
|
+
* "workspace.deletion_cancelled": ({ workspaceId }) => unfreeze(workspaceId),
|
|
64
|
+
* "workspace.deleted": ({ workspaceId }) => purge(workspaceId),
|
|
65
65
|
* },
|
|
66
66
|
* })
|
|
67
67
|
* ```
|
package/dist/cjs/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Wire types for the `/api/v1/
|
|
3
|
+
* Wire types for the `/api/v1/application/*` surface - the application-partner API,
|
|
4
4
|
* and the only thing this SDK covers.
|
|
5
5
|
*
|
|
6
6
|
* Hand-written rather than generated so the published package carries no
|
package/dist/esm/cli/doctor.js
CHANGED
|
@@ -159,8 +159,8 @@ function checkEnv(root) {
|
|
|
159
159
|
status: "fail",
|
|
160
160
|
title: `${name} set`,
|
|
161
161
|
detail: declaredEmpty
|
|
162
|
-
? `Declared but empty in .env.local. The value is in your
|
|
163
|
-
: `Not found in .env.local or the environment. Both values are in your
|
|
162
|
+
? `Declared but empty in .env.local. The value is in your application's Integration tab in Connect.`
|
|
163
|
+
: `Not found in .env.local or the environment. Both values are in your application's Integration tab in Connect.`,
|
|
164
164
|
};
|
|
165
165
|
});
|
|
166
166
|
}
|
|
@@ -173,7 +173,7 @@ function checkRedirectUri() {
|
|
|
173
173
|
return {
|
|
174
174
|
status: "warn",
|
|
175
175
|
title: "Redirect URI registered in Connect",
|
|
176
|
-
detail: "Not checkable from here. Confirm {your origin}/api/connect/callback is listed as a redirect URI in your
|
|
176
|
+
detail: "Not checkable from here. Confirm {your origin}/api/connect/callback is listed as a redirect URI in your application's Integration tab - including the deployed origin, not just http://localhost:3000.",
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
const MARKER = { pass: " ok ", warn: " note ", fail: " FAIL " };
|
package/dist/esm/cli/init.js
CHANGED
|
@@ -39,7 +39,7 @@ const PLANS_PAGE = `"use client";
|
|
|
39
39
|
// with the other exports) whenever you want your own copy or layout.
|
|
40
40
|
export { ConnectPlansPage as default } from "@cosmoops/connect-sdk/client";
|
|
41
41
|
`;
|
|
42
|
-
const ENV_TEMPLATE = `# CosmoOps Connect - values come from your
|
|
42
|
+
const ENV_TEMPLATE = `# CosmoOps Connect - values come from your application's Integration tab.
|
|
43
43
|
CONNECT_API_KEY=
|
|
44
44
|
CONNECT_CLIENT_ID=
|
|
45
45
|
`;
|
|
@@ -106,7 +106,7 @@ export function runInit(argv = []) {
|
|
|
106
106
|
console.log(` ${marker} ${relative(root, target)} - ${scaffold.description}`);
|
|
107
107
|
}
|
|
108
108
|
const env = ensureEnv(root);
|
|
109
|
-
console.log(` ${env === "skipped" ? "exists " : env === "appended" ? "updated" : "created"} .env.local - fill in the two values from your
|
|
109
|
+
console.log(` ${env === "skipped" ? "exists " : env === "appended" ? "updated" : "created"} .env.local - fill in the two values from your application's Integration tab`);
|
|
110
110
|
// The two steps a scaffolder must not do for you: editing an existing layout
|
|
111
111
|
// means parsing and rewriting JSX someone else wrote, and the redirect URI
|
|
112
112
|
// lives in Connect, not in this repo.
|
|
@@ -132,7 +132,7 @@ Three things left, all one-time:
|
|
|
132
132
|
Tailwind roots its content scan inside node_modules and skips your app.
|
|
133
133
|
|
|
134
134
|
3. Register {your origin}/api/connect/callback as a redirect URI in your
|
|
135
|
-
|
|
135
|
+
application's Integration tab in Connect.
|
|
136
136
|
|
|
137
137
|
No next.config.ts changes needed - not even transpilePackages: dist/ is
|
|
138
138
|
already ES2022 with "use client" hoisted, so Turbopack and webpack consume it
|
|
@@ -43,7 +43,7 @@ export function useConnectAccessGate() {
|
|
|
43
43
|
}
|
|
44
44
|
const readiness = data.readiness;
|
|
45
45
|
const blocking = blockingBlockers(readiness);
|
|
46
|
-
const suspended = blocking.find((b) => b.code === "
|
|
46
|
+
const suspended = blocking.find((b) => b.code === "workspace_suspended");
|
|
47
47
|
if (suspended)
|
|
48
48
|
return { state: "suspended", blocker: suspended, paymentRetry: null };
|
|
49
49
|
const noSubscription = blocking.find((b) => b.code === "subscription_missing");
|
|
@@ -106,13 +106,13 @@ export function ConnectAccessGate({ children, fallback, loading, className }) {
|
|
|
106
106
|
}
|
|
107
107
|
function AccessGateFallback({ state, blocker, className, }) {
|
|
108
108
|
if (state === "no_subscription") {
|
|
109
|
-
return (_jsx(GateCard, { icon: CreditCard, iconClassName: "text-accent", title: "Choose a plan to continue", message: blocker?.message ?? "This workspace isn't subscribed to this
|
|
109
|
+
return (_jsx(GateCard, { icon: CreditCard, iconClassName: "text-accent", title: "Choose a plan to continue", message: blocker?.message ?? "This workspace isn't subscribed to this application yet.", actionLabel: "See plans", resolveUrl: blocker?.resolveUrl ?? null, className: className }));
|
|
110
110
|
}
|
|
111
111
|
if (state === "suspended") {
|
|
112
112
|
return (_jsx(GateCard, { icon: Ban, iconClassName: "text-danger", title: "Workspace suspended", message: blocker?.message ?? "This workspace has been suspended.", resolveUrl: null, className: className }));
|
|
113
113
|
}
|
|
114
114
|
if (state === "onboarding_pending") {
|
|
115
|
-
return (_jsx(GateCard, { icon: Clock, iconClassName: "text-muted", title: "Waiting on approval", message: blocker?.message ?? "This workspace is waiting on approval before it can use this
|
|
115
|
+
return (_jsx(GateCard, { icon: Clock, iconClassName: "text-muted", title: "Waiting on approval", message: blocker?.message ?? "This workspace is waiting on approval before it can use this application.", resolveUrl: null, className: className }));
|
|
116
116
|
}
|
|
117
117
|
// "blocked" - any other blocking code (verification, audience, seats, ...).
|
|
118
118
|
// Full fidelity for a code this component doesn't special-case: the same
|