@cboxdk/id-js 0.18.0 → 0.20.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 (39) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/README.md +121 -4
  3. package/RELEASE-CANDIDATE.md +11 -0
  4. package/dist/api-keys-BE3R3q_A.d.ts +105 -0
  5. package/dist/api-keys-C8-Q4eFA.d.cts +105 -0
  6. package/dist/chunk-EVZ6RB3K.js +98 -0
  7. package/dist/chunk-EVZ6RB3K.js.map +1 -0
  8. package/dist/{chunk-CXGKOJRJ.js → chunk-YGLMLIKL.js} +144 -9
  9. package/dist/chunk-YGLMLIKL.js.map +1 -0
  10. package/dist/{client-BxUHm5hX.d.cts → client-BT-jOm0p.d.cts} +126 -2
  11. package/dist/{client-BSZASrMo.d.ts → client-xlEJalu8.d.ts} +126 -2
  12. package/dist/decisions-C84Fzah4.d.ts +23 -0
  13. package/dist/decisions-DNd9UXwi.d.cts +23 -0
  14. package/dist/index.cjs +338 -28
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +84 -6
  17. package/dist/index.d.ts +84 -6
  18. package/dist/index.js +87 -15
  19. package/dist/index.js.map +1 -1
  20. package/dist/management.cjs +1115 -62
  21. package/dist/management.cjs.map +1 -1
  22. package/dist/management.d.cts +3618 -135
  23. package/dist/management.d.ts +3618 -135
  24. package/dist/management.js +1115 -63
  25. package/dist/management.js.map +1 -1
  26. package/dist/nextjs.cjs +136 -5
  27. package/dist/nextjs.cjs.map +1 -1
  28. package/dist/nextjs.d.cts +4 -3
  29. package/dist/nextjs.d.ts +4 -3
  30. package/dist/nextjs.js +1 -1
  31. package/dist/server.cjs +103 -9
  32. package/dist/server.cjs.map +1 -1
  33. package/dist/server.d.cts +3 -105
  34. package/dist/server.d.ts +3 -105
  35. package/dist/server.js +1 -0
  36. package/dist/{types-BYZldock.d.cts → types-CC1bz68x.d.cts} +30 -1
  37. package/dist/{types-BYZldock.d.ts → types-CC1bz68x.d.ts} +30 -1
  38. package/package.json +8 -3
  39. package/dist/chunk-CXGKOJRJ.js.map +0 -1
@@ -1,4 +1,5 @@
1
- import { a as CboxIdConfig, A as AuthorizationRequestOptions, b as AuthorizationRequest, C as CboxUser, D as DeviceAuthorization, R as RefreshedTokens, T as TokenTypeHint } from './types-BYZldock.cjs';
1
+ import { C as CboxIdError } from './errors-D61xljZE.cjs';
2
+ import { a as CboxIdConfig, A as AuthorizationRequestOptions, b as AuthorizationRequest, C as CboxUser, D as DeviceAuthorization, R as RefreshedTokens, T as TokenTypeHint } from './types-CC1bz68x.cjs';
2
3
 
3
4
  /** A stored vault secret's metadata (never its plaintext). */
