docusaurus-theme-openapi-docs 0.0.0-1268 → 0.0.0-1294

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.
@@ -42,13 +42,36 @@ function getTypeFromSchema(schema) {
42
42
  }
43
43
  return undefined;
44
44
  }
45
+ // OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
46
+ // (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
47
+ // union form joined with ` | `.
48
+ function normalizeType(type) {
49
+ if (Array.isArray(type)) {
50
+ const filtered = type.filter((t) => typeof t === "string");
51
+ if (filtered.length === 0)
52
+ return { isUnion: false };
53
+ if (filtered.length === 1)
54
+ return { single: filtered[0], isUnion: false };
55
+ return { pretty: filtered.join(" | "), isUnion: true };
56
+ }
57
+ if (typeof type === "string")
58
+ return { single: type, isUnion: false };
59
+ return { isUnion: false };
60
+ }
45
61
  function prettyName(schema, circular) {
46
62
  // Handle enum-only schemas (valid in JSON Schema)
47
63
  // When enum is present without explicit type, treat as string
48
64
  if (schema.enum && !schema.type) {
49
65
  return "string";
50
66
  }
67
+ const t = normalizeType(schema.type);
51
68
  if (schema.format) {
69
+ if (t.single) {
70
+ return `${t.single}<${schema.format}>`;
71
+ }
72
+ if (t.isUnion) {
73
+ return `(${t.pretty})<${schema.format}>`;
74
+ }
52
75
  return schema.format;
53
76
  }
54
77
  if (schema.allOf) {
@@ -72,22 +95,23 @@ function prettyName(schema, circular) {
72
95
  if (schema.anyOf) {
73
96
  return "object";
74
97
  }
75
- if (schema.type === "object") {
76
- return schema.xml?.name ?? schema.type;
77
- // return schema.type;
98
+ if (t.single === "object") {
99
+ return schema.xml?.name ?? t.single;
78
100
  }
79
- if (schema.type === "array") {
80
- return schema.xml?.name ?? schema.type;
81
- // return schema.type;
101
+ if (t.single === "array") {
102
+ return schema.xml?.name ?? t.single;
82
103
  }
83
- if (Array.isArray(schema.type)) {
84
- return schema.type.join(" | ");
104
+ if (t.isUnion) {
105
+ return t.pretty;
85
106
  }
86
- return schema.title ?? schema.type;
107
+ return schema.title ?? t.single;
87
108
  }
88
109
  function getSchemaName(schema, circular) {
89
110
  if (schema.items) {
90
- return getSchemaName(schema.items, circular) + "[]";
111
+ const items = schema.items;
112
+ const inner = getSchemaName(items, circular);
113
+ const needsParens = Array.isArray(items.type) && items.type.length > 1;
114
+ return needsParens ? `(${inner})[]` : `${inner}[]`;
91
115
  }
92
116
  return prettyName(schema, circular) ?? "";
93
117
  }
@@ -48,4 +48,39 @@ describe("getSchemaName", () => {
48
48
  };
49
49
  expect((0, schema_1.getSchemaName)(schema)).toBe("integer[][][]");
50
50
  });
51
+ it("joins OpenAPI 3.1 type arrays with ` | ` (issue #950)", () => {
52
+ const schema = { type: ["string", "null"] };
53
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string | null");
54
+ });
55
+ it("unwraps a single-element type array", () => {
56
+ const schema = { type: ["integer"] };
57
+ expect((0, schema_1.getSchemaName)(schema)).toBe("integer");
58
+ });
59
+ it("renders single type with format as `type<format>`", () => {
60
+ const schema = {
61
+ type: "string",
62
+ format: "uuid",
63
+ };
64
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string<uuid>");
65
+ });
66
+ it("renders type union with format", () => {
67
+ const schema = {
68
+ type: ["string", "null"],
69
+ format: "uuid",
70
+ };
71
+ expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)<uuid>");
72
+ });
73
+ it("resolves type from an allOf wrapper that contains an enum", () => {
74
+ const schema = {
75
+ allOf: [{ type: "string", enum: ["a", "b"] }],
76
+ };
77
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string");
78
+ });
79
+ it("renders array of items whose type is a union", () => {
80
+ const schema = {
81
+ type: "array",
82
+ items: { type: ["string", "null"] },
83
+ };
84
+ expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)[]");
85
+ });
51
86
  });
