@opendatalabs/connect-js 1.0.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 +62 -0
- package/dist/chunk-JEDKJQ3M.js +41 -0
- package/dist/chunk-JEDKJQ3M.js.map +1 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +35 -0
- package/dist/react/index.js +36 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/index.d.ts +13 -0
- package/dist/server/index.js +20 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @opendatalabs/connect-js
|
|
2
|
+
|
|
3
|
+
`@opendatalabs/connect-js` is the JavaScript SDK for launching hosted Open Data Labs Connect flows.
|
|
4
|
+
|
|
5
|
+
It is designed around the same trust split used by embedded products like Stripe Connect and Plaid Link:
|
|
6
|
+
|
|
7
|
+
- your server uses a secret Open Data Labs API key
|
|
8
|
+
- your frontend uses a public app ID
|
|
9
|
+
- your backend creates short-lived Connect sessions
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @opendatalabs/connect-js
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## React usage
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { OpenDataLabsProvider } from "@opendatalabs/connect-js/react";
|
|
21
|
+
|
|
22
|
+
<OpenDataLabsProvider
|
|
23
|
+
appId={process.env.NEXT_PUBLIC_ODL_APP_ID}
|
|
24
|
+
createSession={async ({ source, scopes, appId }) => {
|
|
25
|
+
const response = await fetch("/api/connect-session", {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: { "Content-Type": "application/json" },
|
|
28
|
+
body: JSON.stringify({ source, scopes, appId }),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error("Failed to create Connect session");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return response.json();
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<App />
|
|
39
|
+
</OpenDataLabsProvider>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Server usage
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { createConnectSession } from "@opendatalabs/connect-js/server";
|
|
46
|
+
|
|
47
|
+
const session = await createConnectSession(
|
|
48
|
+
"https://api.opendatalabs.com/api/v1",
|
|
49
|
+
process.env.OPENDATALABS_API_KEY!,
|
|
50
|
+
{
|
|
51
|
+
appId: process.env.ODL_APP_ID,
|
|
52
|
+
source: "instagram",
|
|
53
|
+
origin: "https://app.example.com",
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- Keep your API key on the server.
|
|
61
|
+
- Use an app-scoped public `appId` in the browser.
|
|
62
|
+
- Add each embedding domain in the Open Data Labs dashboard before creating sessions for it.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/core/client.ts
|
|
2
|
+
function listenForConnectMessages(connectUrl, events) {
|
|
3
|
+
const expectedOrigin = new URL(connectUrl).origin;
|
|
4
|
+
const handler = (event) => {
|
|
5
|
+
if (event.origin !== expectedOrigin) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const type = event.data?.type;
|
|
9
|
+
if (type === "ready") {
|
|
10
|
+
events.onReady?.();
|
|
11
|
+
} else if (type === "success") {
|
|
12
|
+
events.onSuccess?.({
|
|
13
|
+
connectionId: event.data?.connectionId,
|
|
14
|
+
data: event.data?.data
|
|
15
|
+
});
|
|
16
|
+
} else if (type === "demo-data") {
|
|
17
|
+
events.onSuccess?.({
|
|
18
|
+
connectionId: event.data?.connectionId ?? "",
|
|
19
|
+
data: event.data?.data
|
|
20
|
+
});
|
|
21
|
+
} else if (type === "exit") {
|
|
22
|
+
events.onExit?.();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener("message", handler);
|
|
26
|
+
return () => window.removeEventListener("message", handler);
|
|
27
|
+
}
|
|
28
|
+
function createConnectIframe(session) {
|
|
29
|
+
const iframe = document.createElement("iframe");
|
|
30
|
+
iframe.src = session.connectUrl;
|
|
31
|
+
iframe.style.width = "100%";
|
|
32
|
+
iframe.style.height = "100%";
|
|
33
|
+
iframe.style.border = "0";
|
|
34
|
+
return iframe;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
listenForConnectMessages,
|
|
39
|
+
createConnectIframe
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=chunk-JEDKJQ3M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/client.ts"],"sourcesContent":["import type { ConnectEvents, ConnectSession } from \"./types\";\n\nexport function listenForConnectMessages(\n connectUrl: string,\n events: ConnectEvents\n) {\n const expectedOrigin = new URL(connectUrl).origin;\n\n const handler = (event: MessageEvent) => {\n if (event.origin !== expectedOrigin) {\n return;\n }\n\n const type = event.data?.type;\n if (type === \"ready\") {\n events.onReady?.();\n } else if (type === \"success\") {\n events.onSuccess?.({\n connectionId: event.data?.connectionId,\n data: event.data?.data,\n });\n } else if (type === \"demo-data\") {\n events.onSuccess?.({\n connectionId: event.data?.connectionId ?? \"\",\n data: event.data?.data,\n });\n } else if (type === \"exit\") {\n events.onExit?.();\n }\n };\n\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n}\n\nexport function createConnectIframe(session: ConnectSession) {\n const iframe = document.createElement(\"iframe\");\n iframe.src = session.connectUrl;\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n iframe.style.border = \"0\";\n return iframe;\n}\n"],"mappings":";AAEO,SAAS,yBACd,YACA,QACA;AACA,QAAM,iBAAiB,IAAI,IAAI,UAAU,EAAE;AAE3C,QAAM,UAAU,CAAC,UAAwB;AACvC,QAAI,MAAM,WAAW,gBAAgB;AACnC;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,MAAM;AACzB,QAAI,SAAS,SAAS;AACpB,aAAO,UAAU;AAAA,IACnB,WAAW,SAAS,WAAW;AAC7B,aAAO,YAAY;AAAA,QACjB,cAAc,MAAM,MAAM;AAAA,QAC1B,MAAM,MAAM,MAAM;AAAA,MACpB,CAAC;AAAA,IACH,WAAW,SAAS,aAAa;AAC/B,aAAO,YAAY;AAAA,QACjB,cAAc,MAAM,MAAM,gBAAgB;AAAA,QAC1C,MAAM,MAAM,MAAM;AAAA,MACpB,CAAC;AAAA,IACH,WAAW,SAAS,QAAQ;AAC1B,aAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,iBAAiB,WAAW,OAAO;AAC1C,SAAO,MAAM,OAAO,oBAAoB,WAAW,OAAO;AAC5D;AAEO,SAAS,oBAAoB,SAAyB;AAC3D,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,MAAM,QAAQ;AACrB,SAAO,MAAM,QAAQ;AACrB,SAAO,MAAM,SAAS;AACtB,SAAO,MAAM,SAAS;AACtB,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface CreateSessionOptions {
|
|
2
|
+
source: string;
|
|
3
|
+
scopes?: string[];
|
|
4
|
+
redirectUrl?: string;
|
|
5
|
+
origin?: string;
|
|
6
|
+
appId?: string;
|
|
7
|
+
}
|
|
8
|
+
interface ConnectSession {
|
|
9
|
+
connectionId: string;
|
|
10
|
+
connectToken: string;
|
|
11
|
+
connectUrl: string;
|
|
12
|
+
}
|
|
13
|
+
interface ConnectEvents {
|
|
14
|
+
onReady?: () => void;
|
|
15
|
+
onSuccess?: (payload: {
|
|
16
|
+
connectionId: string;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
}) => void;
|
|
19
|
+
onExit?: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare function listenForConnectMessages(connectUrl: string, events: ConnectEvents): () => void;
|
|
23
|
+
declare function createConnectIframe(session: ConnectSession): HTMLIFrameElement;
|
|
24
|
+
|
|
25
|
+
export { type ConnectEvents, type ConnectSession, type CreateSessionOptions, createConnectIframe, listenForConnectMessages };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ConnectEvents, ConnectSession, CreateSessionOptions, createConnectIframe, listenForConnectMessages } from './core/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface OpenDataLabsConfig {
|
|
5
|
+
appId?: string;
|
|
6
|
+
createSession: (input: {
|
|
7
|
+
source: string;
|
|
8
|
+
scopes?: string[];
|
|
9
|
+
redirectUrl?: string;
|
|
10
|
+
origin?: string;
|
|
11
|
+
appId?: string;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
connectionId: string;
|
|
14
|
+
connectToken: string;
|
|
15
|
+
connectUrl: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
interface OpenDataLabsProviderProps extends OpenDataLabsConfig {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
declare function OpenDataLabsProvider({ children, ...value }: OpenDataLabsProviderProps): react_jsx_runtime.JSX.Element;
|
|
22
|
+
declare function useOpenDataLabs(): OpenDataLabsConfig;
|
|
23
|
+
|
|
24
|
+
declare function useConnect(): (input: {
|
|
25
|
+
source: string;
|
|
26
|
+
scopes?: string[];
|
|
27
|
+
redirectUrl?: string;
|
|
28
|
+
origin?: string;
|
|
29
|
+
}) => Promise<{
|
|
30
|
+
connectionId: string;
|
|
31
|
+
connectToken: string;
|
|
32
|
+
connectUrl: string;
|
|
33
|
+
}>;
|
|
34
|
+
|
|
35
|
+
export { type OpenDataLabsConfig, OpenDataLabsProvider, type OpenDataLabsProviderProps, useConnect, useOpenDataLabs };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/react/provider.tsx
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var ConnectContext = createContext(null);
|
|
5
|
+
function OpenDataLabsProvider({
|
|
6
|
+
children,
|
|
7
|
+
...value
|
|
8
|
+
}) {
|
|
9
|
+
return /* @__PURE__ */ jsx(ConnectContext.Provider, { value, children });
|
|
10
|
+
}
|
|
11
|
+
function useOpenDataLabs() {
|
|
12
|
+
const context = useContext(ConnectContext);
|
|
13
|
+
if (!context) {
|
|
14
|
+
throw new Error("useOpenDataLabs must be used within OpenDataLabsProvider");
|
|
15
|
+
}
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/react/use-connect.ts
|
|
20
|
+
import { useCallback } from "react";
|
|
21
|
+
function useConnect() {
|
|
22
|
+
const { createSession, appId } = useOpenDataLabs();
|
|
23
|
+
return useCallback(
|
|
24
|
+
(input) => createSession({
|
|
25
|
+
...input,
|
|
26
|
+
appId
|
|
27
|
+
}),
|
|
28
|
+
[appId, createSession]
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
OpenDataLabsProvider,
|
|
33
|
+
useConnect,
|
|
34
|
+
useOpenDataLabs
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/provider.tsx","../../src/react/use-connect.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\n\nexport interface OpenDataLabsConfig {\n appId?: string;\n createSession: (input: {\n source: string;\n scopes?: string[];\n redirectUrl?: string;\n origin?: string;\n appId?: string;\n }) => Promise<{\n connectionId: string;\n connectToken: string;\n connectUrl: string;\n }>;\n}\n\nexport interface OpenDataLabsProviderProps extends OpenDataLabsConfig {\n children: ReactNode;\n}\n\nconst ConnectContext = createContext<OpenDataLabsConfig | null>(null);\n\nexport function OpenDataLabsProvider({\n children,\n ...value\n}: OpenDataLabsProviderProps) {\n return <ConnectContext.Provider value={value}>{children}</ConnectContext.Provider>;\n}\n\nexport function useOpenDataLabs() {\n const context = useContext(ConnectContext);\n if (!context) {\n throw new Error(\"useOpenDataLabs must be used within OpenDataLabsProvider\");\n }\n return context;\n}\n","import { useCallback } from \"react\";\nimport { useOpenDataLabs } from \"./provider\";\n\nexport function useConnect() {\n const { createSession, appId } = useOpenDataLabs();\n\n return useCallback(\n (input: {\n source: string;\n scopes?: string[];\n redirectUrl?: string;\n origin?: string;\n }) =>\n createSession({\n ...input,\n appId,\n }),\n [appId, createSession]\n );\n}\n"],"mappings":";AAAA,SAAS,eAAe,kBAAkC;AA2BjD;AANT,IAAM,iBAAiB,cAAyC,IAAI;AAE7D,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA,GAAG;AACL,GAA8B;AAC5B,SAAO,oBAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAC1D;AAEO,SAAS,kBAAkB;AAChC,QAAM,UAAU,WAAW,cAAc;AACzC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AACA,SAAO;AACT;;;ACpCA,SAAS,mBAAmB;AAGrB,SAAS,aAAa;AAC3B,QAAM,EAAE,eAAe,MAAM,IAAI,gBAAgB;AAEjD,SAAO;AAAA,IACL,CAAC,UAMC,cAAc;AAAA,MACZ,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,IACH,CAAC,OAAO,aAAa;AAAA,EACvB;AACF;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare function createConnectSession(apiBaseUrl: string, apiKey: string, body: {
|
|
2
|
+
source: string;
|
|
3
|
+
scopes?: string[];
|
|
4
|
+
redirectUrl?: string;
|
|
5
|
+
origin?: string;
|
|
6
|
+
appId?: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
connectionId: string;
|
|
9
|
+
connectToken: string;
|
|
10
|
+
connectUrl: string;
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
export { createConnectSession };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/server/index.ts
|
|
2
|
+
async function createConnectSession(apiBaseUrl, apiKey, body) {
|
|
3
|
+
const response = await fetch(`${apiBaseUrl}/connect/sessions`, {
|
|
4
|
+
method: "POST",
|
|
5
|
+
headers: {
|
|
6
|
+
Authorization: `Bearer ${apiKey}`,
|
|
7
|
+
"Content-Type": "application/json"
|
|
8
|
+
},
|
|
9
|
+
body: JSON.stringify(body)
|
|
10
|
+
});
|
|
11
|
+
const data = await response.json();
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error(data.message || "Failed to create connect session");
|
|
14
|
+
}
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
createConnectSession
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["export async function createConnectSession(\n apiBaseUrl: string,\n apiKey: string,\n body: {\n source: string;\n scopes?: string[];\n redirectUrl?: string;\n origin?: string;\n appId?: string;\n }\n) {\n const response = await fetch(`${apiBaseUrl}/connect/sessions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n const data = await response.json();\n if (!response.ok) {\n throw new Error(data.message || \"Failed to create connect session\");\n }\n\n return data as {\n connectionId: string;\n connectToken: string;\n connectUrl: string;\n };\n}\n"],"mappings":";AAAA,eAAsB,qBACpB,YACA,QACA,MAOA;AACA,QAAM,WAAW,MAAM,MAAM,GAAG,UAAU,qBAAqB;AAAA,IAC7D,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,MAAM;AAAA,MAC/B,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AAED,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,KAAK,WAAW,kCAAkC;AAAA,EACpE;AAEA,SAAO;AAKT;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opendatalabs/connect-js",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "JavaScript SDK for embedding Open Data Labs Connect flows",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public",
|
|
10
|
+
"tag": "alpha"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./react": {
|
|
25
|
+
"types": "./dist/react/index.d.ts",
|
|
26
|
+
"import": "./dist/react/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./server": {
|
|
29
|
+
"types": "./dist/server/index.d.ts",
|
|
30
|
+
"import": "./dist/server/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./core": {
|
|
33
|
+
"types": "./dist/core/index.d.ts",
|
|
34
|
+
"import": "./dist/core/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"clean": "rm -rf dist",
|
|
40
|
+
"pack:check": "node ../../scripts/assert-connect-package.mjs"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://dev.opendatalabs.com/docs",
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"react": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"react": {
|
|
48
|
+
"optional": true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|