4
5
  interface VaultSecretRef {
@@ -17,6 +18,98 @@ interface VaultLease {
17
18
  secret: string;
18
19
  expiresAt: string;
19
20
  }
21
+ /** A provider a pipe can connect to. */
22
+ type PipeProvider = 'github' | 'google' | 'microsoft' | 'slack' | 'salesforce' | 'hubspot' | 'linear' | 'notion';
23
+ /**
24
+ * A fresh access token for one person's connected account at a provider — what
25
+ * {@link VaultClient.leasePipeToken} returns. Use it, drop it, lease again next time.
26
+ */
27
+ interface PipeToken {
28
+ /** The provider's access token. Send it as a bearer token to the provider's API. */
29
+ accessToken: string;
30
+ tokenType: 'Bearer';
31
+ provider: string;
32
+ userId: string;
33
+ connectionId: string;
34
+ /** What the person consented to. */
35
+ scopes: string[];
36
+ /** When the PROVIDER stops accepting it; null for tokens that do not expire. */
37
+ expiresAt: string | null;
38
+ /** When to drop it and lease again. */
39
+ leaseExpiresAt: string;
40
+ /** What some providers need to be called at all — Salesforce's `instance_url`, Slack's `team.id`. */
41
+ metadata: Record<string, string>;
42
+ }
43
+ /** Where a person connects a provider, and where they come back to afterwards. */
44
+ interface PipeConnectOptions {
45
+ /** Your app's client id — the connect page shows its name and allows its origins. */
46
+ clientId?: string;
47
+ /**
48
+ * Where to land afterwards, with `?provider=…&status=connected|cancelled|failed`. Must be
49
+ * on one of the app's registered redirect origins, or it is ignored.
50
+ */
51
+ returnTo?: string;
52
+ }
53
+ /**
54
+ * Add `client_id` and `return_to` to a connect URL — the one a lease error carries, or
55
+ * one built with {@link pipeConnectUrl}.
56
+ */
57
+ declare function withConnectReturn(connectUrl: string, options?: PipeConnectOptions): string;
58
+ /**
59
+ * The hosted page where the signed-in person connects their account at `provider`:
60
+ * `{issuer}/account/connected-services/{provider}/connect?client_id=…&return_to=…`.
61
+ */
62
+ declare function pipeConnectUrl(issuer: string, provider: PipeProvider | string, options?: PipeConnectOptions): string;
63
+ /**
64
+ * A pipe token lease was refused. Catch the subclasses for the cases you can act on:
65
+ *
66
+ * - {@link PipeNotConnectedError} (404) and {@link PipeReauthorizationRequiredError}
67
+ * (409) — send the person to `connectUrl`.
68
+ * - {@link PipeTemporarilyUnavailableError} (503) — retry after `retryAfter` seconds.
69
+ * - {@link PipeLeaseDeniedError} (403) — a configuration problem: the app is not granted
70
+ * the pipe, it is disabled, or the person is outside the app's organization.
71
+ *
72
+ * Anything else (401, 422, 429) arrives as this base class with `status` and `error`.
73
+ */
74
+ declare class PipeLeaseError extends CboxIdError {
75
+ /** The server's error code, e.g. `not_connected`. */
76
+ readonly error: string | null;
77
+ readonly status: number;
78
+ /** Where to send the person to (re)connect — set on 404 and 409. */
79
+ readonly connectUrl: string | null;
80
+ /** Seconds to wait off `Retry-After`, when the server sent one. */
81
+ readonly retryAfter: number | null;
82
+ constructor(message: string,
83
+ /** The server's error code, e.g. `not_connected`. */
84
+ error: string | null, status: number,
85
+ /** Where to send the person to (re)connect — set on 404 and 409. */
86
+ connectUrl?: string | null,
87
+ /** Seconds to wait off `Retry-After`, when the server sent one. */
88
+ retryAfter?: number | null);
89
+ /** `connectUrl` with your `client_id` and `return_to` on it, or null when there is none. */
90
+ connectUrlWith(options: PipeConnectOptions): string | null;
91
+ }
92
+ /** The person has not connected this provider (404 `not_connected`). Send them to `connectUrl`. */
93
+ declare class PipeNotConnectedError extends PipeLeaseError {
94
+ readonly connectUrl: string;
95
+ }
96
+ /**
97
+ * The provider stopped accepting the connection — revoked, or the refresh token expired
98
+ * (409 `reauthorization_required`). Send the person to `connectUrl` to connect again.
99
+ */
100
+ declare class PipeReauthorizationRequiredError extends PipeLeaseError {
101
+ readonly connectUrl: string;
102
+ }
103
+ /** The provider could not refresh the token just now (503). Retry after `retryAfter`. */
104
+ declare class PipeTemporarilyUnavailableError extends PipeLeaseError {
105
+ }
106
+ /**
107
+ * The lease was denied (403 `lease_denied`): the app is not granted the pipe, the pipe is
108
+ * disabled or missing, the person is not in the app's organization, or `userId` names
109
+ * someone other than the token's person. One answer for every reason, by design.
110
+ */
111
+ declare class PipeLeaseDeniedError extends PipeLeaseError {
112
+ }
20
113
  interface StoreSecretInput {
21
114
  name: string;
22
115
  provider: string;
@@ -54,8 +147,32 @@ declare class VaultClient {
54
147
  * is identified by the token's client; a lease with no live grant is refused.
55
148
  */
56
149
  lease(secretId: string, purpose: string): Promise<VaultLease>;
150
+ /**
151
+ * Lease a fresh access token for a person's connected account at `provider` (Pipes,
152
+ * scope `vault.lease`). The token is refreshed first when it is about to expire, so
153
+ * you never handle a refresh token.
154
+ *
155
+ * With a client-credentials token, name the person in `userId`. With a token issued to
156
+ * your app FOR a person, leave it out — the lease is theirs.
157
+ *
158
+ * ```ts
159
+ * try {
160
+ * const { accessToken } = await vault.leasePipeToken('github', { userId, purpose: 'list-repos' })
161
+ * } catch (e) {
162
+ * if (e instanceof PipeNotConnectedError || e instanceof PipeReauthorizationRequiredError) {
163
+ * return redirect(e.connectUrlWith({ clientId, returnTo }))
164
+ * }
165
+ * throw e
166
+ * }
167
+ * ```
168
+ */
169
+ leasePipeToken(provider: PipeProvider | string, options: {
170
+ purpose: string;
171
+ userId?: string;
172
+ }): Promise<PipeToken>;
57
173
  private json;
58
174
  private request;
175
+ private send;
59
176
  }
60
177
 
61
178
  /**
@@ -259,6 +376,13 @@ declare class CboxIdClient {
259
376
  * registered. `organization` picks which of the person's organizations the keys act in;
260
377
  * omitted, the page uses the one they are in.
261
378
  */
379
+ /**
380
+ * The hosted page where the signed-in person connects their account at `provider`
381
+ * (Pipes) — `/account/connected-services/{provider}/connect`, preselected to this app.
382
+ * They come back to `returnTo` with `?provider=…&status=connected|cancelled|failed`,
383
+ * honoured only on an origin the app registered.
384
+ */
385
+ pipeConnectUrl(provider: PipeProvider | string, returnTo?: string): string;
262
386
  apiKeysUrl(options?: {
263
387
  clientId?: string;
264
388
  returnTo?: string;
@@ -338,4 +462,4 @@ declare class CboxIdClient {
338
462
  private fetchWithTimeout;
339
463
  }
340
464
 
341
- export { CboxIdClient as C, type StoreSecretInput as S, VaultClient as V, type WebhookHeaders as W, type CallbackParams as a, type StoredAuthState as b, type VaultLease as c, type VaultSecretRef as d, type VerifyStandardWebhookOptions as e, type VerifyWebhookOptions as f, verifyWebhook as g, verifyStandardWebhook as v };
465
+ export { CboxIdClient as C, type PipeConnectOptions as P, type StoreSecretInput as S, VaultClient as V, type WebhookHeaders as W, type CallbackParams as a, PipeLeaseDeniedError as b, PipeLeaseError as c, PipeNotConnectedError as d, type PipeProvider as e, PipeReauthorizationRequiredError as f, PipeTemporarilyUnavailableError as g, type PipeToken as h, type StoredAuthState as i, type VaultLease as j, type VaultSecretRef as k, type VerifyStandardWebhookOptions as l, type VerifyWebhookOptions as m, verifyWebhook as n, pipeConnectUrl as p, verifyStandardWebhook as v, withConnectReturn as w };
@@ -1,4 +1,5 @@
1
- import { a as CboxIdConfig, A as AuthorizationRequestOptions, b as AuthorizationRequest, C as CboxUser, D as DeviceAuthorization, R as RefreshedTokens, T as TokenTypeHint } from './types-BYZldock.js';
1
+ import { C as CboxIdError } from './errors-D61xljZE.js';
2
+ import { a as CboxIdConfig, A as AuthorizationRequestOptions, b as AuthorizationRequest, C as CboxUser, D as DeviceAuthorization, R as RefreshedTokens, T as TokenTypeHint } from './types-CC1bz68x.js';
2
3
 
3
4
  /** A stored vault secret's metadata (never its plaintext). */
4
5
  interface VaultSecretRef {
@@ -17,6 +18,98 @@ interface VaultLease {
17
18
  secret: string;
18
19
  expiresAt: string;
19
20
  }
21
+ /** A provider a pipe can connect to. */
22
+ type PipeProvider = 'github' | 'google' | 'microsoft' | 'slack' | 'salesforce' | 'hubspot' | 'linear' | 'notion';
23
+ /**
24
+ * A fresh access token for one person's connected account at a provider — what
25
+ * {@link VaultClient.leasePipeToken} returns. Use it, drop it, lease again next time.
26
+ */
27
+ interface PipeToken {
28
+ /** The provider's access token. Send it as a bearer token to the provider's API. */
29
+ accessToken: string;
30
+ tokenType: 'Bearer';
31
+ provider: string;
32
+ userId: string;
33
+ connectionId: string;
34
+ /** What the person consented to. */
35
+ scopes: string[];
36
+ /** When the PROVIDER stops accepting it; null for tokens that do not expire. */
37
+ expiresAt: string | null;
38
+ /** When to drop it and lease again. */
39
+ leaseExpiresAt: string;
40
+ /** What some providers need to be called at all — Salesforce's `instance_url`, Slack's `team.id`. */
41
+ metadata: Record<string, string>;
42
+ }
43
+ /** Where a person connects a provider, and where they come back to afterwards. */
44
+ interface PipeConnectOptions {
45
+ /** Your app's client id — the connect page shows its name and allows its origins. */
46
+ clientId?: string;
47
+ /**
48
+ * Where to land afterwards, with `?provider=…&status=connected|cancelled|failed`. Must be
49
+ * on one of the app's registered redirect origins, or it is ignored.
50
+ */
51
+ returnTo?: string;
52
+ }
53
+ /**
54
+ * Add `client_id` and `return_to` to a connect URL — the one a lease error carries, or
55
+ * one built with {@link pipeConnectUrl}.
56
+ */
57
+ declare function withConnectReturn(connectUrl: string, options?: PipeConnectOptions): string;
58
+ /**
59
+ * The hosted page where the signed-in person connects their account at `provider`:
60
+ * `{issuer}/account/connected-services/{provider}/connect?client_id=…&return_to=…`.
61
+ */
62
+ declare function pipeConnectUrl(issuer: string, provider: PipeProvider | string, options?: PipeConnectOptions): string;
63
+ /**
64
+ * A pipe token lease was refused. Catch the subclasses for the cases you can act on:
65
+ *
66
+ * - {@link PipeNotConnectedError} (404) and {@link PipeReauthorizationRequiredError}
67
+ * (409) — send the person to `connectUrl`.
68
+ * - {@link PipeTemporarilyUnavailableError} (503) — retry after `retryAfter` seconds.
69
+ * - {@link PipeLeaseDeniedError} (403) — a configuration problem: the app is not granted
70
+ * the pipe, it is disabled, or the person is outside the app's organization.
71
+ *
72
+ * Anything else (401, 422, 429) arrives as this base class with `status` and `error`.
73
+ */
74
+ declare class PipeLeaseError extends CboxIdError {
75
+ /** The server's error code, e.g. `not_connected`. */
76
+ readonly error: string | null;
77
+ readonly status: number;
78
+ /** Where to send the person to (re)connect — set on 404 and 409. */
79
+ readonly connectUrl: string | null;
80
+ /** Seconds to wait off `Retry-After`, when the server sent one. */
81
+ readonly retryAfter: number | null;
82
+ constructor(message: string,
83
+ /** The server's error code, e.g. `not_connected`. */
84
+ error: string | null, status: number,
85
+ /** Where to send the person to (re)connect — set on 404 and 409. */
86
+ connectUrl?: string | null,
87
+ /** Seconds to wait off `Retry-After`, when the server sent one. */
88
+ retryAfter?: number | null);
89
+ /** `connectUrl` with your `client_id` and `return_to` on it, or null when there is none. */
90
+ connectUrlWith(options: PipeConnectOptions): string | null;
91
+ }
92
+ /** The person has not connected this provider (404 `not_connected`). Send them to `connectUrl`. */
93
+ declare class PipeNotConnectedError extends PipeLeaseError {
94
+ readonly connectUrl: string;
95
+ }
96
+ /**
97
+ * The provider stopped accepting the connection — revoked, or the refresh token expired
98
+ * (409 `reauthorization_required`). Send the person to `connectUrl` to connect again.
99
+ */
100
+ declare class PipeReauthorizationRequiredError extends PipeLeaseError {
101
+ readonly connectUrl: string;
102
+ }
103
+ /** The provider could not refresh the token just now (503). Retry after `retryAfter`. */
104
+ declare class PipeTemporarilyUnavailableError extends PipeLeaseError {
105
+ }
106
+ /**
107
+ * The lease was denied (403 `lease_denied`): the app is not granted the pipe, the pipe is
108
+ * disabled or missing, the person is not in the app's organization, or `userId` names
109
+ * someone other than the token's person. One answer for every reason, by design.
110
+ */
111
+ declare class PipeLeaseDeniedError extends PipeLeaseError {
112
+ }
20
113
  interface StoreSecretInput {
21
114
  name: string;
22
115
  provider: string;
@@ -54,8 +147,32 @@ declare class VaultClient {
54
147
  * is identified by the token's client; a lease with no live grant is refused.
55
148
  */
56
149
  lease(secretId: string, purpose: string): Promise<VaultLease>;
150
+ /**
151
+ * Lease a fresh access token for a person's connected account at `provider` (Pipes,
152
+ * scope `vault.lease`). The token is refreshed first when it is about to expire, so
153
+ * you never handle a refresh token.
154
+ *
155
+ * With a client-credentials token, name the person in `userId`. With a token issued to
156
+ * your app FOR a person, leave it out — the lease is theirs.
157
+ *
158
+ * ```ts
159
+ * try {
160
+ * const { accessToken } = await vault.leasePipeToken('github', { userId, purpose: 'list-repos' })
161
+ * } catch (e) {
162
+ * if (e instanceof PipeNotConnectedError || e instanceof PipeReauthorizationRequiredError) {
163
+ * return redirect(e.connectUrlWith({ clientId, returnTo }))
164
+ * }
165
+ * throw e
166
+ * }
167
+ * ```
168
+ */
169
+ leasePipeToken(provider: PipeProvider | string, options: {
170
+ purpose: string;
171
+ userId?: string;
172
+ }): Promise<PipeToken>;
57
173
  private json;
58
174
  private request;
175
+ private send;
59
176
  }
60
177
 
61
178
  /**
@@ -259,6 +376,13 @@ declare class CboxIdClient {
259
376
  * registered. `organization` picks which of the person's organizations the keys act in;
260
377
  * omitted, the page uses the one they are in.
261
378
  */
379
+ /**
380
+ * The hosted page where the signed-in person connects their account at `provider`
381
+ * (Pipes) — `/account/connected-services/{provider}/connect`, preselected to this app.
382
+ * They come back to `returnTo` with `?provider=…&status=connected|cancelled|failed`,
383
+ * honoured only on an origin the app registered.
384
+ */
385
+ pipeConnectUrl(provider: PipeProvider | string, returnTo?: string): string;
262
386
  apiKeysUrl(options?: {
263
387
  clientId?: string;
264
388
  returnTo?: string;
@@ -338,4 +462,4 @@ declare class CboxIdClient {
338
462
  private fetchWithTimeout;
339
463
  }
340
464
 
341
- export { CboxIdClient as C, type StoreSecretInput as S, VaultClient as V, type WebhookHeaders as W, type CallbackParams as a, type StoredAuthState as b, type VaultLease as c, type VaultSecretRef as d, type VerifyStandardWebhookOptions as e, type VerifyWebhookOptions as f, verifyWebhook as g, verifyStandardWebhook as v };
465
+ export { CboxIdClient as C, type PipeConnectOptions as P, type StoreSecretInput as S, VaultClient as V, type WebhookHeaders as W, type CallbackParams as a, PipeLeaseDeniedError as b, PipeLeaseError as c, PipeNotConnectedError as d, type PipeProvider as e, PipeReauthorizationRequiredError as f, PipeTemporarilyUnavailableError as g, type PipeToken as h, type StoredAuthState as i, type VaultLease as j, type VaultSecretRef as k, type VerifyStandardWebhookOptions as l, type VerifyWebhookOptions as m, verifyWebhook as n, pipeConnectUrl as p, verifyStandardWebhook as v, withConnectReturn as w };
@@ -0,0 +1,23 @@
1
+ import { O as OrganizationRole } from './types-CC1bz68x.js';
2
+
3
+ interface PermissionDecisionConfig {
4
+ issuer: string;
5
+ clientId: string;
6
+ timeoutMs?: number;
7
+ }
8
+ /** A current server decision; shared membership tiers are not app grants. */
9
+ declare class PermissionDecision {
10
+ readonly subject: string;
11
+ readonly organization: string | null;
12
+ readonly clientId: string;
13
+ readonly organizationRole: OrganizationRole | null;
14
+ readonly organizationActive: boolean;
15
+ readonly permissions: Readonly<Record<string, boolean>>;
16
+ constructor(subject: string, organization: string | null, clientId: string, organizationRole: OrganizationRole | null, organizationActive: boolean, permissions: Readonly<Record<string, boolean>>);
17
+ allows(permission: string): boolean;
18
+ allowed(): boolean;
19
+ }
20
+ /** No positive cache: check each request and again when queued work starts. */
21
+ declare function checkPermissions(config: PermissionDecisionConfig, accessToken: string, subject: string, organization: string | null, permissions: readonly string[]): Promise<PermissionDecision>;
22
+
23
+ export { PermissionDecision as P, type PermissionDecisionConfig as a, checkPermissions as c };
@@ -0,0 +1,23 @@
1
+ import { O as OrganizationRole } from './types-CC1bz68x.cjs';
2
+
3
+ interface PermissionDecisionConfig {
4
+ issuer: string;
5
+ clientId: string;
6
+ timeoutMs?: number;
7
+ }
8
+ /** A current server decision; shared membership tiers are not app grants. */
9
+ declare class PermissionDecision {
10
+ readonly subject: string;
11
+ readonly organization: string | null;
12
+ readonly clientId: string;
13
+ readonly organizationRole: OrganizationRole | null;
14
+ readonly organizationActive: boolean;
15
+ readonly permissions: Readonly<Record<string, boolean>>;
16
+ constructor(subject: string, organization: string | null, clientId: string, organizationRole: OrganizationRole | null, organizationActive: boolean, permissions: Readonly<Record<string, boolean>>);
17
+ allows(permission: string): boolean;
18
+ allowed(): boolean;
19
+ }
20
+ /** No positive cache: check each request and again when queued work starts. */
21
+ declare function checkPermissions(config: PermissionDecisionConfig, accessToken: string, subject: string, organization: string | null, permissions: readonly string[]): Promise<PermissionDecision>;
22
+
23
+ export { PermissionDecision as P, type PermissionDecisionConfig as a, checkPermissions as c };