@@ -101,9 +101,21 @@ function ApiItem(props) {
101
101
  api?.parameters?.forEach((param) => {
102
102
  const paramType = param.in;
103
103
  const paramsArray = params[paramType];
104
- const defaultValue = param.schema?.default;
104
+ const p = param;
105
+ // Prefill order: schema.default, then example sources. `default` is
106
+ // semantically a server-side fallback, so for required params authors
107
+ // typically rely on `example` / `examples`. See #544 and #1079.
108
+ const firstNamedExample =
109
+ p.examples && typeof p.examples === "object"
110
+ ? Object.values(p.examples)[0]?.value
111
+ : undefined;
112
+ const prefill =
113
+ p.schema?.default ??
114
+ p.example ??
115
+ p.schema?.example ??
116
+ firstNamedExample;
105
117
  const initialized =
106
- defaultValue !== undefined ? { ...param, value: defaultValue } : param;
118
+ prefill !== undefined ? { ...param, value: prefill } : param;
107
119
  paramsArray?.push(initialized);
108
120
  });
109
121
  const auth = (0, slice_1.createAuth)({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "0.0.0-1268",
4
+ "version": "0.0.0-1294",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -38,7 +38,7 @@
38
38
  "@types/postman-collection": "^3.5.11",
39
39
  "@types/react-modal": "^3.16.3",
40
40
  "concurrently": "^9.2.0",
41
- "docusaurus-plugin-openapi-docs": "0.0.0-1268",
41
+ "docusaurus-plugin-openapi-docs": "0.0.0-1294",
42
42
  "docusaurus-plugin-sass": "^0.2.6",
43
43
  "eslint-plugin-prettier": "^5.5.1"
44
44
  },
@@ -82,5 +82,5 @@
82
82
  "engines": {
83
83
  "node": ">=14"
84
84
  },
85
- "gitHead": "27848b60d7a6efd00d8a202a554b81152e24408e"
85
+ "gitHead": "dcce97d6a3cae4f76af8f02e81571e8ce5a394ac"
86
86
  }
@@ -58,4 +58,45 @@ describe("getSchemaName", () => {
58
58
  } as SchemaObject;
59
59
  expect(getSchemaName(schema)).toBe("integer[][][]");
60
60
  });
61
+
62
+ it("joins OpenAPI 3.1 type arrays with ` | ` (issue #950)", () => {
63
+ const schema = { type: ["string", "null"] } as unknown as SchemaObject;
64
+ expect(getSchemaName(schema)).toBe("string | null");
65
+ });
66
+
67
+ it("unwraps a single-element type array", () => {
68
+ const schema = { type: ["integer"] } as unknown as SchemaObject;
69
+ expect(getSchemaName(schema)).toBe("integer");
70
+ });
71
+
72
+ it("renders single type with format as `type<format>`", () => {
73
+ const schema = {
74
+ type: "string",
75
+ format: "uuid",
76
+ } as SchemaObject;
77
+ expect(getSchemaName(schema)).toBe("string<uuid>");
78
+ });
79
+
80
+ it("renders type union with format", () => {
81
+ const schema = {
82
+ type: ["string", "null"],
83
+ format: "uuid",
84
+ } as unknown as SchemaObject;
85
+ expect(getSchemaName(schema)).toBe("(string | null)<uuid>");
86
+ });
87
+
88
+ it("resolves type from an allOf wrapper that contains an enum", () => {
89
+ const schema = {
90
+ allOf: [{ type: "string", enum: ["a", "b"] }],
91
+ } as unknown as SchemaObject;
92
+ expect(getSchemaName(schema)).toBe("string");
93
+ });
94
+
95
+ it("renders array of items whose type is a union", () => {
96
+ const schema: SchemaObject = {
97
+ type: "array",
98
+ items: { type: ["string", "null"] } as any,
99
+ } as SchemaObject;
100
+ expect(getSchemaName(schema)).toBe("(string | null)[]");
101
+ });
61
102
  });
@@ -48,6 +48,24 @@ function getTypeFromSchema(schema: SchemaObject): string | undefined {
48
48
  return undefined;
49
49
  }
