@scalar/workspace-store 0.21.0 → 0.22.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/CHANGELOG.md +28 -0
- package/dist/client.d.ts +14 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8 -6
- package/dist/client.js.map +2 -2
- package/dist/events/bus.d.ts +1 -1
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js.map +1 -1
- package/dist/events/definitions/auth.d.ts +2 -1
- package/dist/events/definitions/auth.d.ts.map +1 -1
- package/dist/events/definitions/document.d.ts +11 -0
- package/dist/events/definitions/document.d.ts.map +1 -1
- package/dist/events/definitions/index.d.ts +3 -1
- package/dist/events/definitions/index.d.ts.map +1 -1
- package/dist/events/definitions/operation.d.ts +20 -1
- package/dist/events/definitions/operation.d.ts.map +1 -1
- package/dist/events/definitions/tabs.d.ts +16 -1
- package/dist/events/definitions/tabs.d.ts.map +1 -1
- package/dist/events/definitions/tag.d.ts +15 -0
- package/dist/events/definitions/tag.d.ts.map +1 -0
- package/dist/events/definitions/tag.js +1 -0
- package/dist/events/definitions/tag.js.map +7 -0
- package/dist/events/definitions/ui.d.ts +118 -61
- package/dist/events/definitions/ui.d.ts.map +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js.map +2 -2
- package/dist/mutators/auth.d.ts +6 -1
- package/dist/mutators/auth.d.ts.map +1 -1
- package/dist/mutators/document.d.ts +3 -0
- package/dist/mutators/document.d.ts.map +1 -1
- package/dist/mutators/document.js +24 -0
- package/dist/mutators/document.js.map +2 -2
- package/dist/mutators/index.d.ts +28 -8
- package/dist/mutators/index.d.ts.map +1 -1
- package/dist/mutators/index.js +24 -1
- package/dist/mutators/index.js.map +2 -2
- package/dist/mutators/operation.d.ts +27 -8
- package/dist/mutators/operation.d.ts.map +1 -1
- package/dist/mutators/operation.js +75 -7
- package/dist/mutators/operation.js.map +2 -2
- package/dist/mutators/request.d.ts +2 -1
- package/dist/mutators/request.d.ts.map +1 -1
- package/dist/mutators/request.js.map +1 -1
- package/dist/mutators/server.d.ts.map +1 -1
- package/dist/mutators/server.js +1 -1
- package/dist/mutators/server.js.map +2 -2
- package/dist/mutators/tabs.d.ts +44 -0
- package/dist/mutators/tabs.d.ts.map +1 -0
- package/dist/mutators/tabs.js +133 -0
- package/dist/mutators/tabs.js.map +7 -0
- package/dist/mutators/tag.d.ts +12 -0
- package/dist/mutators/tag.d.ts.map +1 -0
- package/dist/mutators/tag.js +19 -0
- package/dist/mutators/tag.js.map +7 -0
- package/dist/navigation/helpers/get-openapi-object.d.ts +35 -0
- package/dist/navigation/helpers/get-openapi-object.d.ts.map +1 -0
- package/dist/navigation/helpers/get-openapi-object.js +31 -0
- package/dist/navigation/helpers/get-openapi-object.js.map +7 -0
- package/dist/navigation/helpers/get-operation-entries.d.ts +24 -0
- package/dist/navigation/helpers/get-operation-entries.d.ts.map +1 -0
- package/dist/navigation/helpers/get-operation-entries.js +33 -0
- package/dist/navigation/helpers/get-operation-entries.js.map +7 -0
- package/dist/navigation/helpers/get-parent-entry.d.ts +15 -0
- package/dist/navigation/helpers/get-parent-entry.d.ts.map +1 -0
- package/dist/navigation/helpers/get-parent-entry.js +13 -0
- package/dist/navigation/helpers/get-parent-entry.js.map +7 -0
- package/dist/navigation/helpers/traverse-description.d.ts +0 -1
- package/dist/navigation/helpers/traverse-description.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-description.js +0 -1
- package/dist/navigation/helpers/traverse-description.js.map +2 -2
- package/dist/navigation/helpers/traverse-document.js +1 -1
- package/dist/navigation/helpers/traverse-document.js.map +2 -2
- package/dist/navigation/helpers/traverse-paths.js +1 -1
- package/dist/navigation/helpers/traverse-paths.js.map +1 -1
- package/dist/navigation/helpers/traverse-tags.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-tags.js +2 -2
- package/dist/navigation/helpers/traverse-tags.js.map +2 -2
- package/dist/navigation/helpers/utils.d.ts +2 -1
- package/dist/navigation/helpers/utils.d.ts.map +1 -1
- package/dist/navigation/helpers/utils.js.map +1 -1
- package/dist/navigation/index.d.ts +2 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +5 -3
- package/dist/navigation/index.js.map +2 -2
- package/dist/schemas/extensions/operation/index.d.ts +4 -1
- package/dist/schemas/extensions/operation/index.d.ts.map +1 -1
- package/dist/schemas/extensions/operation/index.js +22 -0
- package/dist/schemas/extensions/operation/index.js.map +3 -3
- package/dist/schemas/extensions/operation/x-code-samples.d.ts +0 -5
- package/dist/schemas/extensions/operation/x-code-samples.d.ts.map +1 -1
- package/dist/schemas/extensions/operation/x-code-samples.js +0 -1
- package/dist/schemas/extensions/operation/x-code-samples.js.map +2 -2
- package/dist/schemas/extensions/operation/x-post-response.d.ts +0 -18
- package/dist/schemas/extensions/operation/x-post-response.d.ts.map +1 -1
- package/dist/schemas/extensions/operation/x-post-response.js.map +1 -1
- package/dist/schemas/extensions/tag/x-tag-groups.d.ts +2 -13
- package/dist/schemas/extensions/tag/x-tag-groups.d.ts.map +1 -1
- package/dist/schemas/extensions/tag/x-tag-groups.js +0 -1
- package/dist/schemas/extensions/tag/x-tag-groups.js.map +2 -2
- package/dist/schemas/extensions/workspace/index.d.ts +4 -0
- package/dist/schemas/extensions/workspace/index.d.ts.map +1 -0
- package/dist/schemas/extensions/workspace/index.js +15 -0
- package/dist/schemas/extensions/workspace/index.js.map +7 -0
- package/dist/schemas/extensions/workspace/x-scalar-tabs.d.ts +36 -0
- package/dist/schemas/extensions/workspace/x-scalar-tabs.d.ts.map +1 -0
- package/dist/schemas/extensions/workspace/x-scalar-tabs.js +16 -0
- package/dist/schemas/extensions/workspace/x-scalar-tabs.js.map +7 -0
- package/dist/schemas/inmemory-workspace.d.ts +5 -6
- package/dist/schemas/inmemory-workspace.d.ts.map +1 -1
- package/dist/schemas/navigation.d.ts +8 -0
- package/dist/schemas/navigation.d.ts.map +1 -1
- package/dist/schemas/navigation.js.map +1 -1
- package/dist/schemas/reference-config/index.d.ts +2 -3
- package/dist/schemas/reference-config/index.d.ts.map +1 -1
- package/dist/schemas/reference-config/settings.d.ts +2 -3
- package/dist/schemas/reference-config/settings.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/header.d.ts +0 -45
- package/dist/schemas/v3.1/strict/header.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/header.js +1 -3
- package/dist/schemas/v3.1/strict/header.js.map +2 -2
- package/dist/schemas/v3.1/strict/oauth-flow.d.ts +0 -99
- package/dist/schemas/v3.1/strict/oauth-flow.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/oauth-flow.js +0 -7
- package/dist/schemas/v3.1/strict/oauth-flow.js.map +2 -2
- package/dist/schemas/v3.1/strict/openapi-document.d.ts +71 -104
- package/dist/schemas/v3.1/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/openapi-document.js +0 -1
- package/dist/schemas/v3.1/strict/openapi-document.js.map +2 -2
- package/dist/schemas/v3.1/strict/parameter.d.ts +1 -101
- package/dist/schemas/v3.1/strict/parameter.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/parameter.js +1 -4
- package/dist/schemas/v3.1/strict/parameter.js.map +2 -2
- package/dist/schemas/v3.1/strict/ref-definitions.d.ts +0 -1
- package/dist/schemas/v3.1/strict/ref-definitions.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/ref-definitions.js +0 -2
- package/dist/schemas/v3.1/strict/ref-definitions.js.map +2 -2
- package/dist/schemas/v3.1/strict/schema.d.ts +28 -11
- package/dist/schemas/v3.1/strict/schema.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/schema.js +2 -2
- package/dist/schemas/v3.1/strict/schema.js.map +2 -2
- package/dist/schemas/v3.1/strict/security-scheme.d.ts +1 -54
- package/dist/schemas/v3.1/strict/security-scheme.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/security-scheme.js +0 -5
- package/dist/schemas/v3.1/strict/security-scheme.js.map +2 -2
- package/dist/schemas/workspace-specification/config.d.ts +2 -3
- package/dist/schemas/workspace-specification/config.d.ts.map +1 -1
- package/dist/schemas/workspace-specification/index.d.ts +2 -3
- package/dist/schemas/workspace-specification/index.d.ts.map +1 -1
- package/dist/schemas/workspace.d.ts +35 -22
- package/dist/schemas/workspace.d.ts.map +1 -1
- package/dist/schemas/workspace.js +11 -6
- package/dist/schemas/workspace.js.map +2 -2
- package/package.json +50 -36
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { TabEvents } from '../events/definitions/tabs.js';
|
|
2
|
+
import type { Workspace } from '../schemas.js';
|
|
3
|
+
/**
|
|
4
|
+
* Updates the tabs and active tab index in the workspace.
|
|
5
|
+
* This is used for bulk updates when synchronizing state.
|
|
6
|
+
*/
|
|
7
|
+
export declare const updateTabs: (workspace: Workspace | null, payload: TabEvents["tabs:update:tabs"]) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Adds a new tab by duplicating the currently active tab.
|
|
10
|
+
* This preserves the user's context when opening a new tab.
|
|
11
|
+
*/
|
|
12
|
+
export declare const addTab: (workspace: Workspace | null, _payload: TabEvents["tabs:add:tab"]) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Closes the currently active tab.
|
|
15
|
+
* Prevents closing if only one tab remains, to ensure the user always has a tab open.
|
|
16
|
+
* Adjusts the active index if needed to keep it in bounds.
|
|
17
|
+
*/
|
|
18
|
+
export declare const closeTab: (workspace: Workspace | null, payload: TabEvents["tabs:close:tab"]) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Closes all other tabs except the one at the given index
|
|
21
|
+
*/
|
|
22
|
+
export declare const closeOtherTabs: (workspace: Workspace | null, payload: TabEvents["tabs:close:other-tabs"]) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Navigates to the previous tab in the list.
|
|
25
|
+
* Does nothing if already at the first tab.
|
|
26
|
+
*/
|
|
27
|
+
export declare const navigatePreviousTab: (workspace: Workspace | null, _payload: TabEvents["tabs:navigate:previous"]) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Navigates to the next tab in the list.
|
|
30
|
+
* Does nothing if already at the last tab.
|
|
31
|
+
*/
|
|
32
|
+
export declare const navigateNextTab: (workspace: Workspace | null, _payload: TabEvents["tabs:navigate:next"]) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Focuses a specific tab based on keyboard number input (1-9).
|
|
35
|
+
* Extracts the digit from the keyboard event and focuses that tab.
|
|
36
|
+
* Tab numbering starts at 1 for user convenience but uses 0-based indexing internally.
|
|
37
|
+
*/
|
|
38
|
+
export declare const focusTab: (workspace: Workspace | null, payload: TabEvents["tabs:focus:tab"]) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Focuses the last tab in the list.
|
|
41
|
+
* This provides a quick way to jump to the end, regardless of how many tabs exist.
|
|
42
|
+
*/
|
|
43
|
+
export declare const focusLastTab: (workspace: Workspace | null, _payload: TabEvents["tabs:focus:tab-last"]) => boolean;
|
|
44
|
+
//# sourceMappingURL=tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/mutators/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAoC1C;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,kBAAkB,CAAC,KAAG,IAYhG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,UAAU,SAAS,CAAC,cAAc,CAAC,KAAG,OAkBzF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,gBAAgB,CAAC,KAAG,OA8B5F,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,uBAAuB,CAAC,KAAG,OAezG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,SAAS,GAAG,IAAI,EAC3B,UAAU,SAAS,CAAC,wBAAwB,CAAC,KAC5C,OAaF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,UAAU,SAAS,CAAC,oBAAoB,CAAC,KAAG,OAcxG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,gBAAgB,CAAC,KAAG,OAsB5F,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,WAAW,SAAS,GAAG,IAAI,EAAE,UAAU,SAAS,CAAC,qBAAqB,CAAC,KAAG,OAatG,CAAA"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { unpackProxyObject } from "../helpers/unpack-proxy.js";
|
|
2
|
+
const TAB_UNPACK_DEPTH = 1;
|
|
3
|
+
const hasValidTabs = (workspace) => {
|
|
4
|
+
return workspace !== null && workspace["x-scalar-tabs"] !== void 0;
|
|
5
|
+
};
|
|
6
|
+
const getUnpackedTabs = (workspace) => {
|
|
7
|
+
return unpackProxyObject(workspace["x-scalar-tabs"], { depth: TAB_UNPACK_DEPTH });
|
|
8
|
+
};
|
|
9
|
+
const getActiveIndex = (workspace) => {
|
|
10
|
+
return workspace["x-scalar-active-tab"] ?? 0;
|
|
11
|
+
};
|
|
12
|
+
const updateTabs = (workspace, payload) => {
|
|
13
|
+
if (!workspace) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (payload["x-scalar-tabs"]) {
|
|
17
|
+
workspace["x-scalar-tabs"] = payload["x-scalar-tabs"];
|
|
18
|
+
}
|
|
19
|
+
if (payload["x-scalar-active-tab"] !== void 0) {
|
|
20
|
+
workspace["x-scalar-active-tab"] = payload["x-scalar-active-tab"];
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const addTab = (workspace, _payload) => {
|
|
24
|
+
if (!hasValidTabs(workspace)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const tabs = getUnpackedTabs(workspace);
|
|
28
|
+
const activeIndex = getActiveIndex(workspace);
|
|
29
|
+
const currentTab = tabs[activeIndex];
|
|
30
|
+
if (!currentTab) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const newTabs = [...tabs, { ...currentTab }];
|
|
34
|
+
workspace["x-scalar-tabs"] = newTabs;
|
|
35
|
+
workspace["x-scalar-active-tab"] = newTabs.length - 1;
|
|
36
|
+
return true;
|
|
37
|
+
};
|
|
38
|
+
const closeTab = (workspace, payload) => {
|
|
39
|
+
const getInputIndex = () => {
|
|
40
|
+
if ("event" in payload) {
|
|
41
|
+
return payload.event.code.startsWith("Digit") ? Number.parseInt(payload.event.key, 10) - 1 : Number.NaN;
|
|
42
|
+
}
|
|
43
|
+
return payload.index;
|
|
44
|
+
};
|
|
45
|
+
if (!hasValidTabs(workspace)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const tabs = getUnpackedTabs(workspace);
|
|
49
|
+
const index = getInputIndex();
|
|
50
|
+
if (tabs.length <= 1) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
workspace["x-scalar-tabs"] = tabs.filter((_, i) => i !== index);
|
|
54
|
+
if (index >= tabs.length - 1) {
|
|
55
|
+
workspace["x-scalar-active-tab"] = tabs.length - 2;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
59
|
+
const closeOtherTabs = (workspace, payload) => {
|
|
60
|
+
if (!hasValidTabs(workspace)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const tabs = getUnpackedTabs(workspace);
|
|
64
|
+
if (tabs.length <= 1) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
workspace["x-scalar-tabs"] = tabs.filter((_, index) => index === payload.index);
|
|
68
|
+
workspace["x-scalar-active-tab"] = 0;
|
|
69
|
+
return true;
|
|
70
|
+
};
|
|
71
|
+
const navigatePreviousTab = (workspace, _payload) => {
|
|
72
|
+
if (!hasValidTabs(workspace)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const activeIndex = getActiveIndex(workspace);
|
|
76
|
+
if (activeIndex <= 0) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
workspace["x-scalar-active-tab"] = activeIndex - 1;
|
|
80
|
+
return true;
|
|
81
|
+
};
|
|
82
|
+
const navigateNextTab = (workspace, _payload) => {
|
|
83
|
+
if (!hasValidTabs(workspace)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const tabs = getUnpackedTabs(workspace);
|
|
87
|
+
const activeIndex = getActiveIndex(workspace);
|
|
88
|
+
if (activeIndex >= tabs.length - 1) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
workspace["x-scalar-active-tab"] = activeIndex + 1;
|
|
92
|
+
return true;
|
|
93
|
+
};
|
|
94
|
+
const focusTab = (workspace, payload) => {
|
|
95
|
+
if (!hasValidTabs(workspace)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const getInputIndex = () => {
|
|
99
|
+
if ("event" in payload) {
|
|
100
|
+
return payload.event.code.startsWith("Digit") ? Number.parseInt(payload.event.key, 10) - 1 : Number.NaN;
|
|
101
|
+
}
|
|
102
|
+
return payload.index;
|
|
103
|
+
};
|
|
104
|
+
const tabs = getUnpackedTabs(workspace);
|
|
105
|
+
const newActiveIndex = getInputIndex();
|
|
106
|
+
if (Number.isNaN(newActiveIndex) || newActiveIndex < 0 || newActiveIndex >= tabs.length) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
workspace["x-scalar-active-tab"] = newActiveIndex;
|
|
110
|
+
return true;
|
|
111
|
+
};
|
|
112
|
+
const focusLastTab = (workspace, _payload) => {
|
|
113
|
+
if (!hasValidTabs(workspace)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
const tabs = getUnpackedTabs(workspace);
|
|
117
|
+
if (tabs.length <= 1) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
workspace["x-scalar-active-tab"] = tabs.length - 1;
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
export {
|
|
124
|
+
addTab,
|
|
125
|
+
closeOtherTabs,
|
|
126
|
+
closeTab,
|
|
127
|
+
focusLastTab,
|
|
128
|
+
focusTab,
|
|
129
|
+
navigateNextTab,
|
|
130
|
+
navigatePreviousTab,
|
|
131
|
+
updateTabs
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=tabs.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/mutators/tabs.ts"],
|
|
4
|
+
"sourcesContent": ["import type { TabEvents } from '@/events/definitions/tabs'\nimport { unpackProxyObject } from '@/helpers/unpack-proxy'\nimport type { Workspace } from '@/schemas'\n\n/**\n * Depth level for unpacking tab proxy objects.\n * We only need shallow unpacking since tabs are a flat array.\n */\nconst TAB_UNPACK_DEPTH = 1\n\n/**\n * Helper to validate that workspace has tabs configured.\n * Returns false if workspace or tabs are not available.\n */\nconst hasValidTabs = (\n workspace: Workspace | null,\n): workspace is Workspace & { 'x-scalar-tabs': NonNullable<Workspace['x-scalar-tabs']> } => {\n return workspace !== null && workspace['x-scalar-tabs'] !== undefined\n}\n\n/**\n * Helper to get the unpacked tabs array from workspace.\n * Returns the tabs as a plain array, not a proxy.\n */\nconst getUnpackedTabs = (\n workspace: Workspace & { 'x-scalar-tabs': NonNullable<Workspace['x-scalar-tabs']> },\n): ReturnType<typeof unpackProxyObject<NonNullable<Workspace['x-scalar-tabs']>>> => {\n return unpackProxyObject(workspace['x-scalar-tabs']!, { depth: TAB_UNPACK_DEPTH })\n}\n\n/**\n * Helper to get the current active tab index.\n * Defaults to 0 if not set.\n */\nconst getActiveIndex = (workspace: Workspace): number => {\n return workspace['x-scalar-active-tab'] ?? 0\n}\n\n/**\n * Updates the tabs and active tab index in the workspace.\n * This is used for bulk updates when synchronizing state.\n */\nexport const updateTabs = (workspace: Workspace | null, payload: TabEvents['tabs:update:tabs']): void => {\n if (!workspace) {\n return\n }\n\n if (payload['x-scalar-tabs']) {\n workspace['x-scalar-tabs'] = payload['x-scalar-tabs']\n }\n\n if (payload['x-scalar-active-tab'] !== undefined) {\n workspace['x-scalar-active-tab'] = payload['x-scalar-active-tab']\n }\n}\n\n/**\n * Adds a new tab by duplicating the currently active tab.\n * This preserves the user's context when opening a new tab.\n */\nexport const addTab = (workspace: Workspace | null, _payload: TabEvents['tabs:add:tab']): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const tabs = getUnpackedTabs(workspace)\n const activeIndex = getActiveIndex(workspace)\n const currentTab = tabs[activeIndex]\n\n if (!currentTab) {\n return false\n }\n\n const newTabs = [...tabs, { ...currentTab }]\n\n workspace['x-scalar-tabs'] = newTabs\n workspace['x-scalar-active-tab'] = newTabs.length - 1\n return true\n}\n\n/**\n * Closes the currently active tab.\n * Prevents closing if only one tab remains, to ensure the user always has a tab open.\n * Adjusts the active index if needed to keep it in bounds.\n */\nexport const closeTab = (workspace: Workspace | null, payload: TabEvents['tabs:close:tab']): boolean => {\n const getInputIndex = (): number => {\n if ('event' in payload) {\n return payload.event.code.startsWith('Digit') ? Number.parseInt(payload.event.key, 10) - 1 : Number.NaN\n }\n return payload.index\n }\n\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const tabs = getUnpackedTabs(workspace)\n const index = getInputIndex()\n\n if (tabs.length <= 1) {\n return false\n }\n\n workspace['x-scalar-tabs'] = tabs.filter((_, i) => i !== index)\n\n /**\n * If we closed a tab at the end, the active index needs to move back.\n * This ensures the active tab stays within bounds after removal.\n */\n if (index >= tabs.length - 1) {\n workspace['x-scalar-active-tab'] = tabs.length - 2\n }\n\n return true\n}\n\n/**\n * Closes all other tabs except the one at the given index\n */\nexport const closeOtherTabs = (workspace: Workspace | null, payload: TabEvents['tabs:close:other-tabs']): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const tabs = getUnpackedTabs(workspace)\n\n if (tabs.length <= 1) {\n return false\n }\n\n workspace['x-scalar-tabs'] = tabs.filter((_, index) => index === payload.index)\n // set the active tab to the first tab since we closed all other tabs\n workspace['x-scalar-active-tab'] = 0\n return true\n}\n\n/**\n * Navigates to the previous tab in the list.\n * Does nothing if already at the first tab.\n */\nexport const navigatePreviousTab = (\n workspace: Workspace | null,\n _payload: TabEvents['tabs:navigate:previous'],\n): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const activeIndex = getActiveIndex(workspace)\n\n if (activeIndex <= 0) {\n return false\n }\n\n workspace['x-scalar-active-tab'] = activeIndex - 1\n return true\n}\n\n/**\n * Navigates to the next tab in the list.\n * Does nothing if already at the last tab.\n */\nexport const navigateNextTab = (workspace: Workspace | null, _payload: TabEvents['tabs:navigate:next']): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const tabs = getUnpackedTabs(workspace)\n const activeIndex = getActiveIndex(workspace)\n\n if (activeIndex >= tabs.length - 1) {\n return false\n }\n\n workspace['x-scalar-active-tab'] = activeIndex + 1\n return true\n}\n\n/**\n * Focuses a specific tab based on keyboard number input (1-9).\n * Extracts the digit from the keyboard event and focuses that tab.\n * Tab numbering starts at 1 for user convenience but uses 0-based indexing internally.\n */\nexport const focusTab = (workspace: Workspace | null, payload: TabEvents['tabs:focus:tab']): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const getInputIndex = (): number => {\n if ('event' in payload) {\n return payload.event.code.startsWith('Digit') ? Number.parseInt(payload.event.key, 10) - 1 : Number.NaN\n }\n return payload.index\n }\n\n const tabs = getUnpackedTabs(workspace)\n\n const newActiveIndex = getInputIndex()\n\n if (Number.isNaN(newActiveIndex) || newActiveIndex < 0 || newActiveIndex >= tabs.length) {\n return false\n }\n\n workspace['x-scalar-active-tab'] = newActiveIndex\n return true\n}\n\n/**\n * Focuses the last tab in the list.\n * This provides a quick way to jump to the end, regardless of how many tabs exist.\n */\nexport const focusLastTab = (workspace: Workspace | null, _payload: TabEvents['tabs:focus:tab-last']): boolean => {\n if (!hasValidTabs(workspace)) {\n return false\n }\n\n const tabs = getUnpackedTabs(workspace)\n\n if (tabs.length <= 1) {\n return false\n }\n\n workspace['x-scalar-active-tab'] = tabs.length - 1\n return true\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,yBAAyB;AAOlC,MAAM,mBAAmB;AAMzB,MAAM,eAAe,CACnB,cAC0F;AAC1F,SAAO,cAAc,QAAQ,UAAU,eAAe,MAAM;AAC9D;AAMA,MAAM,kBAAkB,CACtB,cACkF;AAClF,SAAO,kBAAkB,UAAU,eAAe,GAAI,EAAE,OAAO,iBAAiB,CAAC;AACnF;AAMA,MAAM,iBAAiB,CAAC,cAAiC;AACvD,SAAO,UAAU,qBAAqB,KAAK;AAC7C;AAMO,MAAM,aAAa,CAAC,WAA6B,YAAiD;AACvG,MAAI,CAAC,WAAW;AACd;AAAA,EACF;AAEA,MAAI,QAAQ,eAAe,GAAG;AAC5B,cAAU,eAAe,IAAI,QAAQ,eAAe;AAAA,EACtD;AAEA,MAAI,QAAQ,qBAAqB,MAAM,QAAW;AAChD,cAAU,qBAAqB,IAAI,QAAQ,qBAAqB;AAAA,EAClE;AACF;AAMO,MAAM,SAAS,CAAC,WAA6B,aAAiD;AACnG,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gBAAgB,SAAS;AACtC,QAAM,cAAc,eAAe,SAAS;AAC5C,QAAM,aAAa,KAAK,WAAW;AAEnC,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,CAAC,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC;AAE3C,YAAU,eAAe,IAAI;AAC7B,YAAU,qBAAqB,IAAI,QAAQ,SAAS;AACpD,SAAO;AACT;AAOO,MAAM,WAAW,CAAC,WAA6B,YAAkD;AACtG,QAAM,gBAAgB,MAAc;AAClC,QAAI,WAAW,SAAS;AACtB,aAAO,QAAQ,MAAM,KAAK,WAAW,OAAO,IAAI,OAAO,SAAS,QAAQ,MAAM,KAAK,EAAE,IAAI,IAAI,OAAO;AAAA,IACtG;AACA,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gBAAgB,SAAS;AACtC,QAAM,QAAQ,cAAc;AAE5B,MAAI,KAAK,UAAU,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,YAAU,eAAe,IAAI,KAAK,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK;AAM9D,MAAI,SAAS,KAAK,SAAS,GAAG;AAC5B,cAAU,qBAAqB,IAAI,KAAK,SAAS;AAAA,EACnD;AAEA,SAAO;AACT;AAKO,MAAM,iBAAiB,CAAC,WAA6B,YAAyD;AACnH,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gBAAgB,SAAS;AAEtC,MAAI,KAAK,UAAU,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,YAAU,eAAe,IAAI,KAAK,OAAO,CAAC,GAAG,UAAU,UAAU,QAAQ,KAAK;AAE9E,YAAU,qBAAqB,IAAI;AACnC,SAAO;AACT;AAMO,MAAM,sBAAsB,CACjC,WACA,aACY;AACZ,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,eAAe,SAAS;AAE5C,MAAI,eAAe,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,YAAU,qBAAqB,IAAI,cAAc;AACjD,SAAO;AACT;AAMO,MAAM,kBAAkB,CAAC,WAA6B,aAAuD;AAClH,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gBAAgB,SAAS;AACtC,QAAM,cAAc,eAAe,SAAS;AAE5C,MAAI,eAAe,KAAK,SAAS,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,YAAU,qBAAqB,IAAI,cAAc;AACjD,SAAO;AACT;AAOO,MAAM,WAAW,CAAC,WAA6B,YAAkD;AACtG,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,MAAc;AAClC,QAAI,WAAW,SAAS;AACtB,aAAO,QAAQ,MAAM,KAAK,WAAW,OAAO,IAAI,OAAO,SAAS,QAAQ,MAAM,KAAK,EAAE,IAAI,IAAI,OAAO;AAAA,IACtG;AACA,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,OAAO,gBAAgB,SAAS;AAEtC,QAAM,iBAAiB,cAAc;AAErC,MAAI,OAAO,MAAM,cAAc,KAAK,iBAAiB,KAAK,kBAAkB,KAAK,QAAQ;AACvF,WAAO;AAAA,EACT;AAEA,YAAU,qBAAqB,IAAI;AACnC,SAAO;AACT;AAMO,MAAM,eAAe,CAAC,WAA6B,aAAwD;AAChH,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gBAAgB,SAAS;AAEtC,MAAI,KAAK,UAAU,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,YAAU,qBAAqB,IAAI,KAAK,SAAS;AACjD,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkspaceStore } from '../client.js';
|
|
2
|
+
import type { TagEvents } from '../events/definitions/tag.js';
|
|
3
|
+
/**
|
|
4
|
+
* Adds a new tag to the WorkspaceDocument's `tags` array.
|
|
5
|
+
*
|
|
6
|
+
* If the document or its tags property does not exist, the function safely no-ops or initializes `tags` as needed.
|
|
7
|
+
*
|
|
8
|
+
* @param document - The target WorkspaceDocument
|
|
9
|
+
* @param payload - The name of the tag to add
|
|
10
|
+
*/
|
|
11
|
+
export declare const createTag: (store: WorkspaceStore | null, payload: TagEvents["tag:create:tag"]) => void;
|
|
12
|
+
//# sourceMappingURL=tag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/mutators/tag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,cAAc,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,gBAAgB,CAAC,SAkB3F,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const createTag = (store, payload) => {
|
|
2
|
+
const document = store?.workspace.documents[payload.documentName];
|
|
3
|
+
if (!document) {
|
|
4
|
+
console.error("Document not found", { payload, store });
|
|
5
|
+
payload.callback?.(false);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (!document.tags) {
|
|
9
|
+
document.tags = [];
|
|
10
|
+
}
|
|
11
|
+
document.tags.push({
|
|
12
|
+
name: payload.name
|
|
13
|
+
});
|
|
14
|
+
payload.callback?.(true);
|
|
15
|
+
};
|
|
16
|
+
export {
|
|
17
|
+
createTag
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=tag.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/mutators/tag.ts"],
|
|
4
|
+
"sourcesContent": ["import type { WorkspaceStore } from '@/client'\nimport type { TagEvents } from '@/events/definitions/tag'\n\n/**\n * Adds a new tag to the WorkspaceDocument's `tags` array.\n *\n * If the document or its tags property does not exist, the function safely no-ops or initializes `tags` as needed.\n *\n * @param document - The target WorkspaceDocument\n * @param payload - The name of the tag to add\n */\nexport const createTag = (store: WorkspaceStore | null, payload: TagEvents['tag:create:tag']) => {\n const document = store?.workspace.documents[payload.documentName]\n\n if (!document) {\n console.error('Document not found', { payload, store })\n payload.callback?.(false)\n return\n }\n\n if (!document.tags) {\n document.tags = []\n }\n\n document.tags.push({\n name: payload.name,\n })\n\n payload.callback?.(true)\n}\n"],
|
|
5
|
+
"mappings": "AAWO,MAAM,YAAY,CAAC,OAA8B,YAAyC;AAC/F,QAAM,WAAW,OAAO,UAAU,UAAU,QAAQ,YAAY;AAEhE,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,sBAAsB,EAAE,SAAS,MAAM,CAAC;AACtD,YAAQ,WAAW,KAAK;AACxB;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,MAAM;AAClB,aAAS,OAAO,CAAC;AAAA,EACnB;AAEA,WAAS,KAAK,KAAK;AAAA,IACjB,MAAM,QAAQ;AAAA,EAChB,CAAC;AAED,UAAQ,WAAW,IAAI;AACzB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { WorkspaceStore } from '../../client.js';
|
|
2
|
+
import type { WorkspaceDocument } from '../../schemas.js';
|
|
3
|
+
import type { TraversedDocument, TraversedEntry, TraversedOperation, TraversedTag } from '../../schemas/navigation.js';
|
|
4
|
+
import type { OperationObject, TagObject } from '../../schemas/v3.1/strict/openapi-document.js';
|
|
5
|
+
type TraversedOrderable = TraversedDocument | TraversedTag | TraversedOperation;
|
|
6
|
+
type GetOpenapiObject<Entry extends TraversedOrderable> = Entry extends TraversedDocument ? WorkspaceDocument : Entry extends TraversedTag ? TagObject : Entry extends TraversedOperation ? OperationObject : never;
|
|
7
|
+
/** Type guard which checks if the entry has an x-scalar-order property */
|
|
8
|
+
export declare const canHaveOrder: (entry: TraversedEntry) => entry is TraversedOrderable;
|
|
9
|
+
/**
|
|
10
|
+
* Retrieves the corresponding OpenAPI object (document, tag, or operation) from the workspace store based on the provided entry.
|
|
11
|
+
*
|
|
12
|
+
* This helper abstracts the common lookup logic for working with sidebar/drag-and-drop entries and their associated OpenAPI objects.
|
|
13
|
+
* Returns `null` when the lookup cannot be completed (e.g., document/tag/operation not found).
|
|
14
|
+
*
|
|
15
|
+
* @template Entry Either TraversedDocument, TraversedTag, or TraversedOperation.
|
|
16
|
+
* @param store - The workspace store containing loaded documents.
|
|
17
|
+
* @param entry - The sidebar entry (document, tag, or operation).
|
|
18
|
+
* @returns The corresponding OpenAPI object (WorkspaceDocument, TagObject, or OperationObject) or `null` if not found.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // For a Document entry:
|
|
22
|
+
* const document = getOpenapiObject({ store, entry: documentEntry })
|
|
23
|
+
*
|
|
24
|
+
* // For a Tag entry:
|
|
25
|
+
* const tag = getOpenapiObject({ store, entry: tagEntry })
|
|
26
|
+
*
|
|
27
|
+
* // For an Operation entry:
|
|
28
|
+
* const operation = getOpenapiObject({ store, entry: operationEntry })
|
|
29
|
+
*/
|
|
30
|
+
export declare const getOpenapiObject: <Entry extends TraversedOrderable>({ store, entry, }: {
|
|
31
|
+
store: WorkspaceStore;
|
|
32
|
+
entry: Entry;
|
|
33
|
+
}) => GetOpenapiObject<Entry> | null;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=get-openapi-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-openapi-object.d.ts","sourceRoot":"","sources":["../../../src/navigation/helpers/get-openapi-object.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC/G,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAIxF,KAAK,kBAAkB,GAAG,iBAAiB,GAAG,YAAY,GAAG,kBAAkB,CAAA;AAE/E,KAAK,gBAAgB,CAAC,KAAK,SAAS,kBAAkB,IAAI,KAAK,SAAS,iBAAiB,GACrF,iBAAiB,GACjB,KAAK,SAAS,YAAY,GACxB,SAAS,GACT,KAAK,SAAS,kBAAkB,GAC9B,eAAe,GACf,KAAK,CAAA;AAEb,0EAA0E;AAC1E,eAAO,MAAM,YAAY,GAAI,OAAO,cAAc,KAAG,KAAK,IAAI,kBACmB,CAAA;AAEjF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,kBAAkB,EAAE,mBAGhE;IACD,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,KAAK,CAAA;CACb,KAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,IA2B7B,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getResolvedRef } from "../../helpers/get-resolved-ref.js";
|
|
2
|
+
import { getParentEntry } from "./get-parent-entry.js";
|
|
3
|
+
const canHaveOrder = (entry) => entry.type === "document" || entry.type === "tag" || entry.type === "operation";
|
|
4
|
+
const getOpenapiObject = ({
|
|
5
|
+
store,
|
|
6
|
+
entry
|
|
7
|
+
}) => {
|
|
8
|
+
const documentEntry = getParentEntry("document", entry);
|
|
9
|
+
if (!documentEntry) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const document = store.workspace.documents[documentEntry.name];
|
|
13
|
+
if (!document) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (entry.type === "document") {
|
|
17
|
+
return document;
|
|
18
|
+
}
|
|
19
|
+
if (entry.type === "tag") {
|
|
20
|
+
return document.tags?.find((tag) => tag.name === entry.name) ?? null;
|
|
21
|
+
}
|
|
22
|
+
if (entry.type === "operation") {
|
|
23
|
+
return getResolvedRef(document.paths?.[entry.path]?.[entry.method]) ?? null;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
canHaveOrder,
|
|
29
|
+
getOpenapiObject
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=get-openapi-object.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/navigation/helpers/get-openapi-object.ts"],
|
|
4
|
+
"sourcesContent": ["import type { WorkspaceStore } from '@/client'\nimport { getResolvedRef } from '@/helpers/get-resolved-ref'\nimport type { WorkspaceDocument } from '@/schemas'\nimport type { TraversedDocument, TraversedEntry, TraversedOperation, TraversedTag } from '@/schemas/navigation'\nimport type { OperationObject, TagObject } from '@/schemas/v3.1/strict/openapi-document'\n\nimport { getParentEntry } from './get-parent-entry'\n\ntype TraversedOrderable = TraversedDocument | TraversedTag | TraversedOperation\n\ntype GetOpenapiObject<Entry extends TraversedOrderable> = Entry extends TraversedDocument\n ? WorkspaceDocument\n : Entry extends TraversedTag\n ? TagObject\n : Entry extends TraversedOperation\n ? OperationObject\n : never\n\n/** Type guard which checks if the entry has an x-scalar-order property */\nexport const canHaveOrder = (entry: TraversedEntry): entry is TraversedOrderable =>\n entry.type === 'document' || entry.type === 'tag' || entry.type === 'operation'\n\n/**\n * Retrieves the corresponding OpenAPI object (document, tag, or operation) from the workspace store based on the provided entry.\n *\n * This helper abstracts the common lookup logic for working with sidebar/drag-and-drop entries and their associated OpenAPI objects.\n * Returns `null` when the lookup cannot be completed (e.g., document/tag/operation not found).\n *\n * @template Entry Either TraversedDocument, TraversedTag, or TraversedOperation.\n * @param store - The workspace store containing loaded documents.\n * @param entry - The sidebar entry (document, tag, or operation).\n * @returns The corresponding OpenAPI object (WorkspaceDocument, TagObject, or OperationObject) or `null` if not found.\n *\n * @example\n * // For a Document entry:\n * const document = getOpenapiObject({ store, entry: documentEntry })\n *\n * // For a Tag entry:\n * const tag = getOpenapiObject({ store, entry: tagEntry })\n *\n * // For an Operation entry:\n * const operation = getOpenapiObject({ store, entry: operationEntry })\n */\nexport const getOpenapiObject = <Entry extends TraversedOrderable>({\n store,\n entry,\n}: {\n store: WorkspaceStore\n entry: Entry\n}): GetOpenapiObject<Entry> | null => {\n const documentEntry = getParentEntry('document', entry)\n if (!documentEntry) {\n return null\n }\n\n const document = store.workspace.documents[documentEntry.name]\n if (!document) {\n return null\n }\n\n if (entry.type === 'document') {\n return document as GetOpenapiObject<Entry>\n }\n\n if (entry.type === 'tag') {\n // Find the tag by name in the document's tags array\n return (document.tags?.find((tag) => tag.name === entry.name) as GetOpenapiObject<Entry> | undefined) ?? null\n }\n\n if (entry.type === 'operation') {\n // Fetch and resolve the referenced operation object at the given path/method\n return (getResolvedRef(document.paths?.[entry.path]?.[entry.method]) as GetOpenapiObject<Entry> | undefined) ?? null\n }\n\n // If entry type is unknown, return null\n return null\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,sBAAsB;AAK/B,SAAS,sBAAsB;AAaxB,MAAM,eAAe,CAAC,UAC3B,MAAM,SAAS,cAAc,MAAM,SAAS,SAAS,MAAM,SAAS;AAuB/D,MAAM,mBAAmB,CAAmC;AAAA,EACjE;AAAA,EACA;AACF,MAGsC;AACpC,QAAM,gBAAgB,eAAe,YAAY,KAAK;AACtD,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,MAAM,UAAU,UAAU,cAAc,IAAI;AAC7D,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,YAAY;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,OAAO;AAExB,WAAQ,SAAS,MAAM,KAAK,CAAC,QAAQ,IAAI,SAAS,MAAM,IAAI,KAA6C;AAAA,EAC3G;AAEA,MAAI,MAAM,SAAS,aAAa;AAE9B,WAAQ,eAAe,SAAS,QAAQ,MAAM,IAAI,IAAI,MAAM,MAAM,CAAC,KAA6C;AAAA,EAClH;AAGA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TraversedDocument, TraversedOperation, TraversedWebhook, WithParent } from '../../schemas/navigation.js';
|
|
2
|
+
type EntriesMap = Map<string, (WithParent<TraversedOperation> | WithParent<TraversedWebhook>)[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Builds a map of all operations and webhooks in a document, indexed by path/name and method.
|
|
5
|
+
*
|
|
6
|
+
* This function recursively traverses the document structure and collects all operation and webhook
|
|
7
|
+
* entries. Multiple entries can share the same path|method key (for example, when operations are
|
|
8
|
+
* duplicated across different tags or groups).
|
|
9
|
+
*
|
|
10
|
+
* Performance note: If this function is called frequently, consider generating this map once when
|
|
11
|
+
* creating the sidebar state rather than recalculating it in mutators.
|
|
12
|
+
*
|
|
13
|
+
* @param document - The traversed OpenAPI document to extract operations from
|
|
14
|
+
* @returns A map where keys are `path|method` (for operations) or `name|method` (for webhooks),
|
|
15
|
+
* and values are arrays of matching entries. The pipe separator is used to create a
|
|
16
|
+
* unique composite key from the two parts.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const entries = getOperationEntries(document)
|
|
20
|
+
* const getUsers = entries.get('/users|get') // Array of all GET /users operations
|
|
21
|
+
*/
|
|
22
|
+
export declare const getOperationEntries: (document: TraversedDocument) => EntriesMap;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=get-operation-entries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-operation-entries.d.ts","sourceRoot":"","sources":["../../../src/navigation/helpers/get-operation-entries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACX,MAAM,sBAAsB,CAAA;AAE7B,KAAK,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAA;AAEhG;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,iBAAiB,KAAG,UA2DjE,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const getOperationEntries = (document) => {
|
|
2
|
+
const map = /* @__PURE__ */ new Map();
|
|
3
|
+
const addToMap = (key, entry) => {
|
|
4
|
+
const existing = map.get(key);
|
|
5
|
+
if (existing) {
|
|
6
|
+
existing.push(entry);
|
|
7
|
+
} else {
|
|
8
|
+
map.set(key, [entry]);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const traverse = (entries, parent) => {
|
|
12
|
+
if (!entries) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
if (entry.type === "operation") {
|
|
17
|
+
const key = `${entry.path}|${entry.method}`;
|
|
18
|
+
addToMap(key, { ...entry, parent });
|
|
19
|
+
} else if (entry.type === "webhook") {
|
|
20
|
+
const key = `${entry.name}|${entry.method}`;
|
|
21
|
+
addToMap(key, { ...entry, parent });
|
|
22
|
+
} else if ("children" in entry && entry.children) {
|
|
23
|
+
traverse(entry.children, { ...entry, parent });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
traverse(document.children, document);
|
|
28
|
+
return map;
|
|
29
|
+
};
|
|
30
|
+
export {
|
|
31
|
+
getOperationEntries
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=get-operation-entries.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/navigation/helpers/get-operation-entries.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n TraversedDocument,\n TraversedEntry,\n TraversedOperation,\n TraversedWebhook,\n WithParent,\n} from '@/schemas/navigation'\n\ntype EntriesMap = Map<string, (WithParent<TraversedOperation> | WithParent<TraversedWebhook>)[]>\n\n/**\n * Builds a map of all operations and webhooks in a document, indexed by path/name and method.\n *\n * This function recursively traverses the document structure and collects all operation and webhook\n * entries. Multiple entries can share the same path|method key (for example, when operations are\n * duplicated across different tags or groups).\n *\n * Performance note: If this function is called frequently, consider generating this map once when\n * creating the sidebar state rather than recalculating it in mutators.\n *\n * @param document - The traversed OpenAPI document to extract operations from\n * @returns A map where keys are `path|method` (for operations) or `name|method` (for webhooks),\n * and values are arrays of matching entries. The pipe separator is used to create a\n * unique composite key from the two parts.\n *\n * @example\n * const entries = getOperationEntries(document)\n * const getUsers = entries.get('/users|get') // Array of all GET /users operations\n */\nexport const getOperationEntries = (document: TraversedDocument): EntriesMap => {\n const map: EntriesMap = new Map()\n\n /**\n * Helper function to add an entry to the map under the specified key.\n * If the key already exists, appends to the array; otherwise creates a new array.\n *\n * @param key - The composite key (path|method or name|method)\n * @param entry - The operation or webhook entry to add (with parent information)\n */\n const addToMap = (key: string, entry: WithParent<TraversedOperation> | WithParent<TraversedWebhook>): void => {\n const existing = map.get(key)\n if (existing) {\n existing.push(entry)\n } else {\n map.set(key, [entry])\n }\n }\n\n /**\n * Recursively traverses the document tree to find all operations and webhooks.\n * Handles three entry types:\n * - operations: collected into the map using path|method as key\n * - webhooks: collected into the map using name|method as key\n * - containers (tags, groups): recursively traversed for their children\n *\n * @param entries - Array of entries to traverse (may be undefined for empty sections)\n * @param parent - The parent entry of the current entries (if any)\n */\n const traverse = (\n entries: TraversedEntry[] | undefined,\n parent: WithParent<TraversedEntry> | TraversedDocument,\n ): void => {\n if (!entries) {\n return\n }\n\n for (const entry of entries) {\n // Handle operations - use path and method to create unique key\n if (entry.type === 'operation') {\n const key = `${entry.path}|${entry.method}`\n addToMap(key, { ...entry, parent })\n }\n // Handle webhooks - use name and method to create unique key\n else if (entry.type === 'webhook') {\n const key = `${entry.name}|${entry.method}`\n addToMap(key, { ...entry, parent })\n }\n // Handle containers - recursively traverse children, passing current entry as parent\n else if ('children' in entry && entry.children) {\n traverse(entry.children, { ...entry, parent })\n }\n }\n }\n\n // Start traversal from document root\n traverse(document.children, document)\n\n return map\n}\n"],
|
|
5
|
+
"mappings": "AA6BO,MAAM,sBAAsB,CAAC,aAA4C;AAC9E,QAAM,MAAkB,oBAAI,IAAI;AAShC,QAAM,WAAW,CAAC,KAAa,UAA+E;AAC5G,UAAM,WAAW,IAAI,IAAI,GAAG;AAC5B,QAAI,UAAU;AACZ,eAAS,KAAK,KAAK;AAAA,IACrB,OAAO;AACL,UAAI,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,IACtB;AAAA,EACF;AAYA,QAAM,WAAW,CACf,SACA,WACS;AACT,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,eAAW,SAAS,SAAS;AAE3B,UAAI,MAAM,SAAS,aAAa;AAC9B,cAAM,MAAM,GAAG,MAAM,IAAI,IAAI,MAAM,MAAM;AACzC,iBAAS,KAAK,EAAE,GAAG,OAAO,OAAO,CAAC;AAAA,MACpC,WAES,MAAM,SAAS,WAAW;AACjC,cAAM,MAAM,GAAG,MAAM,IAAI,IAAI,MAAM,MAAM;AACzC,iBAAS,KAAK,EAAE,GAAG,OAAO,OAAO,CAAC;AAAA,MACpC,WAES,cAAc,SAAS,MAAM,UAAU;AAC9C,iBAAS,MAAM,UAAU,EAAE,GAAG,OAAO,OAAO,CAAC;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAGA,WAAS,SAAS,UAAU,QAAQ;AAEpC,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TraversedEntry } from '../../schemas/navigation.js';
|
|
2
|
+
/**
|
|
3
|
+
* Traverses up the tree to find and return the closest parent node (including self) of a specified type.
|
|
4
|
+
*
|
|
5
|
+
* @template Type - The type of node to look for.
|
|
6
|
+
* @param type - The type to match in the parent chain.
|
|
7
|
+
* @param node - The node from which traversal begins.
|
|
8
|
+
* @returns The closest parent node of the specified type, or undefined if not found.
|
|
9
|
+
*/
|
|
10
|
+
export declare const getParentEntry: <Type extends TraversedEntry["type"]>(type: Type, node?: TraversedEntry & {
|
|
11
|
+
parent?: TraversedEntry;
|
|
12
|
+
}) => (TraversedEntry & {
|
|
13
|
+
type: Type;
|
|
14
|
+
}) | undefined;
|
|
15
|
+
//# sourceMappingURL=get-parent-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-parent-entry.d.ts","sourceRoot":"","sources":["../../../src/navigation/helpers/get-parent-entry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,SAAS,cAAc,CAAC,MAAM,CAAC,EAChE,MAAM,IAAI,EACV,OAAO,cAAc,GAAG;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,KAClD,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,GAAG,SAUtC,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const getParentEntry = (type, node) => {
|
|
2
|
+
if (!node) {
|
|
3
|
+
return void 0;
|
|
4
|
+
}
|
|
5
|
+
if (node.type === type) {
|
|
6
|
+
return node;
|
|
7
|
+
}
|
|
8
|
+
return getParentEntry(type, node.parent);
|
|
9
|
+
};
|
|
10
|
+
export {
|
|
11
|
+
getParentEntry
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=get-parent-entry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/navigation/helpers/get-parent-entry.ts"],
|
|
4
|
+
"sourcesContent": ["import type { TraversedEntry } from '@/schemas/navigation'\n\n/**\n * Traverses up the tree to find and return the closest parent node (including self) of a specified type.\n *\n * @template Type - The type of node to look for.\n * @param type - The type to match in the parent chain.\n * @param node - The node from which traversal begins.\n * @returns The closest parent node of the specified type, or undefined if not found.\n */\nexport const getParentEntry = <Type extends TraversedEntry['type']>(\n type: Type,\n node?: TraversedEntry & { parent?: TraversedEntry },\n): (TraversedEntry & { type: Type }) | undefined => {\n if (!node) {\n return undefined\n }\n\n if (node.type === type) {\n return node as TraversedEntry & { type: Type }\n }\n\n return getParentEntry(type, node.parent)\n}\n"],
|
|
5
|
+
"mappings": "AAUO,MAAM,iBAAiB,CAC5B,MACA,SACkD;AAClD,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,SAAS,MAAM;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,eAAe,MAAM,KAAK,MAAM;AACzC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { TraverseSpecOptions } from '../../navigation/types.js';
|
|
2
2
|
import type { TraversedDescription } from '../../schemas/navigation.js';
|
|
3
3
|
import type { InfoObject } from '../../schemas/v3.1/strict/info.js';
|
|
4
|
-
export declare const DEFAULT_INTRODUCTION_SLUG = "introduction";
|
|
5
4
|
/**
|
|
6
5
|
* Creates a hierarchical navigation structure from markdown headings in an OpenAPI description.
|
|
7
6
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverse-description.d.ts","sourceRoot":"","sources":["../../../src/navigation/helpers/traverse-description.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"traverse-description.d.ts","sourceRoot":"","sources":["../../../src/navigation/helpers/traverse-description.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAI5D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAAI,iCAIjC;IACD,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAA;IAC7C,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,UAAU,CAAA;CACjB,KAAG,oBAAoB,EAoEvB,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/navigation/helpers/traverse-description.ts"],
|
|
4
|
-
"sourcesContent": ["import { getHeadingsFromMarkdown, getLowestHeadingLevel } from '@/navigation/helpers/utils'\nimport type { Heading, TraverseSpecOptions } from '@/navigation/types'\nimport type { TraversedDescription } from '@/schemas/navigation'\nimport type { InfoObject } from '@/schemas/v3.1/strict/info'\n\
|
|
5
|
-
"mappings": "AAAA,SAAS,yBAAyB,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import { getHeadingsFromMarkdown, getLowestHeadingLevel } from '@/navigation/helpers/utils'\nimport type { Heading, TraverseSpecOptions } from '@/navigation/types'\nimport type { TraversedDescription } from '@/schemas/navigation'\nimport type { InfoObject } from '@/schemas/v3.1/strict/info'\n\nconst DEFAULT_INTRODUCTION_SLUG = 'introduction'\n\n/**\n * Creates a hierarchical navigation structure from markdown headings in an OpenAPI description.\n *\n * The function processes markdown headings to create a two-level navigation tree:\n * - Level 1: Main sections (based on the lowest heading level found)\n * - Level 2: Subsections (one level deeper than the main sections)\n *\n * If the description starts with content rather than a heading, an \"Introduction\" section\n * is automatically added as the first entry.\n *\n * @param description - The markdown description text to process\n * @param entitiesMap - Map to store heading IDs and titles for mobile header navigation\n * @param getHeadingId - Function to generate unique IDs for headings\n * @returns Array of navigation entries with their hierarchy\n */\nexport const traverseDescription = ({\n generateId,\n parentId,\n info,\n}: {\n generateId: TraverseSpecOptions['generateId']\n parentId: string\n info: InfoObject\n}): TraversedDescription[] => {\n if (!info.description?.trim()) {\n return []\n }\n\n const headings = getHeadingsFromMarkdown(info.description)\n const lowestLevel = getLowestHeadingLevel(headings)\n\n const entries: TraversedDescription[] = []\n let currentParent: TraversedDescription | null = null\n\n // Add \"Introduction\" as the first heading\n if (info.description && !info.description.trim().startsWith('#')) {\n const heading: Heading = {\n depth: 1,\n value: 'Introduction',\n slug: DEFAULT_INTRODUCTION_SLUG,\n }\n\n const id = generateId({\n type: 'text',\n depth: heading.depth,\n slug: heading.slug,\n parentId: parentId,\n info: info,\n value: heading.value,\n })\n const title = heading.value\n\n const entry = {\n id,\n title,\n type: 'text',\n } satisfies TraversedDescription\n\n // Push to entries\n entries.push(entry)\n }\n\n // Traverse for the rest\n for (const heading of headings) {\n if (heading.depth !== lowestLevel && heading.depth !== lowestLevel + 1) {\n continue\n }\n\n const entry: TraversedDescription = {\n id: generateId({\n type: 'text',\n depth: heading.depth,\n slug: heading.slug,\n parentId: parentId,\n info: info,\n value: heading.value,\n }),\n title: heading.value,\n type: 'text',\n }\n\n if (heading.depth === lowestLevel) {\n entry.children = []\n entries.push(entry)\n currentParent = entry\n } else if (currentParent) {\n currentParent.children?.push(entry)\n }\n }\n\n return entries\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,yBAAyB,6BAA6B;AAK/D,MAAM,4BAA4B;AAiB3B,MAAM,sBAAsB,CAAC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF,MAI8B;AAC5B,MAAI,CAAC,KAAK,aAAa,KAAK,GAAG;AAC7B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,wBAAwB,KAAK,WAAW;AACzD,QAAM,cAAc,sBAAsB,QAAQ;AAElD,QAAM,UAAkC,CAAC;AACzC,MAAI,gBAA6C;AAGjD,MAAI,KAAK,eAAe,CAAC,KAAK,YAAY,KAAK,EAAE,WAAW,GAAG,GAAG;AAChE,UAAM,UAAmB;AAAA,MACvB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAEA,UAAM,KAAK,WAAW;AAAA,MACpB,MAAM;AAAA,MACN,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA,OAAO,QAAQ;AAAA,IACjB,CAAC;AACD,UAAM,QAAQ,QAAQ;AAEtB,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR;AAGA,YAAQ,KAAK,KAAK;AAAA,EACpB;AAGA,aAAW,WAAW,UAAU;AAC9B,QAAI,QAAQ,UAAU,eAAe,QAAQ,UAAU,cAAc,GAAG;AACtE;AAAA,IACF;AAEA,UAAM,QAA8B;AAAA,MAClC,IAAI,WAAW;AAAA,QACb,MAAM;AAAA,QACN,OAAO,QAAQ;AAAA,QACf,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,QACA,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,MACD,OAAO,QAAQ;AAAA,MACf,MAAM;AAAA,IACR;AAEA,QAAI,QAAQ,UAAU,aAAa;AACjC,YAAM,WAAW,CAAC;AAClB,cAAQ,KAAK,KAAK;AAClB,sBAAgB;AAAA,IAClB,WAAW,eAAe;AACxB,oBAAc,UAAU,KAAK,KAAK;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -84,8 +84,8 @@ const traverseDocument = (documentName, document, config) => {
|
|
|
84
84
|
const safeIndexB = indexB === -1 ? Number.POSITIVE_INFINITY : indexB;
|
|
85
85
|
return safeIndexA - safeIndexB;
|
|
86
86
|
});
|
|
87
|
-
document["x-scalar-order"] = unpackProxyObject(entries.map((entry) => entry.id));
|
|
88
87
|
}
|
|
88
|
+
document["x-scalar-order"] = unpackProxyObject(entries.map((entry) => entry.id));
|
|
89
89
|
return {
|
|
90
90
|
id: documentId,
|
|
91
91
|
type: "document",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/navigation/helpers/traverse-document.ts"],
|
|
4
|
-
"sourcesContent": ["import { unpackProxyObject } from '@/helpers/unpack-proxy'\nimport { getNavigationOptions } from '@/navigation/get-navigation-options'\nimport type { TagsMap } from '@/navigation/types'\nimport type { TraversedDocument, TraversedEntry } from '@/schemas/navigation'\nimport type { OpenApiDocument } from '@/schemas/v3.1/strict/openapi-document'\nimport type { DocumentConfiguration } from '@/schemas/workspace-specification/config'\n\nimport { traverseDescription } from './traverse-description'\nimport { traversePaths } from './traverse-paths'\nimport { traverseSchemas } from './traverse-schemas'\nimport { traverseTags } from './traverse-tags'\nimport { traverseWebhooks } from './traverse-webhooks'\n\n/**\n * Traverses an OpenAPI Document to generate navigation structure and metadata.\n *\n * This function processes the OpenAPI document to create:\n * - A hierarchical navigation structure for the sidebar\n * - A mapping of IDs to titles for mobile header navigation\n * - Tag-based organization of operations and webhooks\n * - Optional schema/model documentation\n */\nexport const traverseDocument = (documentName: string, document: OpenApiDocument, config?: DocumentConfiguration) => {\n const { hideModels, tagsSorter, operationsSorter, generateId } = getNavigationOptions(documentName, config)\n\n const documentId = generateId({\n type: 'document',\n info: document.info,\n name: documentName,\n })\n\n /** Map of tags and their entries */\n const tagsMap: TagsMap = new Map(\n document.tags?.map((tag) => [\n tag.name ?? 'Untitled Tag',\n { id: generateId({ type: 'tag', tag, parentId: documentId }), parentId: documentId, tag, entries: [] },\n ]) ?? [],\n )\n\n /** Generate entries for the document info description field */\n const entries: TraversedEntry[] = traverseDescription({\n generateId,\n parentId: documentId,\n info: document.info,\n })\n\n /** Traverse all the document path */\n const { untaggedOperations } = traversePaths({ document, tagsMap, generateId, documentId })\n\n const untaggedWebhooksParentId = generateId({\n type: 'webhook',\n name: '',\n parentId: documentId,\n })\n\n const untaggedWebhooks = traverseWebhooks({\n document,\n generateId,\n tagsMap,\n untaggedWebhooksParentId,\n documentId,\n })\n\n const tagsEntries = traverseTags({\n document,\n tagsMap,\n documentId,\n options: { tagsSorter, operationsSorter, generateId },\n })\n\n // Add tagged operations, webhooks and tagGroups\n entries.push(...tagsEntries)\n // Add untagged operations\n entries.push(...untaggedOperations)\n\n // Add untagged webhooks\n if (untaggedWebhooks.length) {\n entries.push({\n type: 'tag',\n id: untaggedWebhooksParentId,\n title: 'Webhooks',\n name: 'Webhooks',\n children: untaggedWebhooks,\n isGroup: false,\n isWebhooks: true,\n })\n }\n\n // Add models if they are not hidden\n if (!hideModels && document.components?.schemas) {\n const untaggedModels = traverseSchemas({\n documentId,\n document,\n generateId,\n tagsMap,\n })\n\n if (untaggedModels.length) {\n entries.push({\n type: 'models',\n id: generateId({\n type: 'model',\n parentId: documentId,\n }),\n title: 'Models',\n name: 'Models',\n children: untaggedModels,\n })\n }\n }\n\n const sortOrder = document['x-scalar-order']\n\n // Try to sort the entries using the x-scalar-order\n if (sortOrder) {\n entries.sort((a, b) => {\n const indexA = sortOrder.indexOf(a.id)\n const indexB = sortOrder.indexOf(b.id)\n // If an id is not found, treat it as \"infinity\" so those items go last.\n const safeIndexA = indexA === -1 ? Number.POSITIVE_INFINITY : indexA\n const safeIndexB = indexB === -1 ? Number.POSITIVE_INFINITY : indexB\n return safeIndexA - safeIndexB\n })\n\n
|
|
5
|
-
"mappings": "AAAA,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AAMrC,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAW1B,MAAM,mBAAmB,CAAC,cAAsB,UAA2B,WAAmC;AACnH,QAAM,EAAE,YAAY,YAAY,kBAAkB,WAAW,IAAI,qBAAqB,cAAc,MAAM;AAE1G,QAAM,aAAa,WAAW;AAAA,IAC5B,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,MAAM;AAAA,EACR,CAAC;AAGD,QAAM,UAAmB,IAAI;AAAA,IAC3B,SAAS,MAAM,IAAI,CAAC,QAAQ;AAAA,MAC1B,IAAI,QAAQ;AAAA,MACZ,EAAE,IAAI,WAAW,EAAE,MAAM,OAAO,KAAK,UAAU,WAAW,CAAC,GAAG,UAAU,YAAY,KAAK,SAAS,CAAC,EAAE;AAAA,IACvG,CAAC,KAAK,CAAC;AAAA,EACT;AAGA,QAAM,UAA4B,oBAAoB;AAAA,IACpD;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAS;AAAA,EACjB,CAAC;AAGD,QAAM,EAAE,mBAAmB,IAAI,cAAc,EAAE,UAAU,SAAS,YAAY,WAAW,CAAC;AAE1F,QAAM,2BAA2B,WAAW;AAAA,IAC1C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,mBAAmB,iBAAiB;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,cAAc,aAAa;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,EAAE,YAAY,kBAAkB,WAAW;AAAA,EACtD,CAAC;AAGD,UAAQ,KAAK,GAAG,WAAW;AAE3B,UAAQ,KAAK,GAAG,kBAAkB;AAGlC,MAAI,iBAAiB,QAAQ;AAC3B,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,cAAc,SAAS,YAAY,SAAS;AAC/C,UAAM,iBAAiB,gBAAgB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,eAAe,QAAQ;AACzB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,IAAI,WAAW;AAAA,UACb,MAAM;AAAA,UACN,UAAU;AAAA,QACZ,CAAC;AAAA,QACD,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,SAAS,gBAAgB;AAG3C,MAAI,WAAW;AACb,YAAQ,KAAK,CAAC,GAAG,MAAM;AACrB,YAAM,SAAS,UAAU,QAAQ,EAAE,EAAE;AACrC,YAAM,SAAS,UAAU,QAAQ,EAAE,EAAE;AAErC,YAAM,aAAa,WAAW,KAAK,OAAO,oBAAoB;AAC9D,YAAM,aAAa,WAAW,KAAK,OAAO,oBAAoB;AAC9D,aAAO,aAAa;AAAA,IACtB,CAAC;
|
|
4
|
+
"sourcesContent": ["import { unpackProxyObject } from '@/helpers/unpack-proxy'\nimport { getNavigationOptions } from '@/navigation/get-navigation-options'\nimport type { TagsMap } from '@/navigation/types'\nimport type { TraversedDocument, TraversedEntry } from '@/schemas/navigation'\nimport type { OpenApiDocument } from '@/schemas/v3.1/strict/openapi-document'\nimport type { DocumentConfiguration } from '@/schemas/workspace-specification/config'\n\nimport { traverseDescription } from './traverse-description'\nimport { traversePaths } from './traverse-paths'\nimport { traverseSchemas } from './traverse-schemas'\nimport { traverseTags } from './traverse-tags'\nimport { traverseWebhooks } from './traverse-webhooks'\n\n/**\n * Traverses an OpenAPI Document to generate navigation structure and metadata.\n *\n * This function processes the OpenAPI document to create:\n * - A hierarchical navigation structure for the sidebar\n * - A mapping of IDs to titles for mobile header navigation\n * - Tag-based organization of operations and webhooks\n * - Optional schema/model documentation\n */\nexport const traverseDocument = (documentName: string, document: OpenApiDocument, config?: DocumentConfiguration) => {\n const { hideModels, tagsSorter, operationsSorter, generateId } = getNavigationOptions(documentName, config)\n\n const documentId = generateId({\n type: 'document',\n info: document.info,\n name: documentName,\n })\n\n /** Map of tags and their entries */\n const tagsMap: TagsMap = new Map(\n document.tags?.map((tag) => [\n tag.name ?? 'Untitled Tag',\n { id: generateId({ type: 'tag', tag, parentId: documentId }), parentId: documentId, tag, entries: [] },\n ]) ?? [],\n )\n\n /** Generate entries for the document info description field */\n const entries: TraversedEntry[] = traverseDescription({\n generateId,\n parentId: documentId,\n info: document.info,\n })\n\n /** Traverse all the document path */\n const { untaggedOperations } = traversePaths({ document, tagsMap, generateId, documentId })\n\n const untaggedWebhooksParentId = generateId({\n type: 'webhook',\n name: '',\n parentId: documentId,\n })\n\n const untaggedWebhooks = traverseWebhooks({\n document,\n generateId,\n tagsMap,\n untaggedWebhooksParentId,\n documentId,\n })\n\n const tagsEntries = traverseTags({\n document,\n tagsMap,\n documentId,\n options: { tagsSorter, operationsSorter, generateId },\n })\n\n // Add tagged operations, webhooks and tagGroups\n entries.push(...tagsEntries)\n // Add untagged operations\n entries.push(...untaggedOperations)\n\n // Add untagged webhooks\n if (untaggedWebhooks.length) {\n entries.push({\n type: 'tag',\n id: untaggedWebhooksParentId,\n title: 'Webhooks',\n name: 'Webhooks',\n children: untaggedWebhooks,\n isGroup: false,\n isWebhooks: true,\n })\n }\n\n // Add models if they are not hidden\n if (!hideModels && document.components?.schemas) {\n const untaggedModels = traverseSchemas({\n documentId,\n document,\n generateId,\n tagsMap,\n })\n\n if (untaggedModels.length) {\n entries.push({\n type: 'models',\n id: generateId({\n type: 'model',\n parentId: documentId,\n }),\n title: 'Models',\n name: 'Models',\n children: untaggedModels,\n })\n }\n }\n\n const sortOrder = document['x-scalar-order']\n\n // Try to sort the entries using the x-scalar-order\n if (sortOrder) {\n entries.sort((a, b) => {\n const indexA = sortOrder.indexOf(a.id)\n const indexB = sortOrder.indexOf(b.id)\n // If an id is not found, treat it as \"infinity\" so those items go last.\n const safeIndexA = indexA === -1 ? Number.POSITIVE_INFINITY : indexA\n const safeIndexB = indexB === -1 ? Number.POSITIVE_INFINITY : indexB\n return safeIndexA - safeIndexB\n })\n }\n\n // Now update the sort order of the entries\n document['x-scalar-order'] = unpackProxyObject(entries.map((entry) => entry.id))\n\n return {\n id: documentId,\n type: 'document',\n title: document.info.title,\n name: documentName,\n children: entries,\n icon: document['x-scalar-icon'],\n } satisfies TraversedDocument\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AAMrC,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAW1B,MAAM,mBAAmB,CAAC,cAAsB,UAA2B,WAAmC;AACnH,QAAM,EAAE,YAAY,YAAY,kBAAkB,WAAW,IAAI,qBAAqB,cAAc,MAAM;AAE1G,QAAM,aAAa,WAAW;AAAA,IAC5B,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,MAAM;AAAA,EACR,CAAC;AAGD,QAAM,UAAmB,IAAI;AAAA,IAC3B,SAAS,MAAM,IAAI,CAAC,QAAQ;AAAA,MAC1B,IAAI,QAAQ;AAAA,MACZ,EAAE,IAAI,WAAW,EAAE,MAAM,OAAO,KAAK,UAAU,WAAW,CAAC,GAAG,UAAU,YAAY,KAAK,SAAS,CAAC,EAAE;AAAA,IACvG,CAAC,KAAK,CAAC;AAAA,EACT;AAGA,QAAM,UAA4B,oBAAoB;AAAA,IACpD;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAS;AAAA,EACjB,CAAC;AAGD,QAAM,EAAE,mBAAmB,IAAI,cAAc,EAAE,UAAU,SAAS,YAAY,WAAW,CAAC;AAE1F,QAAM,2BAA2B,WAAW;AAAA,IAC1C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,mBAAmB,iBAAiB;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,cAAc,aAAa;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,EAAE,YAAY,kBAAkB,WAAW;AAAA,EACtD,CAAC;AAGD,UAAQ,KAAK,GAAG,WAAW;AAE3B,UAAQ,KAAK,GAAG,kBAAkB;AAGlC,MAAI,iBAAiB,QAAQ;AAC3B,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,cAAc,SAAS,YAAY,SAAS;AAC/C,UAAM,iBAAiB,gBAAgB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,eAAe,QAAQ;AACzB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,IAAI,WAAW;AAAA,UACb,MAAM;AAAA,UACN,UAAU;AAAA,QACZ,CAAC;AAAA,QACD,OAAO;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,SAAS,gBAAgB;AAG3C,MAAI,WAAW;AACb,YAAQ,KAAK,CAAC,GAAG,MAAM;AACrB,YAAM,SAAS,UAAU,QAAQ,EAAE,EAAE;AACrC,YAAM,SAAS,UAAU,QAAQ,EAAE,EAAE;AAErC,YAAM,aAAa,WAAW,KAAK,OAAO,oBAAoB;AAC9D,YAAM,aAAa,WAAW,KAAK,OAAO,oBAAoB;AAC9D,aAAO,aAAa;AAAA,IACtB,CAAC;AAAA,EACH;AAGA,WAAS,gBAAgB,IAAI,kBAAkB,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AAE/E,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO,SAAS,KAAK;AAAA,IACrB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAM,SAAS,eAAe;AAAA,EAChC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,7 @@ import { objectKeys } from "@scalar/helpers/object/object-keys";
|
|
|
3
3
|
import { escapeJsonPointer } from "@scalar/json-magic/helpers/escape-json-pointer";
|
|
4
4
|
import { getResolvedRef } from "../../helpers/get-resolved-ref.js";
|
|
5
5
|
import { traverseOperationExamples } from "../../navigation/helpers/traverse-examples.js";
|
|
6
|
-
import { XScalarStabilityValues } from "../../schemas/extensions/operation/
|
|
6
|
+
import { XScalarStabilityValues } from "../../schemas/extensions/operation/index.js";
|
|
7
7
|
import { getTag } from "./get-tag.js";
|
|
8
8
|
const isDeprecatedOperation = (operation) => {
|
|
9
9
|
return operation.deprecated || operation["x-scalar-stability"] === XScalarStabilityValues.Deprecated;
|