@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 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,9 @@
1
+ import {
2
+ createConnectIframe,
3
+ listenForConnectMessages
4
+ } from "../chunk-JEDKJQ3M.js";
5
+ export {
6
+ createConnectIframe,
7
+ listenForConnectMessages
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1 @@
1
+ export { ConnectEvents, ConnectSession, CreateSessionOptions, createConnectIframe, listenForConnectMessages } from './core/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ createConnectIframe,
3
+ listenForConnectMessages
4
+ } from "./chunk-JEDKJQ3M.js";
5
+ export {
6
+ createConnectIframe,
7
+ listenForConnectMessages
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -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
+ }