@keboola/api-client-react 56.0.0 → 57.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/AGENTS.md +14 -66
- package/CHANGELOG.md +11 -0
- package/README.md +11 -17
- package/dist/index.cjs +1 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -64
- package/dist/index.d.ts +9 -64
- package/dist/index.js +3 -48
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/AGENTS.md
CHANGED
|
@@ -15,92 +15,42 @@ non-React surfaces. This package is the **only** place that knows about
|
|
|
15
15
|
|
|
16
16
|
```ts
|
|
17
17
|
import {
|
|
18
|
-
LegacyAuthProvider,
|
|
19
18
|
ProjectApiProvider,
|
|
20
19
|
StackApiProvider,
|
|
21
20
|
useActiveStack,
|
|
22
|
-
useLegacyAuth,
|
|
23
21
|
useProjectApi,
|
|
24
22
|
useSessionState,
|
|
25
23
|
useStackApi,
|
|
26
24
|
} from '@keboola/api-client-react';
|
|
27
25
|
```
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- `
|
|
32
|
-
What is there before a project — sign-in, the account, the project list.
|
|
33
|
-
- `ProjectApiProvider` / `useProjectApi()` — a `ProjectApi`: a `StackApi` plus every project
|
|
34
|
-
namespace. It provides its stack too, so `useStackApi()` answers inside a project.
|
|
35
|
-
- The verified token and the default branch are the app's to fetch (`api.storage.tokens.verify()`,
|
|
36
|
-
`api.storage.branches.getDevBranches()`) and derive with `createProject` / `createBranchRefs`.
|
|
37
|
-
- `LegacyAuthProvider` — takes a **legacy** `session` (+ `baseUrl`, `storageToken`, optional
|
|
38
|
-
`managementToken`). On mount it drives the session to ready (`setBaseUrl` →
|
|
39
|
-
`authenticateManagement?` → `authenticateStorageAsync`) and renders `fallback` until
|
|
40
|
-
`session.isStorageReady()`. Exposes the session via `useLegacyAuth()`.
|
|
41
|
-
- `useSessionState(session)` / `useActiveStack(session)` — a bearer session's table, and its active
|
|
27
|
+
- `StackApiProvider` / `useStackApi()` — a `StackApi`, what is there before a project.
|
|
28
|
+
- `ProjectApiProvider` / `useProjectApi()` — one project's `ProjectApi`; it provides its stack too.
|
|
29
|
+
- `useSessionState(session)` / `useActiveStack(session)` — the session's table and its active
|
|
42
30
|
stack, as re-rendering values.
|
|
43
31
|
|
|
44
|
-
Every hook **throws** outside its provider. Providers are pure pass-throughs: no lifecycle, no
|
|
45
|
-
fallback. Mount the stack where the app is signed in and the project where the URL names one:
|
|
46
|
-
|
|
47
32
|
```tsx
|
|
48
|
-
<StackApiProvider api={keboola.
|
|
49
|
-
<ProjectApiProvider api={keboola.
|
|
33
|
+
<StackApiProvider api={keboola.stackApi}>
|
|
34
|
+
<ProjectApiProvider api={keboola.projectApi(projectId)}>{children}</ProjectApiProvider>
|
|
50
35
|
</StackApiProvider>
|
|
51
36
|
```
|
|
52
37
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```tsx
|
|
56
|
-
<LegacyAuthProvider session={session} baseUrl={url} storageToken={token} fallback={<Loading />}>
|
|
57
|
-
<ProjectApiProvider api={api}>{children}</ProjectApiProvider>
|
|
58
|
-
</LegacyAuthProvider>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
For credential verification (dev login, project switching) there is no provider —
|
|
62
|
-
construct the real per-service client with the candidate host + token and call its
|
|
63
|
-
verify: `createStorageClient({ baseUrl, auth: { type: 'sapi-token', token } }).tokens.verify()`, or
|
|
64
|
-
`createManagementClient({ baseUrl, auth: { type: 'management-token', token }, withAuthMiddleware: false }).verifyToken()`
|
|
65
|
-
(the flag skips the session-managing auth middleware so it's a plain validity check).
|
|
38
|
+
What the handles are and how the client behaves:
|
|
39
|
+
[`@keboola/api-client` → Getting a client](../api-client/AGENTS.md#getting-a-client).
|
|
66
40
|
|
|
67
41
|
## Conventions
|
|
68
42
|
|
|
69
|
-
-
|
|
70
|
-
null —
|
|
71
|
-
soften this to optional types or `??` fallbacks; a missing provider is a programming error.
|
|
43
|
+
- Every hook **throws** outside its provider; providers are pure pass-throughs. Don't soften the
|
|
44
|
+
`null` contexts to optional types or `??` fallbacks — a missing provider is a programming error.
|
|
72
45
|
- Reach for `useStackApi()` when the code only needs the stack: it then works before a project too.
|
|
73
|
-
- React
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
mount is a no-op by design — if you need a new auth context, mount a fresh provider.
|
|
77
|
-
|
|
78
|
-
## Non-component access (loaders, services, module scope)
|
|
79
|
-
|
|
80
|
-
`useStackApi()` and `useProjectApi()` are for React components only. A TanStack Router loader, a
|
|
81
|
-
module instantiated at import time, or any code running outside the React tree
|
|
82
|
-
can't call the hook. Don't reach for the context there — construct a client
|
|
83
|
-
directly:
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
// Single service — the common case
|
|
87
|
-
import { createStorageClient } from '@keboola/api-client/storage';
|
|
88
|
-
|
|
89
|
-
const storage = createStorageClient({ baseUrl, auth: { type: 'sapi-token', token } });
|
|
90
|
-
const tables = await storage.tables.getTables();
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
If you need several services from non-component code, create one client at app
|
|
94
|
-
bootstrap (`createLegacyKeboola(...)` / `createKeboola(...)`, drive its session to
|
|
95
|
-
ready, and export the `api`) and import that instance where needed — rather than
|
|
96
|
-
re-creating clients per call. See
|
|
97
|
-
[`@keboola/api-client` → Getting a client](../api-client/AGENTS.md#getting-a-client).
|
|
46
|
+
- Outside React (loaders, module scope), import the app's one client instead of a hook — never build
|
|
47
|
+
a second one.
|
|
48
|
+
- React is a **peerDependency** (^19.0.0).
|
|
98
49
|
|
|
99
50
|
## Canonical consumers
|
|
100
51
|
|
|
101
|
-
- `apps/kbc-ui/src/scripts/
|
|
102
|
-
|
|
103
|
-
from the URL's project
|
|
52
|
+
- `apps/kbc-ui/src/scripts/app.tsx` — the production `StackApiProvider` mount, around the whole
|
|
53
|
+
app; `login/pages/ProjectPage.tsx` mounts `ProjectApiProvider` from the URL's project
|
|
104
54
|
- `apps/kbc-ui/src/scripts/modules/sandboxes/queries.ts` — `useProjectApi`
|
|
105
55
|
inside a TanStack Query hook (the dominant pattern)
|
|
106
56
|
|
|
@@ -108,7 +58,5 @@ re-creating clients per call. See
|
|
|
108
58
|
|
|
109
59
|
- **Never** create a parallel React context that wraps another client
|
|
110
60
|
instance. One client per app, mounted once at the top.
|
|
111
|
-
- **Never** drive a legacy `session` manually in a consumer — `LegacyAuthProvider` owns the
|
|
112
|
-
drive-to-ready lifecycle.
|
|
113
61
|
- **Never** import from a deep path (`@keboola/api-client-react/src/...`).
|
|
114
62
|
The package only exports `src/index.ts`.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @keboola/api-client-react
|
|
2
2
|
|
|
3
|
+
## 57.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- **Breaking:** `createLegacyKeboola` and its session are gone, with no replacement factory. `LegacySession`, `LegacyKeboolaOptions`, `LegacyAuthProvider` and `useLegacyAuth` go with it, as do the `NoManagementToken`, `NoStorageToken`, `MissingProject`, `NotBearer` and `InvalidBuildTransition` error types and the `all` key of `middlewares` — list a middleware under each client it belongs to. `createKeboola` returns `stackApi` in place of `getStackApi()` — the same object, whose reads follow the active stack — and `projectApi(projectId)` in place of `getProjectApi(projectId)`. The `BearerSession` type is `Session`. `createStorageClient` drops its `onRefreshToken` option, and `createDerivedStore`, `createDerivedAsyncStore`, `shallowEqual` and `AsyncState` go: the legacy client was their only user. `Store.dispose`, `Emitter.clear` and the `ReadableStore` type go with them. `ProjectApi.serviceMeta` goes: every entry was available, and a call to a missing service rejects instead. `ProjectFeature.FrontendLogin` goes: nothing reads it. A call to a service the stack does not run rejects with `ServiceUnavailableError` again, not `NotReady`; its `path` and `clientName` are optional. A Storage API token builds the per-service clients it calls (`createStorageClient`, `createOauthClient`, …), each service's URL from `storage.getStackInfo()`; a full `ProjectApi` comes from a `createKeboola` sign-in (UT-5193)
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @keboola/api-client@57.0.0
|
|
13
|
+
|
|
3
14
|
## 56.0.0
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -14,25 +14,18 @@ Peer dependencies: `react ^19.0.0`, `@keboola/api-client`.
|
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
17
|
-
Two handles: a `StackApi` (what is there before a project) and a `ProjectApi` (a stack plus every project namespace). Legacy (SAPI) shown here — its `api` is one project, mounted inside `LegacyAuthProvider`, which drives the `session` to ready and renders `fallback` until then. Bearer mounts `StackApiProvider` with `createKeboola(...).getStackApi()` and `ProjectApiProvider` with `getProjectApi(projectId)`.
|
|
18
|
-
|
|
19
17
|
```tsx
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
const {
|
|
24
|
-
|
|
25
|
-
export const App = () => (
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
baseUrl="https://connection.keboola.com"
|
|
29
|
-
storageToken="your-storage-token"
|
|
30
|
-
fallback={<div>Loading…</div>}
|
|
31
|
-
>
|
|
32
|
-
<ProjectApiProvider api={api}>
|
|
18
|
+
import { createKeboola } from '@keboola/api-client';
|
|
19
|
+
import { ProjectApiProvider, StackApiProvider, useProjectApi } from '@keboola/api-client-react';
|
|
20
|
+
|
|
21
|
+
const keboola = createKeboola({ defaultBaseUrl: 'https://connection.keboola.com' });
|
|
22
|
+
|
|
23
|
+
export const App = ({ projectId }: { projectId: number }) => (
|
|
24
|
+
<StackApiProvider api={keboola.stackApi}>
|
|
25
|
+
<ProjectApiProvider api={keboola.projectApi(projectId)}>
|
|
33
26
|
<Tables />
|
|
34
27
|
</ProjectApiProvider>
|
|
35
|
-
</
|
|
28
|
+
</StackApiProvider>
|
|
36
29
|
);
|
|
37
30
|
|
|
38
31
|
const Tables = () => {
|
|
@@ -46,7 +39,8 @@ const Tables = () => {
|
|
|
46
39
|
|
|
47
40
|
- `useProjectApi()` — the provided `ProjectApi` (`auth` + `management` + every project namespace).
|
|
48
41
|
- `useStackApi()` — the provided `StackApi` (`auth`, `management`, `baseUrl`, `stack`); a `ProjectApiProvider` provides its stack too.
|
|
49
|
-
- `
|
|
42
|
+
- `useSessionState(session)` / `useActiveStack(session)` — a bearer `session`'s table and its
|
|
43
|
+
active stack, as re-rendering values.
|
|
50
44
|
|
|
51
45
|
## Ownership
|
|
52
46
|
|
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,6 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
4
4
|
// src/context.ts
|
|
5
5
|
const MISSING_STACK_API_ERROR = "useStackApi must be used within <StackApiProvider />";
|
|
6
6
|
const MISSING_PROJECT_API_ERROR = "useProjectApi must be used within <ProjectApiProvider />";
|
|
7
|
-
const MISSING_LEGACY_AUTH_ERROR = "useLegacyAuth must be used within <LegacyAuthProvider />";
|
|
8
7
|
/**
|
|
9
8
|
* One stack: what is there before a project — signing in, the account, the project list.
|
|
10
9
|
*
|
|
@@ -14,8 +13,6 @@ const StackApiContext = (0, react.createContext)(null);
|
|
|
14
13
|
const StackApiContextProvider = StackApiContext;
|
|
15
14
|
const ProjectApiContext = (0, react.createContext)(null);
|
|
16
15
|
const ProjectApiContextProvider = ProjectApiContext;
|
|
17
|
-
const LegacyAuthContext = (0, react.createContext)(null);
|
|
18
|
-
const LegacyAuthContextProvider = LegacyAuthContext;
|
|
19
16
|
const useStackApi = () => {
|
|
20
17
|
const api = (0, react.use)(StackApiContext);
|
|
21
18
|
if (api === null) throw new Error(MISSING_STACK_API_ERROR);
|
|
@@ -26,18 +23,8 @@ const useProjectApi = () => {
|
|
|
26
23
|
if (api === null) throw new Error(MISSING_PROJECT_API_ERROR);
|
|
27
24
|
return api;
|
|
28
25
|
};
|
|
29
|
-
/** The legacy (SAPI) lifecycle session. Throws outside `<LegacyAuthProvider />`. */
|
|
30
|
-
const useLegacyAuth = () => {
|
|
31
|
-
const session = (0, react.use)(LegacyAuthContext);
|
|
32
|
-
if (session === null) throw new Error(MISSING_LEGACY_AUTH_ERROR);
|
|
33
|
-
return session;
|
|
34
|
-
};
|
|
35
26
|
// src/ProjectApiProvider.tsx
|
|
36
|
-
/**
|
|
37
|
-
* Provides one project to `useProjectApi()`, and its stack to `useStackApi()`.
|
|
38
|
-
*
|
|
39
|
-
* - A pure pass-through: the auth lifecycle belongs to the session, or to `LegacyAuthProvider`.
|
|
40
|
-
*/
|
|
27
|
+
/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */
|
|
41
28
|
const ProjectApiProvider = ({ api, children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StackApiContextProvider, {
|
|
42
29
|
value: api,
|
|
43
30
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProjectApiContextProvider, {
|
|
@@ -57,43 +44,9 @@ const useActiveStack = (session) => (0, react.useSyncExternalStore)(session.subs
|
|
|
57
44
|
// src/useSessionState.ts
|
|
58
45
|
/** The session table as a re-rendering value — the binding every gate and panel reads it through. */
|
|
59
46
|
const useSessionState = (session) => (0, react.useSyncExternalStore)(session.subscribe, session.getState);
|
|
60
|
-
// src/LegacyAuthProvider.tsx
|
|
61
|
-
/**
|
|
62
|
-
* Owns the legacy (SAPI) lifecycle: on mount it configures the stack and drives the session to
|
|
63
|
-
* ready, rendering `fallback` until the storage build resolves. The backend-injected SAPI token is
|
|
64
|
-
* known up front, so this drives itself (unlike the interactive bearer `AuthProvider`). Exposes the
|
|
65
|
-
* session via `useLegacyAuth()` and gates `children` behind readiness.
|
|
66
|
-
*/
|
|
67
|
-
const LegacyAuthProvider = ({ session, baseUrl, storageToken, managementToken, fallback = null, errorFallback = fallback, children }) => {
|
|
68
|
-
const [storageState, setStorageState] = (0, react.useState)(() => session.debug().storage);
|
|
69
|
-
const startedRef = (0, react.useRef)(false);
|
|
70
|
-
(0, react.useEffect)(() => {
|
|
71
|
-
const unsubscribe = session.subscribe((snapshot) => setStorageState(snapshot.storage));
|
|
72
|
-
if (!startedRef.current) {
|
|
73
|
-
startedRef.current = true;
|
|
74
|
-
session.setBaseUrl(baseUrl);
|
|
75
|
-
if (managementToken) session.authenticateManagement(managementToken);
|
|
76
|
-
session.authenticateStorageAsync(storageToken).catch((error) => console.error("Keboola session bootstrap failed", error));
|
|
77
|
-
}
|
|
78
|
-
return unsubscribe;
|
|
79
|
-
}, []);
|
|
80
|
-
(0, react.useEffect)(() => {
|
|
81
|
-
if (storageState === "errored") console.error("Keboola session bootstrap failed: the storage build errored.");
|
|
82
|
-
}, [storageState]);
|
|
83
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LegacyAuthContextProvider, {
|
|
84
|
-
value: session,
|
|
85
|
-
children: (() => {
|
|
86
|
-
if (storageState === "ready") return children;
|
|
87
|
-
if (storageState === "errored") return errorFallback;
|
|
88
|
-
return fallback;
|
|
89
|
-
})()
|
|
90
|
-
});
|
|
91
|
-
};
|
|
92
|
-
exports.LegacyAuthProvider = LegacyAuthProvider;
|
|
93
47
|
exports.ProjectApiProvider = ProjectApiProvider;
|
|
94
48
|
exports.StackApiProvider = StackApiProvider;
|
|
95
49
|
exports.useActiveStack = useActiveStack;
|
|
96
|
-
exports.useLegacyAuth = useLegacyAuth;
|
|
97
50
|
exports.useProjectApi = useProjectApi;
|
|
98
51
|
exports.useSessionState = useSessionState;
|
|
99
52
|
exports.useStackApi = useStackApi;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["createContext","use","useSyncExternalStore","useSyncExternalStore"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["createContext","use","useSyncExternalStore","useSyncExternalStore"],"sources":["../src/context.ts","../src/ProjectApiProvider.tsx","../src/StackApiProvider.tsx","../src/useActiveStack.ts","../src/useSessionState.ts"],"sourcesContent":["import { createContext, use } from 'react';\n\nimport type { ProjectApi, StackApi } from '@keboola/api-client';\n\nconst MISSING_STACK_API_ERROR = 'useStackApi must be used within <StackApiProvider />';\nconst MISSING_PROJECT_API_ERROR = 'useProjectApi must be used within <ProjectApiProvider />';\n\n/**\n * One stack: what is there before a project — signing in, the account, the project list.\n *\n * - A `ProjectApiProvider` provides its project's stack here too.\n */\nconst StackApiContext = createContext<StackApi | null>(null);\nexport const StackApiContextProvider = StackApiContext;\n\n// One project, on its stack.\nconst ProjectApiContext = createContext<ProjectApi | null>(null);\nexport const ProjectApiContextProvider = ProjectApiContext;\n\nexport const useStackApi = () => {\n const api = use(StackApiContext);\n if (api === null) throw new Error(MISSING_STACK_API_ERROR);\n return api;\n};\n\nexport const useProjectApi = () => {\n const api = use(ProjectApiContext);\n if (api === null) throw new Error(MISSING_PROJECT_API_ERROR);\n return api;\n};\n","import type { ReactNode } from 'react';\n\nimport type { ProjectApi } from '@keboola/api-client';\n\nimport { ProjectApiContextProvider, StackApiContextProvider } from './context';\n\ntype Props = {\n api: ProjectApi;\n children: ReactNode;\n};\n\n/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */\nexport const ProjectApiProvider = ({ api, children }: Props) => (\n <StackApiContextProvider value={api}>\n <ProjectApiContextProvider value={api}>{children}</ProjectApiContextProvider>\n </StackApiContextProvider>\n);\n","import type { ReactNode } from 'react';\n\nimport type { StackApi } from '@keboola/api-client';\n\nimport { StackApiContextProvider } from './context';\n\ntype Props = {\n api: StackApi;\n children: ReactNode;\n};\n\n/** Provides one stack to `useStackApi()`. */\nexport const StackApiProvider = ({ api, children }: Props) => (\n <StackApiContextProvider value={api}>{children}</StackApiContextProvider>\n);\n","import { useSyncExternalStore } from 'react';\n\nimport type { Session } from '@keboola/api-client';\n\n/** The active stack's row as a re-rendering value; the default stack until something selects another. */\nexport const useActiveStack = (session: Session) =>\n useSyncExternalStore(session.subscribe, session.stack.getActive);\n","import { useSyncExternalStore } from 'react';\n\nimport type { Session } from '@keboola/api-client';\n\n/** The session table as a re-rendering value — the binding every gate and panel reads it through. */\nexport const useSessionState = (session: Session) =>\n useSyncExternalStore(session.subscribe, session.getState);\n"],"mappings":";;;;AAIA,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;;;;;;AAOlC,MAAM,mBAAA,GAAkBA,MAAAA,cAAAA,CAA+B,IAAI;AAC3D,MAAa,0BAA0B;AAGvC,MAAM,qBAAA,GAAoBA,MAAAA,cAAAA,CAAiC,IAAI;AAC/D,MAAa,4BAA4B;AAEzC,MAAa,oBAAoB;CAC/B,MAAM,OAAA,GAAMC,MAAAA,IAAAA,CAAI,eAAe;CAC/B,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,uBAAuB;CACzD,OAAO;AACT;AAEA,MAAa,sBAAsB;CACjC,MAAM,OAAA,GAAMA,MAAAA,IAAAA,CAAI,iBAAiB;CACjC,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,yBAAyB;CAC3D,OAAO;AACT;;;ACjBA,MAAa,sBAAsB,EAAE,KAAK,eACxC,iBAAA,GAAA,kBAAA,IAAA,CAAC,yBAAD;CAAyB,OAAO;CAC9B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,2BAAD;EAA2B,OAAO;EAAM;CAAoC,CAAA;AACrD,CAAA;;;ACH3B,MAAa,oBAAoB,EAAE,KAAK,eACtC,iBAAA,GAAA,kBAAA,IAAA,CAAC,yBAAD;CAAyB,OAAO;CAAM;AAAkC,CAAA;;;ACR1E,MAAa,kBAAkB,aAAA,GAC7BC,MAAAA,qBAAAA,CAAqB,QAAQ,WAAW,QAAQ,MAAM,SAAS;;;ACDjE,MAAa,mBAAmB,aAAA,GAC9BC,MAAAA,qBAAAA,CAAqB,QAAQ,WAAW,QAAQ,QAAQ"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,77 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProjectApi, Session, StackApi } from "@keboola/api-client";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
declare const useStackApi: () => StackApi;
|
|
4
4
|
declare const useProjectApi: () => ProjectApi;
|
|
5
|
-
|
|
6
|
-
declare const useLegacyAuth: () => {
|
|
7
|
-
setBaseUrl: (baseUrl: string) => void;
|
|
8
|
-
isStorageReady: () => boolean;
|
|
9
|
-
authenticateStorage: (sapiToken: string) => void;
|
|
10
|
-
authenticateStorageAsync: (sapiToken: string) => Promise<void>;
|
|
11
|
-
authenticateManagement: (managementToken: string) => void;
|
|
12
|
-
subscribe: (listener: (snapshot: {
|
|
13
|
-
type: 'Sapi';
|
|
14
|
-
config: {
|
|
15
|
-
baseUrl: string | null;
|
|
16
|
-
sapiToken: string | null;
|
|
17
|
-
managementToken: string | null;
|
|
18
|
-
};
|
|
19
|
-
authReady: boolean;
|
|
20
|
-
managementReady: boolean;
|
|
21
|
-
storage: import("@keboola/api-client").AsyncState<unknown>['state'];
|
|
22
|
-
}) => void) => () => void;
|
|
23
|
-
debug: () => {
|
|
24
|
-
type: 'Sapi';
|
|
25
|
-
config: {
|
|
26
|
-
baseUrl: string | null;
|
|
27
|
-
sapiToken: string | null;
|
|
28
|
-
managementToken: string | null;
|
|
29
|
-
};
|
|
30
|
-
authReady: boolean;
|
|
31
|
-
managementReady: boolean;
|
|
32
|
-
storage: import("@keboola/api-client").AsyncState<unknown>['state'];
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
type Props$2 = {
|
|
5
|
+
type Props$1 = {
|
|
36
6
|
api: ProjectApi;
|
|
37
7
|
children: ReactNode;
|
|
38
8
|
};
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* - A pure pass-through: the auth lifecycle belongs to the session, or to `LegacyAuthProvider`.
|
|
43
|
-
*/
|
|
44
|
-
declare const ProjectApiProvider: ({ api, children }: Props$2) => import("react").JSX.Element;
|
|
45
|
-
type Props$1 = {
|
|
9
|
+
/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */
|
|
10
|
+
declare const ProjectApiProvider: ({ api, children }: Props$1) => import("react").JSX.Element;
|
|
11
|
+
type Props = {
|
|
46
12
|
api: StackApi;
|
|
47
13
|
children: ReactNode;
|
|
48
14
|
};
|
|
49
15
|
/** Provides one stack to `useStackApi()`. */
|
|
50
|
-
declare const StackApiProvider: ({ api, children }: Props
|
|
16
|
+
declare const StackApiProvider: ({ api, children }: Props) => import("react").JSX.Element;
|
|
51
17
|
/** The active stack's row as a re-rendering value; the default stack until something selects another. */
|
|
52
|
-
declare const useActiveStack: (session:
|
|
18
|
+
declare const useActiveStack: (session: Session) => import("@keboola/api-client").StackEntry;
|
|
53
19
|
/** The session table as a re-rendering value — the binding every gate and panel reads it through. */
|
|
54
|
-
declare const useSessionState: (session:
|
|
55
|
-
|
|
56
|
-
session: LegacySession;
|
|
57
|
-
/** Stack base URL. */
|
|
58
|
-
baseUrl: string;
|
|
59
|
-
/** SAPI token — drives the storage build to ready. */
|
|
60
|
-
storageToken: string;
|
|
61
|
-
/** Optional manage-api token — unlocks `api.management`. */
|
|
62
|
-
managementToken?: string;
|
|
63
|
-
/** Rendered until the storage build reaches ready. */
|
|
64
|
-
fallback?: ReactNode;
|
|
65
|
-
/** Rendered when the storage build fails — the stack index could not be read. */
|
|
66
|
-
errorFallback?: ReactNode;
|
|
67
|
-
children: ReactNode;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Owns the legacy (SAPI) lifecycle: on mount it configures the stack and drives the session to
|
|
71
|
-
* ready, rendering `fallback` until the storage build resolves. The backend-injected SAPI token is
|
|
72
|
-
* known up front, so this drives itself (unlike the interactive bearer `AuthProvider`). Exposes the
|
|
73
|
-
* session via `useLegacyAuth()` and gates `children` behind readiness.
|
|
74
|
-
*/
|
|
75
|
-
declare const LegacyAuthProvider: ({ session, baseUrl, storageToken, managementToken, fallback, errorFallback, children }: Props) => import("react").JSX.Element;
|
|
76
|
-
export { LegacyAuthProvider, ProjectApiProvider, StackApiProvider, useActiveStack, useLegacyAuth, useProjectApi, useSessionState, useStackApi };
|
|
20
|
+
declare const useSessionState: (session: Session) => import("@keboola/api-client").SessionState;
|
|
21
|
+
export { ProjectApiProvider, StackApiProvider, useActiveStack, useProjectApi, useSessionState, useStackApi };
|
|
77
22
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,77 +1,22 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ProjectApi, Session, StackApi } from "@keboola/api-client";
|
|
3
3
|
declare const useStackApi: () => StackApi;
|
|
4
4
|
declare const useProjectApi: () => ProjectApi;
|
|
5
|
-
|
|
6
|
-
declare const useLegacyAuth: () => {
|
|
7
|
-
setBaseUrl: (baseUrl: string) => void;
|
|
8
|
-
isStorageReady: () => boolean;
|
|
9
|
-
authenticateStorage: (sapiToken: string) => void;
|
|
10
|
-
authenticateStorageAsync: (sapiToken: string) => Promise<void>;
|
|
11
|
-
authenticateManagement: (managementToken: string) => void;
|
|
12
|
-
subscribe: (listener: (snapshot: {
|
|
13
|
-
type: 'Sapi';
|
|
14
|
-
config: {
|
|
15
|
-
baseUrl: string | null;
|
|
16
|
-
sapiToken: string | null;
|
|
17
|
-
managementToken: string | null;
|
|
18
|
-
};
|
|
19
|
-
authReady: boolean;
|
|
20
|
-
managementReady: boolean;
|
|
21
|
-
storage: import("@keboola/api-client").AsyncState<unknown>['state'];
|
|
22
|
-
}) => void) => () => void;
|
|
23
|
-
debug: () => {
|
|
24
|
-
type: 'Sapi';
|
|
25
|
-
config: {
|
|
26
|
-
baseUrl: string | null;
|
|
27
|
-
sapiToken: string | null;
|
|
28
|
-
managementToken: string | null;
|
|
29
|
-
};
|
|
30
|
-
authReady: boolean;
|
|
31
|
-
managementReady: boolean;
|
|
32
|
-
storage: import("@keboola/api-client").AsyncState<unknown>['state'];
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
type Props$2 = {
|
|
5
|
+
type Props$1 = {
|
|
36
6
|
api: ProjectApi;
|
|
37
7
|
children: ReactNode;
|
|
38
8
|
};
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* - A pure pass-through: the auth lifecycle belongs to the session, or to `LegacyAuthProvider`.
|
|
43
|
-
*/
|
|
44
|
-
declare const ProjectApiProvider: ({ api, children }: Props$2) => import("react").JSX.Element;
|
|
45
|
-
type Props$1 = {
|
|
9
|
+
/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */
|
|
10
|
+
declare const ProjectApiProvider: ({ api, children }: Props$1) => import("react").JSX.Element;
|
|
11
|
+
type Props = {
|
|
46
12
|
api: StackApi;
|
|
47
13
|
children: ReactNode;
|
|
48
14
|
};
|
|
49
15
|
/** Provides one stack to `useStackApi()`. */
|
|
50
|
-
declare const StackApiProvider: ({ api, children }: Props
|
|
16
|
+
declare const StackApiProvider: ({ api, children }: Props) => import("react").JSX.Element;
|
|
51
17
|
/** The active stack's row as a re-rendering value; the default stack until something selects another. */
|
|
52
|
-
declare const useActiveStack: (session:
|
|
18
|
+
declare const useActiveStack: (session: Session) => import("@keboola/api-client").StackEntry;
|
|
53
19
|
/** The session table as a re-rendering value — the binding every gate and panel reads it through. */
|
|
54
|
-
declare const useSessionState: (session:
|
|
55
|
-
|
|
56
|
-
session: LegacySession;
|
|
57
|
-
/** Stack base URL. */
|
|
58
|
-
baseUrl: string;
|
|
59
|
-
/** SAPI token — drives the storage build to ready. */
|
|
60
|
-
storageToken: string;
|
|
61
|
-
/** Optional manage-api token — unlocks `api.management`. */
|
|
62
|
-
managementToken?: string;
|
|
63
|
-
/** Rendered until the storage build reaches ready. */
|
|
64
|
-
fallback?: ReactNode;
|
|
65
|
-
/** Rendered when the storage build fails — the stack index could not be read. */
|
|
66
|
-
errorFallback?: ReactNode;
|
|
67
|
-
children: ReactNode;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Owns the legacy (SAPI) lifecycle: on mount it configures the stack and drives the session to
|
|
71
|
-
* ready, rendering `fallback` until the storage build resolves. The backend-injected SAPI token is
|
|
72
|
-
* known up front, so this drives itself (unlike the interactive bearer `AuthProvider`). Exposes the
|
|
73
|
-
* session via `useLegacyAuth()` and gates `children` behind readiness.
|
|
74
|
-
*/
|
|
75
|
-
declare const LegacyAuthProvider: ({ session, baseUrl, storageToken, managementToken, fallback, errorFallback, children }: Props) => import("react").JSX.Element;
|
|
76
|
-
export { LegacyAuthProvider, ProjectApiProvider, StackApiProvider, useActiveStack, useLegacyAuth, useProjectApi, useSessionState, useStackApi };
|
|
20
|
+
declare const useSessionState: (session: Session) => import("@keboola/api-client").SessionState;
|
|
21
|
+
export { ProjectApiProvider, StackApiProvider, useActiveStack, useProjectApi, useSessionState, useStackApi };
|
|
77
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { createContext, use,
|
|
1
|
+
import { createContext, use, useSyncExternalStore } from "react";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
// src/context.ts
|
|
4
4
|
const MISSING_STACK_API_ERROR = "useStackApi must be used within <StackApiProvider />";
|
|
5
5
|
const MISSING_PROJECT_API_ERROR = "useProjectApi must be used within <ProjectApiProvider />";
|
|
6
|
-
const MISSING_LEGACY_AUTH_ERROR = "useLegacyAuth must be used within <LegacyAuthProvider />";
|
|
7
6
|
/**
|
|
8
7
|
* One stack: what is there before a project — signing in, the account, the project list.
|
|
9
8
|
*
|
|
@@ -13,8 +12,6 @@ const StackApiContext = createContext(null);
|
|
|
13
12
|
const StackApiContextProvider = StackApiContext;
|
|
14
13
|
const ProjectApiContext = createContext(null);
|
|
15
14
|
const ProjectApiContextProvider = ProjectApiContext;
|
|
16
|
-
const LegacyAuthContext = createContext(null);
|
|
17
|
-
const LegacyAuthContextProvider = LegacyAuthContext;
|
|
18
15
|
const useStackApi = () => {
|
|
19
16
|
const api = use(StackApiContext);
|
|
20
17
|
if (api === null) throw new Error(MISSING_STACK_API_ERROR);
|
|
@@ -25,18 +22,8 @@ const useProjectApi = () => {
|
|
|
25
22
|
if (api === null) throw new Error(MISSING_PROJECT_API_ERROR);
|
|
26
23
|
return api;
|
|
27
24
|
};
|
|
28
|
-
/** The legacy (SAPI) lifecycle session. Throws outside `<LegacyAuthProvider />`. */
|
|
29
|
-
const useLegacyAuth = () => {
|
|
30
|
-
const session = use(LegacyAuthContext);
|
|
31
|
-
if (session === null) throw new Error(MISSING_LEGACY_AUTH_ERROR);
|
|
32
|
-
return session;
|
|
33
|
-
};
|
|
34
25
|
// src/ProjectApiProvider.tsx
|
|
35
|
-
/**
|
|
36
|
-
* Provides one project to `useProjectApi()`, and its stack to `useStackApi()`.
|
|
37
|
-
*
|
|
38
|
-
* - A pure pass-through: the auth lifecycle belongs to the session, or to `LegacyAuthProvider`.
|
|
39
|
-
*/
|
|
26
|
+
/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */
|
|
40
27
|
const ProjectApiProvider = ({ api, children }) => /* @__PURE__ */ jsx(StackApiContextProvider, {
|
|
41
28
|
value: api,
|
|
42
29
|
children: /* @__PURE__ */ jsx(ProjectApiContextProvider, {
|
|
@@ -56,38 +43,6 @@ const useActiveStack = (session) => useSyncExternalStore(session.subscribe, sess
|
|
|
56
43
|
// src/useSessionState.ts
|
|
57
44
|
/** The session table as a re-rendering value — the binding every gate and panel reads it through. */
|
|
58
45
|
const useSessionState = (session) => useSyncExternalStore(session.subscribe, session.getState);
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Owns the legacy (SAPI) lifecycle: on mount it configures the stack and drives the session to
|
|
62
|
-
* ready, rendering `fallback` until the storage build resolves. The backend-injected SAPI token is
|
|
63
|
-
* known up front, so this drives itself (unlike the interactive bearer `AuthProvider`). Exposes the
|
|
64
|
-
* session via `useLegacyAuth()` and gates `children` behind readiness.
|
|
65
|
-
*/
|
|
66
|
-
const LegacyAuthProvider = ({ session, baseUrl, storageToken, managementToken, fallback = null, errorFallback = fallback, children }) => {
|
|
67
|
-
const [storageState, setStorageState] = useState(() => session.debug().storage);
|
|
68
|
-
const startedRef = useRef(false);
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
const unsubscribe = session.subscribe((snapshot) => setStorageState(snapshot.storage));
|
|
71
|
-
if (!startedRef.current) {
|
|
72
|
-
startedRef.current = true;
|
|
73
|
-
session.setBaseUrl(baseUrl);
|
|
74
|
-
if (managementToken) session.authenticateManagement(managementToken);
|
|
75
|
-
session.authenticateStorageAsync(storageToken).catch((error) => console.error("Keboola session bootstrap failed", error));
|
|
76
|
-
}
|
|
77
|
-
return unsubscribe;
|
|
78
|
-
}, []);
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (storageState === "errored") console.error("Keboola session bootstrap failed: the storage build errored.");
|
|
81
|
-
}, [storageState]);
|
|
82
|
-
return /* @__PURE__ */ jsx(LegacyAuthContextProvider, {
|
|
83
|
-
value: session,
|
|
84
|
-
children: (() => {
|
|
85
|
-
if (storageState === "ready") return children;
|
|
86
|
-
if (storageState === "errored") return errorFallback;
|
|
87
|
-
return fallback;
|
|
88
|
-
})()
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
export { LegacyAuthProvider, ProjectApiProvider, StackApiProvider, useActiveStack, useLegacyAuth, useProjectApi, useSessionState, useStackApi };
|
|
46
|
+
export { ProjectApiProvider, StackApiProvider, useActiveStack, useProjectApi, useSessionState, useStackApi };
|
|
92
47
|
|
|
93
48
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/context.ts","../src/ProjectApiProvider.tsx","../src/StackApiProvider.tsx","../src/useActiveStack.ts","../src/useSessionState.ts"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/context.ts","../src/ProjectApiProvider.tsx","../src/StackApiProvider.tsx","../src/useActiveStack.ts","../src/useSessionState.ts"],"sourcesContent":["import { createContext, use } from 'react';\n\nimport type { ProjectApi, StackApi } from '@keboola/api-client';\n\nconst MISSING_STACK_API_ERROR = 'useStackApi must be used within <StackApiProvider />';\nconst MISSING_PROJECT_API_ERROR = 'useProjectApi must be used within <ProjectApiProvider />';\n\n/**\n * One stack: what is there before a project — signing in, the account, the project list.\n *\n * - A `ProjectApiProvider` provides its project's stack here too.\n */\nconst StackApiContext = createContext<StackApi | null>(null);\nexport const StackApiContextProvider = StackApiContext;\n\n// One project, on its stack.\nconst ProjectApiContext = createContext<ProjectApi | null>(null);\nexport const ProjectApiContextProvider = ProjectApiContext;\n\nexport const useStackApi = () => {\n const api = use(StackApiContext);\n if (api === null) throw new Error(MISSING_STACK_API_ERROR);\n return api;\n};\n\nexport const useProjectApi = () => {\n const api = use(ProjectApiContext);\n if (api === null) throw new Error(MISSING_PROJECT_API_ERROR);\n return api;\n};\n","import type { ReactNode } from 'react';\n\nimport type { ProjectApi } from '@keboola/api-client';\n\nimport { ProjectApiContextProvider, StackApiContextProvider } from './context';\n\ntype Props = {\n api: ProjectApi;\n children: ReactNode;\n};\n\n/** Provides one project to `useProjectApi()`, and its stack to `useStackApi()`. */\nexport const ProjectApiProvider = ({ api, children }: Props) => (\n <StackApiContextProvider value={api}>\n <ProjectApiContextProvider value={api}>{children}</ProjectApiContextProvider>\n </StackApiContextProvider>\n);\n","import type { ReactNode } from 'react';\n\nimport type { StackApi } from '@keboola/api-client';\n\nimport { StackApiContextProvider } from './context';\n\ntype Props = {\n api: StackApi;\n children: ReactNode;\n};\n\n/** Provides one stack to `useStackApi()`. */\nexport const StackApiProvider = ({ api, children }: Props) => (\n <StackApiContextProvider value={api}>{children}</StackApiContextProvider>\n);\n","import { useSyncExternalStore } from 'react';\n\nimport type { Session } from '@keboola/api-client';\n\n/** The active stack's row as a re-rendering value; the default stack until something selects another. */\nexport const useActiveStack = (session: Session) =>\n useSyncExternalStore(session.subscribe, session.stack.getActive);\n","import { useSyncExternalStore } from 'react';\n\nimport type { Session } from '@keboola/api-client';\n\n/** The session table as a re-rendering value — the binding every gate and panel reads it through. */\nexport const useSessionState = (session: Session) =>\n useSyncExternalStore(session.subscribe, session.getState);\n"],"mappings":";;;AAIA,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;;;;;;AAOlC,MAAM,kBAAkB,cAA+B,IAAI;AAC3D,MAAa,0BAA0B;AAGvC,MAAM,oBAAoB,cAAiC,IAAI;AAC/D,MAAa,4BAA4B;AAEzC,MAAa,oBAAoB;CAC/B,MAAM,MAAM,IAAI,eAAe;CAC/B,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,uBAAuB;CACzD,OAAO;AACT;AAEA,MAAa,sBAAsB;CACjC,MAAM,MAAM,IAAI,iBAAiB;CACjC,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,yBAAyB;CAC3D,OAAO;AACT;;;ACjBA,MAAa,sBAAsB,EAAE,KAAK,eACxC,oBAAC,yBAAD;CAAyB,OAAO;CAC9B,UAAA,oBAAC,2BAAD;EAA2B,OAAO;EAAM;CAAoC,CAAA;AACrD,CAAA;;;ACH3B,MAAa,oBAAoB,EAAE,KAAK,eACtC,oBAAC,yBAAD;CAAyB,OAAO;CAAM;AAAkC,CAAA;;;ACR1E,MAAa,kBAAkB,YAC7B,qBAAqB,QAAQ,WAAW,QAAQ,MAAM,SAAS;;;ACDjE,MAAa,mBAAmB,YAC9B,qBAAqB,QAAQ,WAAW,QAAQ,QAAQ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keboola/api-client-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "57.0.0",
|
|
4
4
|
"description": "React bindings for @keboola/api-client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@keboola/api-client": "^
|
|
53
|
+
"@keboola/api-client": "^57.0.0",
|
|
54
54
|
"react": "^19.0.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
58
|
-
"@keboola/api-client": "^
|
|
59
|
-
"@keboola/api-fixtures": "^
|
|
58
|
+
"@keboola/api-client": "^57.0.0",
|
|
59
|
+
"@keboola/api-fixtures": "^52.0.0",
|
|
60
60
|
"@keboola/eslint-plugin-design": "^0.8.0",
|
|
61
61
|
"@keboola/oxlint-config": "^10.3.0",
|
|
62
62
|
"@keboola/tsconfig": "^0.2.1",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"type-check": "tsc",
|
|
84
84
|
"lint": "pnpm lint:format && pnpm lint:oxlint",
|
|
85
85
|
"lint:fix": "oxlint --fix . && oxfmt",
|
|
86
|
-
"knip:check": "
|
|
86
|
+
"knip:check": "node ../../scripts/knip-check.mjs",
|
|
87
87
|
"knip:fix": "pnpm --dir ../.. exec knip --workspace packages/api-client-react --fix-type types,exports,files",
|
|
88
88
|
"lint:oxlint": "oxlint . --quiet",
|
|
89
89
|
"lint:format": "oxfmt --check",
|