50
50
 
51
+ // OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
52
+ // (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
53
+ // union form joined with ` | `.
54
+ function normalizeType(type: unknown): {
55
+ single?: string;
56
+ pretty?: string;
57
+ isUnion: boolean;
58
+ } {
59
+ if (Array.isArray(type)) {
60
+ const filtered = type.filter((t): t is string => typeof t === "string");
61
+ if (filtered.length === 0) return { isUnion: false };
62
+ if (filtered.length === 1) return { single: filtered[0], isUnion: false };
63
+ return { pretty: filtered.join(" | "), isUnion: true };
64
+ }
65
+ if (typeof type === "string") return { single: type, isUnion: false };
66
+ return { isUnion: false };
67
+ }
68
+
51
69
  function prettyName(schema: SchemaObject, circular?: boolean) {
52
70
  // Handle enum-only schemas (valid in JSON Schema)
53
71
  // When enum is present without explicit type, treat as string
@@ -55,7 +73,15 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
55
73
  return "string";
56
74
  }
57
75
 
76
+ const t = normalizeType(schema.type);
77
+
58
78
  if (schema.format) {
79
+ if (t.single) {
80
+ return `${t.single}<${schema.format}>`;
81
+ }
82
+ if (t.isUnion) {
83
+ return `(${t.pretty})<${schema.format}>`;
84
+ }
59
85
  return schema.format;
60
86
  }
61
87
 
@@ -83,21 +109,19 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
83
109
  return "object";
84
110
  }
85
111
 
86
- if (schema.type === "object") {
87
- return schema.xml?.name ?? schema.type;
88
- // return schema.type;
112
+ if (t.single === "object") {
113
+ return schema.xml?.name ?? t.single;
89
114
  }
90
115
 
91
- if (schema.type === "array") {
92
- return schema.xml?.name ?? schema.type;
93
- // return schema.type;
116
+ if (t.single === "array") {
117
+ return schema.xml?.name ?? t.single;
94
118
  }
95
119
 
96
- if (Array.isArray(schema.type)) {
97
- return schema.type.join(" | ");
120
+ if (t.isUnion) {
121
+ return t.pretty;
98
122
  }
99
123
 
100
- return schema.title ?? schema.type;
124
+ return schema.title ?? t.single;
101
125
  }
102
126
 
103
127
  export function getSchemaName(
@@ -105,7 +129,11 @@ export function getSchemaName(
105
129
  circular?: boolean
106
130
  ): string {
107
131
  if (schema.items) {
108
- return getSchemaName(schema.items as SchemaObject, circular) + "[]";
132
+ const items = schema.items as SchemaObject;
133
+ const inner = getSchemaName(items, circular);
134
+ const needsParens =
135
+ Array.isArray((items as any).type) && (items as any).type.length > 1;
136
+ return needsParens ? `(${inner})[]` : `${inner}[]`;
109
137
  }
110
138
 
111
139
  return prettyName(schema, circular) ?? "";
@@ -123,10 +123,22 @@ export default function ApiItem(props: Props): JSX.Element {
123
123
  (param: { in: "path" | "query" | "header" | "cookie" }) => {
124
124
  const paramType = param.in;
125
125
  const paramsArray: ParameterObject[] = params[paramType];
126
- const defaultValue = (param as any).schema?.default;
126
+ const p = param as any;
127
+ // Prefill order: schema.default, then example sources. `default` is
128
+ // semantically a server-side fallback, so for required params authors
129
+ // typically rely on `example` / `examples`. See #544 and #1079.
130
+ const firstNamedExample =
131
+ p.examples && typeof p.examples === "object"
132
+ ? (Object.values(p.examples)[0] as any)?.value
133
+ : undefined;
134
+ const prefill =
135
+ p.schema?.default ??
136
+ p.example ??
137
+ p.schema?.example ??
138
+ firstNamedExample;
127
139
  const initialized =
128
- defaultValue !== undefined
129
- ? ({ ...param, value: defaultValue } as unknown as ParameterObject)
140
+ prefill !== undefined
141
+ ? ({ ...param, value: prefill } as unknown as ParameterObject)
130
142
  : (param as ParameterObject);
131
143
  paramsArray?.push(initialized);
132
144
  }