Skip to content

Commit c475479

Browse files
taylessserrata
andcommitted
feat: implement authPersistence in ThemeConfig
- Fix spelling: authPersistance → authPersistence - Actually implement the feature (was defined but never read) - Rename persistanceMiddleware.ts → persistenceMiddleware.ts - Add proper null checks for storage.getItem('server') - Add JSDoc documentation for the config option Resolves #1239 Resolves #1238 Co-authored-by: sserrata <[email protected]>
1 parent e1e210e commit c475479

File tree

5 files changed

+44
-25
lines changed

5 files changed

+44
-25
lines changed

packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Authorization/slice.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function createAuth({
5858
};
5959
options?: ThemeConfig["api"];
6060
}): AuthState {
61-
const storage = createStorage("sessionStorage");
61+
const storage = createStorage(opts?.authPersistence ?? "sessionStorage");
6262

6363
let data: AuthState["data"] = {};
6464
let options: AuthState["options"] = {};

packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/persistanceMiddleware.ts renamed to packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/persistenceMiddleware.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,29 @@
55
* LICENSE file in the root directory of this source tree.
66
* ========================================================================== */
77

8-
import { Middleware } from "@reduxjs/toolkit";
8+
import type { Middleware } from "@reduxjs/toolkit";
99
import {
1010
setAuthData,
1111
setSelectedAuth,
1212
} from "@theme/ApiExplorer/Authorization/slice";
13-
import { AppDispatch, RootState } from "@theme/ApiItem/store";
14-
/* eslint-disable import/no-extraneous-dependencies*/
15-
import { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
13+
import type { AppDispatch, RootState } from "@theme/ApiItem/store";
14+
import type { ServerObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
15+
import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
1616

1717
import { createStorage, hashArray } from "./storage-utils";
1818

19-
export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
20-
const persistanceMiddleware: Middleware<{}, RootState, AppDispatch> =
19+
export function createPersistenceMiddleware(options: ThemeConfig["api"]) {
20+
const persistenceMiddleware: Middleware<{}, RootState, AppDispatch> =
2121
(storeAPI) =>
2222
(next) =>
2323
(action: ReturnType<typeof setAuthData | typeof setSelectedAuth> | any) => {
2424
const result = next(action);
2525

2626
const state = storeAPI.getState();
2727

28-
const storage = createStorage("sessionStorage");
28+
const storage = createStorage(
29+
options?.authPersistence ?? "sessionStorage"
30+
);
2931

3032
if (action.type === setAuthData.type) {
3133
for (const [key, value] of Object.entries(state.auth.data)) {
@@ -60,14 +62,20 @@ export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
6062
}
6163

6264
if (action.type === "server/setServerVariable") {
63-
const server = storage.getItem("server") ?? "{}";
65+
const server = storage.getItem("server");
66+
if (!server) {
67+
return result;
68+
}
6469
const variables = JSON.parse(action.payload);
65-
let serverObject = JSON.parse(server);
66-
serverObject.variables[variables.key].default = variables.value;
67-
storage.setItem("server", JSON.stringify(serverObject));
70+
71+
const serverObject = (JSON.parse(server) as ServerObject) ?? {};
72+
if (serverObject.variables?.[variables.key]) {
73+
serverObject.variables[variables.key].default = variables.value;
74+
storage.setItem("server", JSON.stringify(serverObject));
75+
}
6876
}
6977

7078
return result;
7179
};
72-
return persistanceMiddleware;
80+
return persistenceMiddleware;
7381
}

packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/storage-utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ export function hashArray(arr: string[]) {
1717
return hash(res);
1818
}
1919

20-
type Persistance = false | "localStorage" | "sessionStorage" | undefined;
20+
type Persistence = false | "localStorage" | "sessionStorage" | undefined;
2121

22-
export function createStorage(persistance: Persistance): Storage {
23-
if (persistance === false) {
22+
export function createStorage(persistence: Persistence): Storage {
23+
if (persistence === false) {
2424
return {
2525
getItem: () => null,
2626
setItem: () => {},
@@ -31,7 +31,7 @@ export function createStorage(persistance: Persistance): Storage {
3131
};
3232
}
3333

34-
if (persistance === "sessionStorage") {
34+
if (persistence === "sessionStorage") {
3535
return sessionStorage;
3636
}
3737

packages/docusaurus-theme-openapi-docs/src/theme/ApiItem/index.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import { HtmlClassNameProvider } from "@docusaurus/theme-common";
1414
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
1515
import useIsBrowser from "@docusaurus/useIsBrowser";
1616
import { createAuth } from "@theme/ApiExplorer/Authorization/slice";
17-
import { createPersistanceMiddleware } from "@theme/ApiExplorer/persistanceMiddleware";
17+
import { createPersistenceMiddleware } from "@theme/ApiExplorer/persistenceMiddleware";
18+
import { createStorage } from "@theme/ApiExplorer/storage-utils";
1819
import DocItemLayout from "@theme/ApiItem/Layout";
1920
import CodeBlock from "@theme/CodeBlock";
2021
import type { Props } from "@theme/DocItem";
@@ -90,11 +91,11 @@ export default function ApiItem(props: Props): JSX.Element {
9091

9192
// Define store2
9293
let store2: any = {};
93-
const persistanceMiddleware = createPersistanceMiddleware(options);
94+
const persistenceMiddleware = createPersistenceMiddleware(options);
9495

9596
// Init store for SSR
9697
if (!isBrowser) {
97-
store2 = createStoreWithoutState({}, [persistanceMiddleware]);
98+
store2 = createStoreWithoutState({}, [persistenceMiddleware]);
9899
}
99100

100101
// Init store for CSR to hydrate components
@@ -129,11 +130,15 @@ export default function ApiItem(props: Props): JSX.Element {
129130
securitySchemes: api?.securitySchemes,
130131
options,
131132
});
133+
134+
const storage = createStorage(options?.authPersistence ?? "sessionStorage");
132135
// TODO: determine way to rehydrate without flashing
133136
// const acceptValue = window?.sessionStorage.getItem("accept");
134137
// const contentTypeValue = window?.sessionStorage.getItem("contentType");
135-
const server = window?.sessionStorage.getItem("server");
136-
const serverObject = (JSON.parse(server!) as ServerObject) ?? {};
138+
const server = storage.getItem("server");
139+
const serverObject = server
140+
? (JSON.parse(server) as ServerObject)
141+
: undefined;
137142

138143
store2 = createStoreWithState(
139144
{
@@ -146,15 +151,15 @@ export default function ApiItem(props: Props): JSX.Element {
146151
options: contentTypeArray,
147152
},
148153
server: {
149-
value: serverObject.url ? serverObject : undefined,
154+
value: serverObject?.url ? serverObject : undefined,
150155
options: servers,
151156
},
152157
response: { value: undefined },
153158
body: { type: "empty" },
154159
params,
155160
auth,
156161
},
157-
[persistanceMiddleware]
162+
[persistenceMiddleware]
158163
);
159164
}
160165

packages/docusaurus-theme-openapi-docs/src/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ import type { JSONSchema4, JSONSchema6, JSONSchema7 } from "json-schema";
1111
export interface ThemeConfig {
1212
api?: {
1313
proxy?: string;
14-
authPersistance?: false | "localStorage" | "sessionStorage";
14+
/**
15+
* Controls how authentication credentials are persisted in the API explorer.
16+
* - `false`: No persistence (in-memory only)
17+
* - `"sessionStorage"`: Persist for the browser session (default)
18+
* - `"localStorage"`: Persist across browser sessions
19+
*/
20+
authPersistence?: false | "sessionStorage" | "localStorage";
1521
/** Request timeout in milliseconds. Defaults to 30000 (30 seconds). */
1622
requestTimeout?: number;
1723
};

0 commit comments

Comments
 (0)