@withone/connect 0.15.0 → 0.16.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/README.md +223 -53
- package/dist/flow.d.ts +0 -4
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.esm.js +1 -1
- package/dist/next.cjs.js +10 -0
- package/dist/next.d.ts +10 -1
- package/dist/next.esm.js +10 -0
- package/dist/node.cjs.js +17 -13
- package/dist/node.d.ts +6 -1
- package/dist/node.esm.js +17 -13
- package/dist/server/types.d.ts +1 -1
- package/dist/types.d.ts +3 -3
- package/package.json +1 -1
- package/skills/one-connect/SKILL.md +105 -50
- package/src/flow.ts +0 -6
- package/src/index.ts +1 -6
- package/src/next.ts +17 -1
- package/src/node.ts +23 -15
- package/src/server/types.ts +1 -1
- package/src/types.ts +3 -3
package/src/flow.ts
CHANGED
|
@@ -156,12 +156,6 @@ export function createConnectFlow(
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
/** @deprecated Renamed to `createConnectFlow` (it is not a React hook;
|
|
160
|
-
* React apps can use `useOneConnect` from `@withone/connect/react`).
|
|
161
|
-
* Removed in the next minor. */
|
|
162
|
-
export const useOneConnect = (options: OneConnectFlowOptions): OneConnectFlow =>
|
|
163
|
-
createConnectFlow(options);
|
|
164
|
-
|
|
165
159
|
/** Test seam: forget this page load's outcome. */
|
|
166
160
|
export function resetPageReturnForTests(): void {
|
|
167
161
|
pageReturn = undefined;
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createConnectFlow, readConnectReturn
|
|
1
|
+
export { createConnectFlow, readConnectReturn } from "./flow";
|
|
2
2
|
export {
|
|
3
3
|
mountConnectButton,
|
|
4
4
|
registerConnectButton,
|
|
@@ -22,8 +22,3 @@ export type {
|
|
|
22
22
|
OneConnectTheme,
|
|
23
23
|
} from "./types";
|
|
24
24
|
|
|
25
|
-
import type { OneConnectFlow, OneConnectFlowOptions } from "./types";
|
|
26
|
-
/** @deprecated Renamed to `OneConnectFlowOptions`; removed in the next minor. */
|
|
27
|
-
export type OneConnectOptions = OneConnectFlowOptions;
|
|
28
|
-
/** @deprecated Renamed to `OneConnectFlow`; removed in the next minor. */
|
|
29
|
-
export type OneConnectHandle = OneConnectFlow;
|
package/src/next.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* That serves /api/one/authorize and /api/one/callback. Register
|
|
15
15
|
* `https://yourapp.com/api/one/callback` as the app's redirect URI.
|
|
16
16
|
*/
|
|
17
|
-
import type { OneConnectClient } from "./server";
|
|
17
|
+
import type { CompleteAuthorizationResult, OneConnectClient } from "./server";
|
|
18
18
|
|
|
19
19
|
export interface OneConnectRoutesOptions {
|
|
20
20
|
/** The app's own id for the signed-in user, or null when nobody is
|
|
@@ -25,6 +25,15 @@ export interface OneConnectRoutesOptions {
|
|
|
25
25
|
/** Where to send the browser when nobody is signed in. Answers 401
|
|
26
26
|
* when omitted. */
|
|
27
27
|
signInUrl?: string;
|
|
28
|
+
/** Called after every callback, before the browser is redirected:
|
|
29
|
+
* `result.outcome` is "connected", "declined" or "failed", and
|
|
30
|
+
* `result.message` says why a flow failed. For your logs and metrics;
|
|
31
|
+
* never show the message to the user. An error it throws is ignored,
|
|
32
|
+
* so the user still lands back in the app. */
|
|
33
|
+
onComplete?: (event: {
|
|
34
|
+
userId: string;
|
|
35
|
+
result: CompleteAuthorizationResult;
|
|
36
|
+
}) => void | Promise<void>;
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
export interface OneConnectRoutes {
|
|
@@ -114,6 +123,13 @@ export function createOneConnectRoutes(
|
|
|
114
123
|
url: request.url,
|
|
115
124
|
getCookie: (name) => readCookie(request, name),
|
|
116
125
|
});
|
|
126
|
+
if (options.onComplete) {
|
|
127
|
+
try {
|
|
128
|
+
await options.onComplete({ userId: user, result });
|
|
129
|
+
} catch {
|
|
130
|
+
/* the app's own hook threw; the redirect still happens */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
117
133
|
return redirectWithCookies(
|
|
118
134
|
result.redirectUrl,
|
|
119
135
|
result.clearCookieName
|
package/src/node.ts
CHANGED
|
@@ -29,8 +29,12 @@ export interface OneConnectNodeOptions {
|
|
|
29
29
|
loginHintFor?: (
|
|
30
30
|
request: IncomingMessage,
|
|
31
31
|
) => Promise<string | null> | string | null;
|
|
32
|
-
/** Where to send the browser when nobody is signed in.
|
|
32
|
+
/** Where to send the browser when nobody is signed in. Answers 401
|
|
33
|
+
* when omitted. */
|
|
33
34
|
signInUrl?: string;
|
|
35
|
+
/** Called after every callback with how it ended; see
|
|
36
|
+
* `OneConnectRoutesOptions.onComplete`. */
|
|
37
|
+
onComplete?: OneConnectRoutesOptions["onComplete"];
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export type NodeHandler = (
|
|
@@ -80,27 +84,31 @@ export function createOneConnectHandlers(
|
|
|
80
84
|
options: OneConnectNodeOptions,
|
|
81
85
|
): OneConnectHandlers {
|
|
82
86
|
// The web adapter receives a Request; the Node callbacks want the
|
|
83
|
-
// original IncomingMessage
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
// original IncomingMessage. Each Request maps to its own message, so
|
|
88
|
+
// concurrent requests never read each other's session or login hint.
|
|
89
|
+
const origin = new WeakMap<Request, IncomingMessage>();
|
|
90
|
+
const nodeRequestFor = (request: Request): IncomingMessage => {
|
|
91
|
+
const message = origin.get(request);
|
|
92
|
+
if (!message) throw new Error("@withone/connect/node: unknown request");
|
|
93
|
+
return message;
|
|
94
|
+
};
|
|
95
|
+
const loginHintFor = options.loginHintFor;
|
|
96
|
+
const routes = createOneConnectRoutes(oneConnect, {
|
|
97
|
+
identifyUser: (request) => options.identifyUser(nodeRequestFor(request)),
|
|
98
|
+
loginHintFor: loginHintFor
|
|
99
|
+
? (request) => loginHintFor(nodeRequestFor(request))
|
|
89
100
|
: undefined,
|
|
90
101
|
signInUrl: options.signInUrl,
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
onComplete: options.onComplete,
|
|
103
|
+
} satisfies OneConnectRoutesOptions);
|
|
93
104
|
|
|
94
105
|
const handle = async (
|
|
95
106
|
request: IncomingMessage,
|
|
96
107
|
response: ServerResponse,
|
|
97
108
|
): Promise<void> => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
} finally {
|
|
102
|
-
current = null;
|
|
103
|
-
}
|
|
109
|
+
const web = toWebRequest(request);
|
|
110
|
+
origin.set(web, request);
|
|
111
|
+
await send(response, await routes.GET(web));
|
|
104
112
|
};
|
|
105
113
|
|
|
106
114
|
return { authorize: handle, callback: handle };
|
package/src/server/types.ts
CHANGED
|
@@ -121,7 +121,7 @@ export interface OneConnectBaseConfig {
|
|
|
121
121
|
export interface OneConnectKeyConfig extends OneConnectBaseConfig {
|
|
122
122
|
mode?: "key";
|
|
123
123
|
/** The app's connect key, minted on the app's page in the dashboard.
|
|
124
|
-
* Server only.
|
|
124
|
+
* Server only. Connect keys work in Production. */
|
|
125
125
|
connectKey: string;
|
|
126
126
|
userStore: OneConnectUserStore;
|
|
127
127
|
tokenStore?: never;
|
package/src/types.ts
CHANGED
|
@@ -75,9 +75,9 @@ export interface ConnectButtonLogo {
|
|
|
75
75
|
imageUrl: string;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
/** @deprecated Renamed to `ConnectButtonLogoInput`; removed in
|
|
78
|
+
/** @deprecated Renamed to `ConnectButtonLogoInput`; removed in 0.17.0. */
|
|
79
79
|
export type ConnectButtonPlatformInput = ConnectButtonLogoInput;
|
|
80
|
-
/** @deprecated Renamed to `ConnectButtonLogo`; removed in
|
|
80
|
+
/** @deprecated Renamed to `ConnectButtonLogo`; removed in 0.17.0. */
|
|
81
81
|
export type ConnectButtonPlatform = ConnectButtonLogo;
|
|
82
82
|
|
|
83
83
|
export type ConnectButtonVariant = "default" | "accent" | "block";
|
|
@@ -94,7 +94,7 @@ export interface ConnectButtonProps {
|
|
|
94
94
|
* into a "+N" chip. Decoration only; the permission set decides what
|
|
95
95
|
* One asks for. */
|
|
96
96
|
logos?: ConnectButtonLogoInput[];
|
|
97
|
-
/** @deprecated Renamed to `logos`; removed in
|
|
97
|
+
/** @deprecated Renamed to `logos`; removed in 0.17.0. */
|
|
98
98
|
platforms?: ConnectButtonLogoInput[];
|
|
99
99
|
/** Whether this user has a live grant, from your server. When set, it
|
|
100
100
|
* decides the Connected state. When omitted, the button shows
|