@scalar/api-client 3.3.1 → 3.4.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.
Files changed (185) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/monacoeditorwork/yaml.worker.bundle.js +92 -79
  3. package/dist/style.css +87 -57
  4. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
  5. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  6. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  7. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +5 -0
  8. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  9. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +4 -0
  10. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
  11. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  12. package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
  13. package/dist/v2/blocks/operation-block/components/Header.vue.script.js +6 -0
  14. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  15. package/dist/v2/blocks/operation-block/helpers/response-cache.d.ts +2 -1
  16. package/dist/v2/blocks/operation-block/helpers/response-cache.d.ts.map +1 -1
  17. package/dist/v2/blocks/operation-block/helpers/response-cache.js +9 -2
  18. package/dist/v2/blocks/operation-block/helpers/response-cache.js.map +1 -1
  19. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  20. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +2 -2
  21. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +2 -2
  22. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +4 -0
  23. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  24. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  25. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  26. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +84 -71
  27. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  28. package/dist/v2/blocks/scalar-address-bar-block/helpers/is-placeholder-path.d.ts +13 -0
  29. package/dist/v2/blocks/scalar-address-bar-block/helpers/is-placeholder-path.d.ts.map +1 -0
  30. package/dist/v2/blocks/scalar-address-bar-block/helpers/is-placeholder-path.js +28 -0
  31. package/dist/v2/blocks/scalar-address-bar-block/helpers/is-placeholder-path.js.map +1 -0
  32. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.d.ts +16 -0
  33. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.d.ts.map +1 -0
  34. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.js +28 -0
  35. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.js.map +1 -0
  36. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-path-masking.d.ts +31 -0
  37. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-path-masking.d.ts.map +1 -0
  38. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-path-masking.js +18 -0
  39. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-path-masking.js.map +1 -0
  40. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  41. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  42. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  43. package/dist/v2/components/code-input/CodeInput.vue.script.js +1 -1
  44. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  45. package/dist/v2/constants.js +1 -1
  46. package/dist/v2/features/app/App.vue.d.ts +25 -1
  47. package/dist/v2/features/app/App.vue.d.ts.map +1 -1
  48. package/dist/v2/features/app/App.vue.js.map +1 -1
  49. package/dist/v2/features/app/App.vue.script.js +54 -39
  50. package/dist/v2/features/app/App.vue.script.js.map +1 -1
  51. package/dist/v2/features/app/app-events.js +4 -4
  52. package/dist/v2/features/app/app-events.js.map +1 -1
  53. package/dist/v2/features/app/app-state.d.ts +20 -14
  54. package/dist/v2/features/app/app-state.d.ts.map +1 -1
  55. package/dist/v2/features/app/app-state.js +89 -55
  56. package/dist/v2/features/app/app-state.js.map +1 -1
  57. package/dist/v2/features/app/components/AppHeader.vue.d.ts +26 -3
  58. package/dist/v2/features/app/components/AppHeader.vue.d.ts.map +1 -1
  59. package/dist/v2/features/app/components/AppHeader.vue.js.map +1 -1
  60. package/dist/v2/features/app/components/AppHeader.vue.script.js +15 -6
  61. package/dist/v2/features/app/components/AppHeader.vue.script.js.map +1 -1
  62. package/dist/v2/features/app/components/AppSidebar.vue.d.ts +2 -2
  63. package/dist/v2/features/app/components/AppSidebar.vue.d.ts.map +1 -1
  64. package/dist/v2/features/app/components/AppSidebar.vue.js +1 -1
  65. package/dist/v2/features/app/components/AppSidebar.vue.js.map +1 -1
  66. package/dist/v2/features/app/components/AppSidebar.vue.script.js +86 -108
  67. package/dist/v2/features/app/components/AppSidebar.vue.script.js.map +1 -1
  68. package/dist/v2/features/app/components/CreateVersionModal.vue.d.ts +28 -0
  69. package/dist/v2/features/app/components/CreateVersionModal.vue.d.ts.map +1 -0
  70. package/dist/v2/features/app/components/CreateVersionModal.vue.js +7 -0
  71. package/dist/v2/features/app/components/CreateVersionModal.vue.js.map +1 -0
  72. package/dist/v2/features/app/components/CreateVersionModal.vue.script.js +84 -0
  73. package/dist/v2/features/app/components/CreateVersionModal.vue.script.js.map +1 -0
  74. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.d.ts +26 -0
  75. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.d.ts.map +1 -0
  76. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.js +9 -0
  77. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.js.map +1 -0
  78. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.script.js +376 -0
  79. package/dist/v2/features/app/components/DocumentBreadcrumb.vue.script.js.map +1 -0
  80. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.d.ts +16 -0
  81. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.d.ts.map +1 -0
  82. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.js +7 -0
  83. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.js.map +1 -0
  84. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.script.js +51 -0
  85. package/dist/v2/features/app/components/DocumentSyncIndicator.vue.script.js.map +1 -0
  86. package/dist/v2/features/app/components/SidebarDocument.vue.d.ts +45 -0
  87. package/dist/v2/features/app/components/SidebarDocument.vue.d.ts.map +1 -0
  88. package/dist/v2/features/app/components/SidebarDocument.vue.js +7 -0
  89. package/dist/v2/features/app/components/SidebarDocument.vue.js.map +1 -0
  90. package/dist/v2/features/app/components/SidebarDocument.vue.script.js +137 -0
  91. package/dist/v2/features/app/components/SidebarDocument.vue.script.js.map +1 -0
  92. package/dist/v2/features/app/helpers/check-version-conflict.d.ts +51 -0
  93. package/dist/v2/features/app/helpers/check-version-conflict.d.ts.map +1 -0
  94. package/dist/v2/features/app/helpers/check-version-conflict.js +79 -0
  95. package/dist/v2/features/app/helpers/check-version-conflict.js.map +1 -0
  96. package/dist/v2/features/app/helpers/compute-version-status.d.ts +45 -0
  97. package/dist/v2/features/app/helpers/compute-version-status.d.ts.map +1 -0
  98. package/dist/v2/features/app/helpers/compute-version-status.js +18 -0
  99. package/dist/v2/features/app/helpers/compute-version-status.js.map +1 -0
  100. package/dist/v2/features/app/helpers/create-draft-registry-document.d.ts +39 -0
  101. package/dist/v2/features/app/helpers/create-draft-registry-document.d.ts.map +1 -0
  102. package/dist/v2/features/app/helpers/create-draft-registry-document.js +64 -0
  103. package/dist/v2/features/app/helpers/create-draft-registry-document.js.map +1 -0
  104. package/dist/v2/features/app/helpers/create-temp-operation.d.ts.map +1 -1
  105. package/dist/v2/features/app/helpers/create-temp-operation.js +5 -8
  106. package/dist/v2/features/app/helpers/create-temp-operation.js.map +1 -1
  107. package/dist/v2/features/app/helpers/detect-document-conflicts.d.ts +26 -0
  108. package/dist/v2/features/app/helpers/detect-document-conflicts.d.ts.map +1 -0
  109. package/dist/v2/features/app/helpers/detect-document-conflicts.js +27 -0
  110. package/dist/v2/features/app/helpers/detect-document-conflicts.js.map +1 -0
  111. package/dist/v2/features/app/helpers/filter-workspaces.d.ts +14 -14
  112. package/dist/v2/features/app/helpers/filter-workspaces.d.ts.map +1 -1
  113. package/dist/v2/features/app/helpers/filter-workspaces.js +15 -15
  114. package/dist/v2/features/app/helpers/filter-workspaces.js.map +1 -1
  115. package/dist/v2/features/app/helpers/group-workspaces.d.ts +23 -3
  116. package/dist/v2/features/app/helpers/group-workspaces.d.ts.map +1 -1
  117. package/dist/v2/features/app/helpers/group-workspaces.js +22 -7
  118. package/dist/v2/features/app/helpers/group-workspaces.js.map +1 -1
  119. package/dist/v2/features/app/helpers/load-registry-document.d.ts +16 -1
  120. package/dist/v2/features/app/helpers/load-registry-document.d.ts.map +1 -1
  121. package/dist/v2/features/app/helpers/load-registry-document.js +7 -6
  122. package/dist/v2/features/app/helpers/load-registry-document.js.map +1 -1
  123. package/dist/v2/features/app/helpers/routes.d.ts +5 -1
  124. package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
  125. package/dist/v2/features/app/helpers/routes.js +1 -1
  126. package/dist/v2/features/app/helpers/routes.js.map +1 -1
  127. package/dist/v2/features/app/helpers/version-status-presentation.d.ts +24 -0
  128. package/dist/v2/features/app/helpers/version-status-presentation.d.ts.map +1 -0
  129. package/dist/v2/features/app/helpers/version-status-presentation.js +43 -0
  130. package/dist/v2/features/app/helpers/version-status-presentation.js.map +1 -0
  131. package/dist/v2/features/app/hooks/use-active-document-version.d.ts +41 -0
  132. package/dist/v2/features/app/hooks/use-active-document-version.d.ts.map +1 -0
  133. package/dist/v2/features/app/hooks/use-active-document-version.js +60 -0
  134. package/dist/v2/features/app/hooks/use-active-document-version.js.map +1 -0
  135. package/dist/v2/features/app/hooks/use-sidebar-documents.d.ts +71 -23
  136. package/dist/v2/features/app/hooks/use-sidebar-documents.d.ts.map +1 -1
  137. package/dist/v2/features/app/hooks/use-sidebar-documents.js +167 -45
  138. package/dist/v2/features/app/hooks/use-sidebar-documents.js.map +1 -1
  139. package/dist/v2/features/app/hooks/use-version-conflict-check.d.ts +35 -0
  140. package/dist/v2/features/app/hooks/use-version-conflict-check.d.ts.map +1 -0
  141. package/dist/v2/features/app/hooks/use-version-conflict-check.js +62 -0
  142. package/dist/v2/features/app/hooks/use-version-conflict-check.js.map +1 -0
  143. package/dist/v2/features/collection/DocumentCollection.vue.d.ts.map +1 -1
  144. package/dist/v2/features/collection/DocumentCollection.vue.js.map +1 -1
  145. package/dist/v2/features/collection/DocumentCollection.vue.script.js +6 -1
  146. package/dist/v2/features/collection/DocumentCollection.vue.script.js.map +1 -1
  147. package/dist/v2/features/collection/OperationCollection.vue.script.js +1 -0
  148. package/dist/v2/features/collection/OperationCollection.vue.script.js.map +1 -1
  149. package/dist/v2/features/collection/WorkspaceCollection.vue.script.js +1 -0
  150. package/dist/v2/features/collection/WorkspaceCollection.vue.script.js.map +1 -1
  151. package/dist/v2/features/collection/components/Authentication.vue.script.js +1 -0
  152. package/dist/v2/features/collection/components/Authentication.vue.script.js.map +1 -1
  153. package/dist/v2/features/collection/components/Cookies.vue.script.js +1 -0
  154. package/dist/v2/features/collection/components/Cookies.vue.script.js.map +1 -1
  155. package/dist/v2/features/collection/components/Editor/Editor.vue.script.js +1 -0
  156. package/dist/v2/features/collection/components/Editor/Editor.vue.script.js.map +1 -1
  157. package/dist/v2/features/collection/components/Environment.vue.script.js +1 -0
  158. package/dist/v2/features/collection/components/Environment.vue.script.js.map +1 -1
  159. package/dist/v2/features/collection/components/GetStarted.vue.d.ts +12 -4
  160. package/dist/v2/features/collection/components/GetStarted.vue.d.ts.map +1 -1
  161. package/dist/v2/features/collection/components/GetStarted.vue.js.map +1 -1
  162. package/dist/v2/features/collection/components/GetStarted.vue.script.js +56 -13
  163. package/dist/v2/features/collection/components/GetStarted.vue.script.js.map +1 -1
  164. package/dist/v2/features/collection/components/Overview.vue.script.js +1 -0
  165. package/dist/v2/features/collection/components/Overview.vue.script.js.map +1 -1
  166. package/dist/v2/features/collection/components/Runner/components/Runner.vue.script.js +1 -0
  167. package/dist/v2/features/collection/components/Runner/components/Runner.vue.script.js.map +1 -1
  168. package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.js +2 -2
  169. package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.js.map +1 -1
  170. package/dist/v2/features/collection/components/Scripts.vue.script.js +1 -0
  171. package/dist/v2/features/collection/components/Scripts.vue.script.js.map +1 -1
  172. package/dist/v2/features/collection/components/Servers.vue.script.js +1 -0
  173. package/dist/v2/features/collection/components/Servers.vue.script.js.map +1 -1
  174. package/dist/v2/features/collection/components/Settings.vue.script.js +1 -0
  175. package/dist/v2/features/collection/components/Settings.vue.script.js.map +1 -1
  176. package/dist/v2/features/editor/hooks/use-three-way-merge-editor.js +1 -1
  177. package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
  178. package/dist/v2/features/operation/Operation.vue.js.map +1 -1
  179. package/dist/v2/features/operation/Operation.vue.script.js +3 -0
  180. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  181. package/dist/v2/helpers/safe-run.d.ts +25 -1
  182. package/dist/v2/helpers/safe-run.d.ts.map +1 -1
  183. package/dist/v2/helpers/safe-run.js +26 -2
  184. package/dist/v2/helpers/safe-run.js.map +1 -1
  185. package/package.json +12 -11
@@ -0,0 +1,137 @@
1
+ import { Fragment, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, openBlock, renderList, toDisplayString, unref, withCtx, withKeys, withModifiers } from "vue";
2
+ import { ScalarIconButton, ScalarSidebarButton, ScalarSidebarItem, ScalarSidebarNestedItems } from "@scalar/components";
3
+ import { ScalarIconCaretLeft, ScalarIconDotsThree, ScalarIconGearSix, ScalarIconMagnifyingGlass, ScalarIconPlus } from "@scalar/icons";
4
+ import { SidebarItem, filterItems } from "@scalar/sidebar";
5
+ //#region src/v2/features/app/components/SidebarDocument.vue?vue&type=script&setup=true&lang.ts
6
+ var _hoisted_1 = { class: "flex items-center gap-1" };
7
+ var _hoisted_2 = {
8
+ key: 1,
9
+ class: "text-c-3 px-3 py-1 text-xs"
10
+ };
11
+ var SidebarDocument_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
12
+ __name: "SidebarDocument",
13
+ props: {
14
+ item: {},
15
+ active: { type: Boolean },
16
+ open: { type: Boolean },
17
+ loading: { type: Boolean },
18
+ isDroppable: { type: Function },
19
+ isExpanded: { type: Function },
20
+ isSelected: { type: Function }
21
+ },
22
+ emits: [
23
+ "back",
24
+ "click",
25
+ "openSettings",
26
+ "search",
27
+ "createOperation",
28
+ "addEmptyFolder",
29
+ "openMenu",
30
+ "selectItem",
31
+ "toggleGroup",
32
+ "dragEnd"
33
+ ],
34
+ setup(__props, { emit: __emit }) {
35
+ const emit = __emit;
36
+ const handleDragEnd = (draggingItem, hoveredItem) => emit("dragEnd", draggingItem, hoveredItem);
37
+ return (_ctx, _cache) => {
38
+ return openBlock(), createBlock(unref(ScalarSidebarNestedItems), {
39
+ active: __props.active,
40
+ controlled: "",
41
+ open: __props.open,
42
+ onBack: _cache[6] || (_cache[6] = ($event) => emit("back")),
43
+ onClick: _cache[7] || (_cache[7] = ($event) => emit("click", __props.item))
44
+ }, createSlots({
45
+ back: withCtx(() => [createElementVNode("div", _hoisted_1, [
46
+ createVNode(unref(ScalarSidebarButton), {
47
+ is: "button",
48
+ class: "text-sidebar-c-1 font-sidebar-active hover:text-sidebar-c-1 flex-1",
49
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("back"))
50
+ }, {
51
+ icon: withCtx(() => [createVNode(unref(ScalarIconCaretLeft), { class: "text-sidebar-c-2 -m-px size-4" })]),
52
+ default: withCtx(() => [_cache[9] || (_cache[9] = createTextVNode(" Back ", -1))]),
53
+ _: 1
54
+ }),
55
+ createVNode(unref(ScalarIconButton), {
56
+ icon: unref(ScalarIconGearSix),
57
+ label: "Collection settings",
58
+ size: "sm",
59
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("openSettings"))
60
+ }, null, 8, ["icon"]),
61
+ createVNode(unref(ScalarIconButton), {
62
+ icon: unref(ScalarIconMagnifyingGlass),
63
+ label: "Search collection",
64
+ size: "sm",
65
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("search"))
66
+ }, null, 8, ["icon"]),
67
+ createVNode(unref(ScalarIconButton), {
68
+ class: "rounded-full border",
69
+ icon: unref(ScalarIconPlus),
70
+ label: "Add operation",
71
+ size: "sm",
72
+ onClick: _cache[3] || (_cache[3] = ($event) => emit("createOperation", __props.item))
73
+ }, null, 8, ["icon"])
74
+ ])]),
75
+ items: withCtx(() => [__props.item.navigation?.children?.length ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(filterItems)("client", __props.item.navigation.children), (child) => {
76
+ return openBlock(), createBlock(unref(SidebarItem), {
77
+ key: child.id,
78
+ isDroppable: __props.isDroppable,
79
+ isExpanded: __props.isExpanded,
80
+ isSelected: __props.isSelected,
81
+ item: child,
82
+ layout: "client",
83
+ onOnDragEnd: handleDragEnd,
84
+ onSelectItem: _cache[4] || (_cache[4] = (id) => emit("selectItem", id)),
85
+ onToggleGroup: _cache[5] || (_cache[5] = (id) => emit("toggleGroup", id))
86
+ }, {
87
+ decorator: withCtx(({ item: entry }) => [createVNode(unref(ScalarIconButton), {
88
+ "aria-expanded": "false",
89
+ "aria-haspopup": "menu",
90
+ class: "bg-b-2",
91
+ icon: unref(ScalarIconDotsThree),
92
+ label: "More options",
93
+ size: "sm",
94
+ variant: "ghost",
95
+ weight: "bold",
96
+ onClick: withModifiers((e) => emit("openMenu", e, entry), ["stop"]),
97
+ onKeydown: [
98
+ withKeys(withModifiers((e) => emit("openMenu", e, entry), ["stop"]), ["down"]),
99
+ withKeys(withModifiers((e) => emit("openMenu", e, entry), ["stop"]), ["enter"]),
100
+ withKeys(withModifiers((e) => emit("openMenu", e, entry), ["stop"]), ["space"]),
101
+ withKeys(withModifiers((e) => emit("openMenu", e, entry), ["stop"]), ["up"])
102
+ ]
103
+ }, null, 8, [
104
+ "icon",
105
+ "onClick",
106
+ "onKeydown"
107
+ ])]),
108
+ empty: withCtx(({ item: emptyItem }) => [createVNode(unref(ScalarSidebarItem), {
109
+ is: "button",
110
+ onClick: ($event) => emit("addEmptyFolder", emptyItem)
111
+ }, {
112
+ icon: withCtx(() => [createVNode(unref(ScalarIconPlus))]),
113
+ default: withCtx(() => [..._cache[10] || (_cache[10] = [createTextVNode("Add operation", -1)])]),
114
+ _: 1
115
+ }, 8, ["onClick"])]),
116
+ _: 1
117
+ }, 8, [
118
+ "isDroppable",
119
+ "isExpanded",
120
+ "isSelected",
121
+ "item"
122
+ ]);
123
+ }), 128)) : (openBlock(), createElementBlock("li", _hoisted_2, " Empty document "))]),
124
+ default: withCtx(() => [createElementVNode("span", null, toDisplayString(__props.item.title), 1)]),
125
+ _: 2
126
+ }, [__props.loading ? {
127
+ name: "aside",
128
+ fn: withCtx(() => [_cache[8] || (_cache[8] = createElementVNode("span", { class: "text-c-3 text-xs" }, "Loading…", -1))]),
129
+ key: "0"
130
+ } : void 0]), 1032, ["active", "open"]);
131
+ };
132
+ }
133
+ });
134
+ //#endregion
135
+ export { SidebarDocument_vue_vue_type_script_setup_true_lang_default as default };
136
+
137
+ //# sourceMappingURL=SidebarDocument.vue.script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SidebarDocument.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/SidebarDocument.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarIconButton,\n ScalarSidebarButton,\n ScalarSidebarItem,\n ScalarSidebarNestedItems,\n} from '@scalar/components'\nimport {\n ScalarIconCaretLeft,\n ScalarIconDotsThree,\n ScalarIconGearSix,\n ScalarIconMagnifyingGlass,\n ScalarIconPlus,\n} from '@scalar/icons'\nimport {\n filterItems,\n SidebarItem,\n type DraggingItem,\n type HoveredItem,\n} from '@scalar/sidebar'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\n\nimport type { SidebarDocumentItem } from '@/v2/features/app/hooks/use-sidebar-documents'\n\nconst { item, active, open, loading } = defineProps<{\n /** The document row to render. */\n item: SidebarDocumentItem\n /** Whether the document row is the currently active sidebar entry. */\n active: boolean\n /** Whether the document is drilled-in (its children are shown). */\n open: boolean\n /** Whether the document is currently being fetched from the registry. */\n loading?: boolean\n /** Predicate to check whether a child entry can be dropped on a target. */\n isDroppable: (draggingItem: DraggingItem, hoveredItem: HoveredItem) => boolean\n /** Predicate to check whether a child entry is currently expanded. */\n isExpanded: (id: string) => boolean\n /** Predicate to check whether a child entry is currently selected. */\n isSelected: (id: string) => boolean\n}>()\n\nconst emit = defineEmits<{\n /** Navigate back from the drilled-in document view. */\n (event: 'back'): void\n /** The document row was clicked. */\n (event: 'click', item: SidebarDocumentItem): void\n /** Open the document (collection) settings. */\n (event: 'openSettings'): void\n /** Open the per-document search modal. */\n (event: 'search'): void\n /** Create a new operation in this document. */\n (event: 'createOperation', item: SidebarDocumentItem): void\n /** Add an operation inside an empty tag/folder. */\n (event: 'addEmptyFolder', item: TraversedEntry): void\n /** Open the contextual \"more\" menu for a child entry. */\n (\n event: 'openMenu',\n nativeEvent: MouseEvent | KeyboardEvent,\n entry: TraversedEntry,\n ): void\n /** A child entry was selected. */\n (event: 'selectItem', id: string): void\n /** A child group was toggled. */\n (event: 'toggleGroup', id: string): void\n /** A drag-and-drop operation has completed. */\n (\n event: 'dragEnd',\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n ): boolean\n}>()\n\nconst handleDragEnd = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => emit('dragEnd', draggingItem, hoveredItem)\n</script>\n\n<template>\n <ScalarSidebarNestedItems\n :active=\"active\"\n controlled\n :open=\"open\"\n @back=\"emit('back')\"\n @click=\"emit('click', item)\">\n <span>{{ item.title }}</span>\n <template\n v-if=\"loading\"\n #aside>\n <span class=\"text-c-3 text-xs\">Loading…</span>\n </template>\n <!-- Document back row -->\n <template #back>\n <div class=\"flex items-center gap-1\">\n <ScalarSidebarButton\n is=\"button\"\n class=\"text-sidebar-c-1 font-sidebar-active hover:text-sidebar-c-1 flex-1\"\n @click=\"emit('back')\">\n <template #icon>\n <ScalarIconCaretLeft class=\"text-sidebar-c-2 -m-px size-4\" />\n </template>\n Back\n </ScalarSidebarButton>\n <ScalarIconButton\n :icon=\"ScalarIconGearSix\"\n label=\"Collection settings\"\n size=\"sm\"\n @click=\"emit('openSettings')\" />\n <ScalarIconButton\n :icon=\"ScalarIconMagnifyingGlass\"\n label=\"Search collection\"\n size=\"sm\"\n @click=\"emit('search')\" />\n <ScalarIconButton\n class=\"rounded-full border\"\n :icon=\"ScalarIconPlus\"\n label=\"Add operation\"\n size=\"sm\"\n @click=\"emit('createOperation', item)\" />\n </div>\n </template>\n <!-- Document items (operations, tags, examples) -->\n <template #items>\n <template v-if=\"item.navigation?.children?.length\">\n <SidebarItem\n v-for=\"child in filterItems('client', item.navigation.children)\"\n :key=\"child.id\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n layout=\"client\"\n @onDragEnd=\"handleDragEnd\"\n @selectItem=\"(id: string) => emit('selectItem', id)\"\n @toggleGroup=\"(id: string) => emit('toggleGroup', id)\">\n <!--\n Per-item \"more\" dropdown for tags, operations and examples\n (add / edit / delete…). The dropdown is rendered once at the\n sidebar root and anchors itself to whichever icon button opened\n it. Operation settings live on the operation header (next to the\n environment selector), not here.\n -->\n <template #decorator=\"{ item: entry }\">\n <ScalarIconButton\n aria-expanded=\"false\"\n aria-haspopup=\"menu\"\n class=\"bg-b-2\"\n :icon=\"ScalarIconDotsThree\"\n label=\"More options\"\n size=\"sm\"\n variant=\"ghost\"\n weight=\"bold\"\n @click.stop=\"(e: MouseEvent) => emit('openMenu', e, entry)\"\n @keydown.down.stop=\"\n (e: KeyboardEvent) => emit('openMenu', e, entry)\n \"\n @keydown.enter.stop=\"\n (e: KeyboardEvent) => emit('openMenu', e, entry)\n \"\n @keydown.space.stop=\"\n (e: KeyboardEvent) => emit('openMenu', e, entry)\n \"\n @keydown.up.stop=\"\n (e: KeyboardEvent) => emit('openMenu', e, entry)\n \" />\n </template>\n <!--\n Empty tag / folder slot. Matches the \"Add operation\" affordance\n from the old sidebar so users can create an operation directly\n inside the hovered tag.\n -->\n <template #empty=\"{ item: emptyItem }\">\n <ScalarSidebarItem\n is=\"button\"\n @click=\"emit('addEmptyFolder', emptyItem)\">\n <template #icon>\n <ScalarIconPlus />\n </template>\n <template #default>Add operation</template>\n </ScalarSidebarItem>\n </template>\n </SidebarItem>\n </template>\n <li\n v-else\n class=\"text-c-3 px-3 py-1 text-xs\">\n Empty document\n </li>\n </template>\n </ScalarSidebarNestedItems>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCA,MAAM,OAAO;EA+Bb,MAAM,iBACJ,cACA,gBACY,KAAK,WAAW,cAAc,YAAW;;uBAIrD,YA8G2B,MAAA,yBAAA,EAAA;IA7GxB,QAAQ,QAAA;IACT,YAAA;IACC,MAAM,QAAA;IACN,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,OAAA;IACV,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAU,QAAA,KAAI;;IAQf,MAAI,cA2BP,CA1BN,mBA0BM,OA1BN,YA0BM;KAzBJ,YAQsB,MAAA,oBAAA,EAAA;MAPpB,IAAG;MACH,OAAM;MACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,OAAA;;MACD,MAAI,cACgD,CAA7D,YAA6D,MAAA,oBAAA,EAAA,EAAxC,OAAM,iCAA+B,CAAA,CAAA,CAAA;6BAG9D,CAAA,OAAA,OAAA,OAAA,KAAA,gBAFa,UAEb,GAAA,EAAA,CAAA;;;KACA,YAIkC,MAAA,iBAAA,EAAA;MAH/B,MAAM,MAAA,kBAAiB;MACxB,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,eAAA;;KACd,YAI4B,MAAA,iBAAA,EAAA;MAHzB,MAAM,MAAA,0BAAyB;MAChC,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAA;;KACd,YAK2C,MAAA,iBAAA,EAAA;MAJzC,OAAM;MACL,MAAM,MAAA,eAAc;MACrB,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,mBAAoB,QAAA,KAAI;;;IAI/B,OAAK,cA4DH,CA3DK,QAAA,KAAK,YAAY,UAAU,UAAA,UAAA,KAAA,EACzC,mBAyDc,UAAA,EAAA,KAAA,GAAA,EAAA,WAxDI,MAAA,YAAW,CAAA,UAAW,QAAA,KAAK,WAAW,SAAQ,GAAvD,UAAK;yBADd,YAyDc,MAAA,YAAA,EAAA;MAvDX,KAAK,MAAM;MACX,aAAa,QAAA;MACb,YAAY,QAAA;MACZ,YAAY,QAAA;MACZ,MAAM;MACP,QAAO;MACN,aAAW;MACX,cAAU,OAAA,OAAA,OAAA,MAAG,OAAe,KAAI,cAAe,GAAE;MACjD,eAAW,OAAA,OAAA,OAAA,MAAG,OAAe,KAAI,eAAgB,GAAE;;MAQzC,WAAS,SAsBZ,EAAA,MAtBsB,YAAK,CACjC,YAqBM,MAAA,iBAAA,EAAA;OApBJ,iBAAc;OACd,iBAAc;OACd,OAAM;OACL,MAAM,MAAA,oBAAmB;OAC1B,OAAM;OACN,MAAK;OACL,SAAQ;OACR,QAAO;OACN,SAAK,eAAQ,MAAkB,KAAI,YAAa,GAAG,MAAK,EAAA,CAAA,OAAA,CAAA;OACxD,WAAO;gCAA8B,MAAqB,KAAI,YAAa,GAAG,MAAK,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,OAAA,CAAA;gCAG7C,MAAqB,KAAI,YAAa,GAAG,MAAK,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,QAAA,CAAA;gCAG9C,MAAqB,KAAI,YAAa,GAAG,MAAK,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,QAAA,CAAA;gCAGjD,MAAqB,KAAI,YAAa,GAAG,MAAK,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,KAAA,CAAA;;;;;;;MAS3E,OAAK,SAQM,EAAA,MARI,gBAAS,CACjC,YAOoB,MAAA,kBAAA,EAAA;OANlB,IAAG;OACF,UAAK,WAAE,KAAI,kBAAmB,UAAS;;OAC7B,MAAI,cACK,CAAlB,YAAkB,MAAA,eAAA,CAAA,CAAA,CAAA;OAET,SAAO,cAAc,CAAA,GAAA,OAAA,QAAA,OAAA,MAAA,CAAA,gBAAb,iBAAa,GAAA,CAAA,EAAA,CAAA;;;;;;;;;;8BAKxC,mBAIK,MAJL,YAEqC,mBAErC,EAAA,CAAA;2BAtG2B,CAA7B,mBAA6B,QAAA,MAAA,gBAApB,QAAA,KAAK,MAAK,EAAA,EAAA,CAAA,CAAA;;OAEX,QAAA,UAAA;UACL;sBAC6C,CAAA,OAAA,OAAA,OAAA,KAA9C,mBAA8C,QAAA,EAAxC,OAAM,oBAAkB,EAAC,YAAQ,GAAA,EAAA,CAAA"}
@@ -0,0 +1,51 @@
1
+ import type { WorkspaceStore } from '@scalar/workspace-store/client';
2
+ import type { ImportDocumentFromRegistry } from '../../../../v2/types/configuration';
3
+ /** Result returned by `checkVersionConflict`. */
4
+ type CheckVersionConflictResult = {
5
+ ok: true;
6
+ hasConflict: boolean;
7
+ /**
8
+ * `true` when the result was already cached on the document for the
9
+ * current registry hash and we did not have to fetch / recompute.
10
+ */
11
+ fromCache: boolean;
12
+ } | {
13
+ ok: false;
14
+ error: string;
15
+ };
16
+ /**
17
+ * Compute (or reuse a cached) conflict-check result for a registry-backed
18
+ * workspace document and persist it on `x-scalar-registry-meta`.
19
+ *
20
+ * The check is a three-way merge between:
21
+ * - the original document (last-known remote, kept in
22
+ * `workspaceStore.getOriginalDocument`),
23
+ * - the editable workspace document (with the user's local edits),
24
+ * - the freshly-fetched remote document advertised at `registryCommitHash`.
25
+ *
26
+ * The result is cached on the document under
27
+ * `x-scalar-registry-meta.{conflictCheckedAgainstHash, hasConflict}` so
28
+ * subsequent renders can short-circuit. The cache is only valid while
29
+ * `conflictCheckedAgainstHash === registryCommitHash`.
30
+ *
31
+ * Writing to `x-scalar-registry-meta` does not flip the document's
32
+ * `x-scalar-is-dirty` flag (the workspace store excludes registry meta from
33
+ * the dirty tracker), so this side effect is safe to perform in the
34
+ * background.
35
+ */
36
+ export declare const checkVersionConflict: ({ workspaceStore, fetcher, documentName, namespace, slug, version, registryCommitHash, }: {
37
+ workspaceStore: WorkspaceStore;
38
+ fetcher: ImportDocumentFromRegistry;
39
+ /** Name of the workspace document the cache lives on. */
40
+ documentName: string;
41
+ namespace: string;
42
+ slug: string;
43
+ version: string;
44
+ /**
45
+ * Commit hash advertised by the registry for this version. The conflict
46
+ * cache is keyed on this hash; passing `undefined` skips the check.
47
+ */
48
+ registryCommitHash?: string;
49
+ }) => Promise<CheckVersionConflictResult>;
50
+ export {};
51
+ //# sourceMappingURL=check-version-conflict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-version-conflict.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/check-version-conflict.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AAI1E,iDAAiD;AACjD,KAAK,0BAA0B,GAC3B;IACE,EAAE,EAAE,IAAI,CAAA;IACR,WAAW,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAA;CACnB,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,GAAU,0FAQxC;IACD,cAAc,EAAE,cAAc,CAAA;IAC9B,OAAO,EAAE,0BAA0B,CAAA;IACnC,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,KAAG,OAAO,CAAC,0BAA0B,CAiDrC,CAAA"}
@@ -0,0 +1,79 @@
1
+ import { detectDocumentConflicts } from "./detect-document-conflicts.js";
2
+ //#region src/v2/features/app/helpers/check-version-conflict.ts
3
+ /**
4
+ * Compute (or reuse a cached) conflict-check result for a registry-backed
5
+ * workspace document and persist it on `x-scalar-registry-meta`.
6
+ *
7
+ * The check is a three-way merge between:
8
+ * - the original document (last-known remote, kept in
9
+ * `workspaceStore.getOriginalDocument`),
10
+ * - the editable workspace document (with the user's local edits),
11
+ * - the freshly-fetched remote document advertised at `registryCommitHash`.
12
+ *
13
+ * The result is cached on the document under
14
+ * `x-scalar-registry-meta.{conflictCheckedAgainstHash, hasConflict}` so
15
+ * subsequent renders can short-circuit. The cache is only valid while
16
+ * `conflictCheckedAgainstHash === registryCommitHash`.
17
+ *
18
+ * Writing to `x-scalar-registry-meta` does not flip the document's
19
+ * `x-scalar-is-dirty` flag (the workspace store excludes registry meta from
20
+ * the dirty tracker), so this side effect is safe to perform in the
21
+ * background.
22
+ */
23
+ var checkVersionConflict = async ({ workspaceStore, fetcher, documentName, namespace, slug, version, registryCommitHash }) => {
24
+ if (!registryCommitHash) return {
25
+ ok: false,
26
+ error: "No registry commit hash available for this version."
27
+ };
28
+ const document = workspaceStore.workspace.documents[documentName];
29
+ if (!document) return {
30
+ ok: false,
31
+ error: `Document "${documentName}" is not loaded in the workspace.`
32
+ };
33
+ const meta = document["x-scalar-registry-meta"];
34
+ if (meta?.conflictCheckedAgainstHash === registryCommitHash && typeof meta?.hasConflict === "boolean") return {
35
+ ok: true,
36
+ hasConflict: meta.hasConflict,
37
+ fromCache: true
38
+ };
39
+ const original = workspaceStore.getOriginalDocument(documentName);
40
+ if (!original) return {
41
+ ok: false,
42
+ error: `Original document for "${documentName}" is unavailable.`
43
+ };
44
+ const result = await fetcher({
45
+ namespace,
46
+ slug,
47
+ version
48
+ });
49
+ if (!result.ok) return {
50
+ ok: false,
51
+ error: `Failed to fetch document: ${result.error || "Unknown error"}`
52
+ };
53
+ const hasConflict = detectDocumentConflicts({
54
+ original,
55
+ local: document,
56
+ remote: result.data
57
+ });
58
+ document["x-scalar-registry-meta"] = {
59
+ ...meta ?? {
60
+ namespace,
61
+ slug,
62
+ version
63
+ },
64
+ namespace,
65
+ slug,
66
+ version,
67
+ conflictCheckedAgainstHash: registryCommitHash,
68
+ hasConflict
69
+ };
70
+ return {
71
+ ok: true,
72
+ hasConflict,
73
+ fromCache: false
74
+ };
75
+ };
76
+ //#endregion
77
+ export { checkVersionConflict };
78
+
79
+ //# sourceMappingURL=check-version-conflict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-version-conflict.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/check-version-conflict.ts"],"sourcesContent":["import type { WorkspaceStore } from '@scalar/workspace-store/client'\n\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\n\nimport { detectDocumentConflicts } from './detect-document-conflicts'\n\n/** Result returned by `checkVersionConflict`. */\ntype CheckVersionConflictResult =\n | {\n ok: true\n hasConflict: boolean\n /**\n * `true` when the result was already cached on the document for the\n * current registry hash and we did not have to fetch / recompute.\n */\n fromCache: boolean\n }\n | { ok: false; error: string }\n\n/**\n * Compute (or reuse a cached) conflict-check result for a registry-backed\n * workspace document and persist it on `x-scalar-registry-meta`.\n *\n * The check is a three-way merge between:\n * - the original document (last-known remote, kept in\n * `workspaceStore.getOriginalDocument`),\n * - the editable workspace document (with the user's local edits),\n * - the freshly-fetched remote document advertised at `registryCommitHash`.\n *\n * The result is cached on the document under\n * `x-scalar-registry-meta.{conflictCheckedAgainstHash, hasConflict}` so\n * subsequent renders can short-circuit. The cache is only valid while\n * `conflictCheckedAgainstHash === registryCommitHash`.\n *\n * Writing to `x-scalar-registry-meta` does not flip the document's\n * `x-scalar-is-dirty` flag (the workspace store excludes registry meta from\n * the dirty tracker), so this side effect is safe to perform in the\n * background.\n */\nexport const checkVersionConflict = async ({\n workspaceStore,\n fetcher,\n documentName,\n namespace,\n slug,\n version,\n registryCommitHash,\n}: {\n workspaceStore: WorkspaceStore\n fetcher: ImportDocumentFromRegistry\n /** Name of the workspace document the cache lives on. */\n documentName: string\n namespace: string\n slug: string\n version: string\n /**\n * Commit hash advertised by the registry for this version. The conflict\n * cache is keyed on this hash; passing `undefined` skips the check.\n */\n registryCommitHash?: string\n}): Promise<CheckVersionConflictResult> => {\n if (!registryCommitHash) {\n return { ok: false, error: 'No registry commit hash available for this version.' }\n }\n\n const document = workspaceStore.workspace.documents[documentName]\n if (!document) {\n return { ok: false, error: `Document \"${documentName}\" is not loaded in the workspace.` }\n }\n\n const meta = document['x-scalar-registry-meta']\n\n // Cache hit - the previous check was performed against the registry hash\n // we are being asked about, so we can return the stored result without\n // touching the network.\n if (meta?.conflictCheckedAgainstHash === registryCommitHash && typeof meta?.hasConflict === 'boolean') {\n return { ok: true, hasConflict: meta.hasConflict, fromCache: true }\n }\n\n const original = workspaceStore.getOriginalDocument(documentName)\n if (!original) {\n return { ok: false, error: `Original document for \"${documentName}\" is unavailable.` }\n }\n\n const result = await fetcher({ namespace, slug, version })\n if (!result.ok) {\n return { ok: false, error: `Failed to fetch document: ${result.error || 'Unknown error'}` }\n }\n\n const hasConflict = detectDocumentConflicts({\n original: original as Record<string, unknown>,\n local: document as unknown as Record<string, unknown>,\n remote: result.data,\n })\n\n // Persist the cache on the document. The workspace store's dirty tracker\n // skips `x-scalar-registry-meta` writes, so this does not mark the\n // document as having local edits.\n const next = {\n ...(meta ?? { namespace, slug, version }),\n namespace,\n slug,\n version,\n conflictCheckedAgainstHash: registryCommitHash,\n hasConflict,\n }\n document['x-scalar-registry-meta'] = next\n\n return { ok: true, hasConflict, fromCache: false }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAa,uBAAuB,OAAO,EACzC,gBACA,SACA,cACA,WACA,MACA,SACA,yBAcyC;AACzC,KAAI,CAAC,mBACH,QAAO;EAAE,IAAI;EAAO,OAAO;EAAuD;CAGpF,MAAM,WAAW,eAAe,UAAU,UAAU;AACpD,KAAI,CAAC,SACH,QAAO;EAAE,IAAI;EAAO,OAAO,aAAa,aAAa;EAAoC;CAG3F,MAAM,OAAO,SAAS;AAKtB,KAAI,MAAM,+BAA+B,sBAAsB,OAAO,MAAM,gBAAgB,UAC1F,QAAO;EAAE,IAAI;EAAM,aAAa,KAAK;EAAa,WAAW;EAAM;CAGrE,MAAM,WAAW,eAAe,oBAAoB,aAAa;AACjE,KAAI,CAAC,SACH,QAAO;EAAE,IAAI;EAAO,OAAO,0BAA0B,aAAa;EAAoB;CAGxF,MAAM,SAAS,MAAM,QAAQ;EAAE;EAAW;EAAM;EAAS,CAAC;AAC1D,KAAI,CAAC,OAAO,GACV,QAAO;EAAE,IAAI;EAAO,OAAO,6BAA6B,OAAO,SAAS;EAAmB;CAG7F,MAAM,cAAc,wBAAwB;EAChC;EACV,OAAO;EACP,QAAQ,OAAO;EAChB,CAAC;AAaF,UAAS,4BARI;EACX,GAAI,QAAQ;GAAE;GAAW;GAAM;GAAS;EACxC;EACA;EACA;EACA,4BAA4B;EAC5B;EACD;AAGD,QAAO;EAAE,IAAI;EAAM;EAAa,WAAW;EAAO"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Sync status surfaced for a registry-backed document version.
3
+ *
4
+ * - `synced`: local commit hash matches the registry's, no local edits since
5
+ * the last save. Nothing to push or pull.
6
+ * - `push`: the workspace document has changes the registry has not seen
7
+ * yet. This covers two cases:
8
+ * 1. Hashes match but the document is dirty (the user has edited it).
9
+ * 2. The document is a brand-new draft - it has registry coordinates but
10
+ * no commit hash on either side, meaning it has never been pushed.
11
+ * - `pull`: registry advertises a different commit hash than the locally
12
+ * stored one *and* we have not detected a merge conflict (or have not
13
+ * checked yet). Pulling the upstream version is safe.
14
+ * - `conflict`: registry advertises a different commit hash than the local
15
+ * one *and* a previous conflict check (cached on the document) determined
16
+ * that merging the upstream version with the local edits would produce
17
+ * conflicts. The user has to resolve them manually.
18
+ * - `unknown`: the version is not loaded into the workspace store yet, so
19
+ * there is nothing local to compare against.
20
+ */
21
+ export type VersionStatus = 'synced' | 'push' | 'pull' | 'conflict' | 'unknown';
22
+ /**
23
+ * Derive the sync status for a single registry-backed version from cached
24
+ * inputs. Pure and synchronous - the conflict check itself is performed
25
+ * elsewhere (`check-version-conflict`) and persisted on the document so this
26
+ * function only has to read the cached result.
27
+ */
28
+ export declare const computeVersionStatus: ({ isLoaded, localHash, registryHash, isDirty, conflictCheckedAgainstHash, hasConflict, }: {
29
+ /** True when the version has a corresponding workspace document. */
30
+ isLoaded: boolean;
31
+ /** Commit hash recorded on the local workspace document, if any. */
32
+ localHash?: string;
33
+ /** Commit hash advertised by the registry for this version, if any. */
34
+ registryHash?: string;
35
+ /** Whether the workspace document has uncommitted local edits. */
36
+ isDirty?: boolean;
37
+ /**
38
+ * Registry hash that the cached `hasConflict` flag was computed against.
39
+ * The cache is only valid while it matches `registryHash`.
40
+ */
41
+ conflictCheckedAgainstHash?: string;
42
+ /** Cached outcome of the last conflict check. */
43
+ hasConflict?: boolean;
44
+ }) => VersionStatus;
45
+ //# sourceMappingURL=compute-version-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-version-status.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/compute-version-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,0FAOlC;IACD,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAA;IACjB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,KAAG,aAsBH,CAAA"}
@@ -0,0 +1,18 @@
1
+ //#region src/v2/features/app/helpers/compute-version-status.ts
2
+ /**
3
+ * Derive the sync status for a single registry-backed version from cached
4
+ * inputs. Pure and synchronous - the conflict check itself is performed
5
+ * elsewhere (`check-version-conflict`) and persisted on the document so this
6
+ * function only has to read the cached result.
7
+ */
8
+ var computeVersionStatus = ({ isLoaded, localHash, registryHash, isDirty, conflictCheckedAgainstHash, hasConflict }) => {
9
+ if (!isLoaded) return "unknown";
10
+ const isConflictActive = hasConflict && conflictCheckedAgainstHash === registryHash;
11
+ if (!registryHash) return isDirty || !localHash ? "push" : "synced";
12
+ if (localHash === registryHash) return isDirty ? "push" : "synced";
13
+ return isConflictActive ? "conflict" : "pull";
14
+ };
15
+ //#endregion
16
+ export { computeVersionStatus };
17
+
18
+ //# sourceMappingURL=compute-version-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-version-status.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/compute-version-status.ts"],"sourcesContent":["/**\n * Sync status surfaced for a registry-backed document version.\n *\n * - `synced`: local commit hash matches the registry's, no local edits since\n * the last save. Nothing to push or pull.\n * - `push`: the workspace document has changes the registry has not seen\n * yet. This covers two cases:\n * 1. Hashes match but the document is dirty (the user has edited it).\n * 2. The document is a brand-new draft - it has registry coordinates but\n * no commit hash on either side, meaning it has never been pushed.\n * - `pull`: registry advertises a different commit hash than the locally\n * stored one *and* we have not detected a merge conflict (or have not\n * checked yet). Pulling the upstream version is safe.\n * - `conflict`: registry advertises a different commit hash than the local\n * one *and* a previous conflict check (cached on the document) determined\n * that merging the upstream version with the local edits would produce\n * conflicts. The user has to resolve them manually.\n * - `unknown`: the version is not loaded into the workspace store yet, so\n * there is nothing local to compare against.\n */\nexport type VersionStatus = 'synced' | 'push' | 'pull' | 'conflict' | 'unknown'\n\n/**\n * Derive the sync status for a single registry-backed version from cached\n * inputs. Pure and synchronous - the conflict check itself is performed\n * elsewhere (`check-version-conflict`) and persisted on the document so this\n * function only has to read the cached result.\n */\nexport const computeVersionStatus = ({\n isLoaded,\n localHash,\n registryHash,\n isDirty,\n conflictCheckedAgainstHash,\n hasConflict,\n}: {\n /** True when the version has a corresponding workspace document. */\n isLoaded: boolean\n /** Commit hash recorded on the local workspace document, if any. */\n localHash?: string\n /** Commit hash advertised by the registry for this version, if any. */\n registryHash?: string\n /** Whether the workspace document has uncommitted local edits. */\n isDirty?: boolean\n /**\n * Registry hash that the cached `hasConflict` flag was computed against.\n * The cache is only valid while it matches `registryHash`.\n */\n conflictCheckedAgainstHash?: string\n /** Cached outcome of the last conflict check. */\n hasConflict?: boolean\n}): VersionStatus => {\n // 1. Foundation check\n if (!isLoaded) {\n return 'unknown'\n }\n\n // 2. Cache Validation: Determine if we have a valid, active conflict\n const isConflictActive = hasConflict && conflictCheckedAgainstHash === registryHash\n\n // 3. Scenario: Nothing on the Registry\n if (!registryHash) {\n // If no remote hash exists, it's either a fresh draft (push) or a local-only change\n return isDirty || !localHash ? 'push' : 'synced'\n }\n\n // 4. Scenario: Matches Registry\n if (localHash === registryHash) {\n return isDirty ? 'push' : 'synced'\n }\n // 5. Scenario: Hash Mismatch (or no localHash but registryHash exists)\n // At this point, localHash !== registryHash and registryHash exists.\n return isConflictActive ? 'conflict' : 'pull'\n}\n"],"mappings":";;;;;;;AA4BA,IAAa,wBAAwB,EACnC,UACA,WACA,cACA,SACA,4BACA,kBAiBmB;AAEnB,KAAI,CAAC,SACH,QAAO;CAIT,MAAM,mBAAmB,eAAe,+BAA+B;AAGvE,KAAI,CAAC,aAEH,QAAO,WAAW,CAAC,YAAY,SAAS;AAI1C,KAAI,cAAc,aAChB,QAAO,UAAU,SAAS;AAI5B,QAAO,mBAAmB,aAAa"}
@@ -0,0 +1,39 @@
1
+ import type { WorkspaceStore } from '@scalar/workspace-store/client';
2
+ /** Result of attempting to create a draft registry document. */
3
+ type CreateDraftRegistryDocumentResult = {
4
+ ok: true;
5
+ documentName: string;
6
+ } | {
7
+ ok: false;
8
+ error: string;
9
+ };
10
+ /**
11
+ * Create a draft workspace document for a brand-new registry version.
12
+ *
13
+ * The draft is seeded from an existing workspace document (typically the
14
+ * currently active version) so the user has something to start from rather
15
+ * than a blank schema. We pull the seed via `getEditableDocument`, which
16
+ * already returns a clean OpenAPI body (internal extensions like
17
+ * `x-scalar-is-dirty`, `x-scalar-navigation`, and the original-document hash
18
+ * are stripped, and `$ref`s are restored), so we only need to stamp the new
19
+ * `info.version` and let `addDocument` do the rest. The `meta` we pass in
20
+ * overrides any leftover `x-scalar-registry-meta` from the seed during the
21
+ * spread that `addInMemoryDocument` performs.
22
+ *
23
+ * Crucially, we do not record a `commitHash` in `x-scalar-registry-meta` -
24
+ * a missing hash is what marks the document as a "draft" the user has not
25
+ * yet pushed to the registry. If the registry later advertises a hash for
26
+ * this version, the existing version-status pipeline picks it up and
27
+ * surfaces the regular pull / conflict flow.
28
+ */
29
+ export declare const createDraftRegistryDocument: ({ workspaceStore, namespace, slug, version, seedDocumentName, }: {
30
+ workspaceStore: WorkspaceStore;
31
+ namespace: string;
32
+ slug: string;
33
+ /** Version string the user just typed in the create-version modal. */
34
+ version: string;
35
+ /** Name of the workspace document whose contents we branch off for the draft. */
36
+ seedDocumentName: string;
37
+ }) => Promise<CreateDraftRegistryDocumentResult>;
38
+ export {};
39
+ //# sourceMappingURL=create-draft-registry-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-draft-registry-document.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-draft-registry-document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAIpE,gEAAgE;AAChE,KAAK,iCAAiC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1G;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,2BAA2B,GAAU,iEAM/C;IACD,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAA;IACf,iFAAiF;IACjF,gBAAgB,EAAE,MAAM,CAAA;CACzB,KAAG,OAAO,CAAC,iCAAiC,CAwD5C,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { generateUniqueSlug } from "../../command-palette/helpers/generate-unique-slug.js";
2
+ //#region src/v2/features/app/helpers/create-draft-registry-document.ts
3
+ /**
4
+ * Create a draft workspace document for a brand-new registry version.
5
+ *
6
+ * The draft is seeded from an existing workspace document (typically the
7
+ * currently active version) so the user has something to start from rather
8
+ * than a blank schema. We pull the seed via `getEditableDocument`, which
9
+ * already returns a clean OpenAPI body (internal extensions like
10
+ * `x-scalar-is-dirty`, `x-scalar-navigation`, and the original-document hash
11
+ * are stripped, and `$ref`s are restored), so we only need to stamp the new
12
+ * `info.version` and let `addDocument` do the rest. The `meta` we pass in
13
+ * overrides any leftover `x-scalar-registry-meta` from the seed during the
14
+ * spread that `addInMemoryDocument` performs.
15
+ *
16
+ * Crucially, we do not record a `commitHash` in `x-scalar-registry-meta` -
17
+ * a missing hash is what marks the document as a "draft" the user has not
18
+ * yet pushed to the registry. If the registry later advertises a hash for
19
+ * this version, the existing version-status pipeline picks it up and
20
+ * surfaces the regular pull / conflict flow.
21
+ */
22
+ var createDraftRegistryDocument = async ({ workspaceStore, namespace, slug, version, seedDocumentName }) => {
23
+ const cloned = await workspaceStore.getEditableDocument(seedDocumentName);
24
+ if (!cloned) return {
25
+ ok: false,
26
+ error: `Seed document "${seedDocumentName}" is not loaded in the workspace.`
27
+ };
28
+ cloned.info = {
29
+ ...cloned.info ?? { title: "" },
30
+ version
31
+ };
32
+ const documentName = await generateUniqueSlug(`${cloned.info.title?.trim() || slug}-${version}`, new Set(Object.keys(workspaceStore.workspace.documents)));
33
+ if (!documentName) return {
34
+ ok: false,
35
+ error: "Failed to generate a unique name for the new version."
36
+ };
37
+ try {
38
+ if (!await workspaceStore.addDocument({
39
+ name: documentName,
40
+ document: cloned,
41
+ meta: { "x-scalar-registry-meta": {
42
+ namespace,
43
+ slug,
44
+ version
45
+ } }
46
+ })) return {
47
+ ok: false,
48
+ error: "Failed to add the new version to the workspace."
49
+ };
50
+ } catch (error) {
51
+ return {
52
+ ok: false,
53
+ error: error instanceof Error ? error.message : "Failed to add the new version to the workspace."
54
+ };
55
+ }
56
+ return {
57
+ ok: true,
58
+ documentName
59
+ };
60
+ };
61
+ //#endregion
62
+ export { createDraftRegistryDocument };
63
+
64
+ //# sourceMappingURL=create-draft-registry-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-draft-registry-document.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/create-draft-registry-document.ts"],"sourcesContent":["import type { WorkspaceStore } from '@scalar/workspace-store/client'\n\nimport { generateUniqueSlug } from '@/v2/features/command-palette/helpers/generate-unique-slug'\n\n/** Result of attempting to create a draft registry document. */\ntype CreateDraftRegistryDocumentResult = { ok: true; documentName: string } | { ok: false; error: string }\n\n/**\n * Create a draft workspace document for a brand-new registry version.\n *\n * The draft is seeded from an existing workspace document (typically the\n * currently active version) so the user has something to start from rather\n * than a blank schema. We pull the seed via `getEditableDocument`, which\n * already returns a clean OpenAPI body (internal extensions like\n * `x-scalar-is-dirty`, `x-scalar-navigation`, and the original-document hash\n * are stripped, and `$ref`s are restored), so we only need to stamp the new\n * `info.version` and let `addDocument` do the rest. The `meta` we pass in\n * overrides any leftover `x-scalar-registry-meta` from the seed during the\n * spread that `addInMemoryDocument` performs.\n *\n * Crucially, we do not record a `commitHash` in `x-scalar-registry-meta` -\n * a missing hash is what marks the document as a \"draft\" the user has not\n * yet pushed to the registry. If the registry later advertises a hash for\n * this version, the existing version-status pipeline picks it up and\n * surfaces the regular pull / conflict flow.\n */\nexport const createDraftRegistryDocument = async ({\n workspaceStore,\n namespace,\n slug,\n version,\n seedDocumentName,\n}: {\n workspaceStore: WorkspaceStore\n namespace: string\n slug: string\n /** Version string the user just typed in the create-version modal. */\n version: string\n /** Name of the workspace document whose contents we branch off for the draft. */\n seedDocumentName: string\n}): Promise<CreateDraftRegistryDocumentResult> => {\n const cloned = await workspaceStore.getEditableDocument(seedDocumentName)\n if (!cloned) {\n return {\n ok: false,\n error: `Seed document \"${seedDocumentName}\" is not loaded in the workspace.`,\n }\n }\n\n // Stamp the user-typed version onto the document itself so the rendered\n // OpenAPI matches the registry coordinates. `info` is required by the\n // OpenAPI schema, but we still guard against an unusually shaped seed.\n cloned.info = { ...(cloned.info ?? { title: '' }), version }\n\n // Compose the workspace key as `slug(title)-slug(version)`\n // so the url will be like /workspace/acme/pets-api-1.0.0\n const title = cloned.info.title?.trim() || slug\n const documentName = await generateUniqueSlug(\n `${title}-${version}`,\n new Set(Object.keys(workspaceStore.workspace.documents)),\n )\n\n if (!documentName) {\n return {\n ok: false,\n error: 'Failed to generate a unique name for the new version.',\n }\n }\n\n try {\n const ok = await workspaceStore.addDocument({\n name: documentName,\n document: cloned,\n meta: {\n 'x-scalar-registry-meta': {\n namespace,\n slug,\n version,\n },\n },\n })\n\n if (!ok) {\n return {\n ok: false,\n error: 'Failed to add the new version to the workspace.',\n }\n }\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Failed to add the new version to the workspace.',\n }\n }\n\n return { ok: true, documentName }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,8BAA8B,OAAO,EAChD,gBACA,WACA,MACA,SACA,uBASgD;CAChD,MAAM,SAAS,MAAM,eAAe,oBAAoB,iBAAiB;AACzE,KAAI,CAAC,OACH,QAAO;EACL,IAAI;EACJ,OAAO,kBAAkB,iBAAiB;EAC3C;AAMH,QAAO,OAAO;EAAE,GAAI,OAAO,QAAQ,EAAE,OAAO,IAAI;EAAG;EAAS;CAK5D,MAAM,eAAe,MAAM,mBACzB,GAFY,OAAO,KAAK,OAAO,MAAM,IAAI,KAEhC,GAAG,WACZ,IAAI,IAAI,OAAO,KAAK,eAAe,UAAU,UAAU,CAAC,CACzD;AAED,KAAI,CAAC,aACH,QAAO;EACL,IAAI;EACJ,OAAO;EACR;AAGH,KAAI;AAaF,MAAI,CAZO,MAAM,eAAe,YAAY;GAC1C,MAAM;GACN,UAAU;GACV,MAAM,EACJ,0BAA0B;IACxB;IACA;IACA;IACD,EACF;GACF,CAAC,CAGA,QAAO;GACL,IAAI;GACJ,OAAO;GACR;UAEI,OAAO;AACd,SAAO;GACL,IAAI;GACJ,OAAO,iBAAiB,QAAQ,MAAM,UAAU;GACjD;;AAGH,QAAO;EAAE,IAAI;EAAM;EAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-temp-operation.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-temp-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AA+BvE;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,MAAM,EACpB,SAAS;IACP,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB,SA+BF,CAAA"}
1
+ {"version":3,"file":"create-temp-operation.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-temp-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AA+BvE;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,MAAM,EACpB,SAAS;IACP,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB,SAyBF,CAAA"}
@@ -12,8 +12,8 @@
12
12
  * @returns A unique operation path (e.g., "/temp1234abcd")
13
13
  */
14
14
  var generateUniquePath = (existingPaths, attempts = 0) => {
15
- if (attempts > 10) return "/temp-path";
16
- const path = `/temp${crypto.randomUUID().slice(0, 8)}`;
15
+ if (attempts > 10) return "/_scalar_temp";
16
+ const path = `/_scalar_temp${crypto.randomUUID().slice(0, 8)}`;
17
17
  if (existingPaths.has(path)) return generateUniquePath(existingPaths, attempts + 1);
18
18
  return path;
19
19
  };
@@ -35,16 +35,13 @@ var createTempOperation = (documentName, options) => {
35
35
  tags: options.tags ?? []
36
36
  },
37
37
  callback: (success) => {
38
- if (success) options.eventBus.emit("ui:navigate", {
38
+ if (!success) return;
39
+ options.eventBus.emit("ui:navigate", {
39
40
  page: "example",
40
41
  documentSlug: documentName,
41
42
  path: uniquePath,
42
43
  method: "get",
43
- exampleName: "default",
44
- callback: async () => {
45
- await new Promise((resolve) => requestAnimationFrame(resolve));
46
- options.eventBus.emit("ui:focus:address-bar", { clear: true });
47
- }
44
+ exampleName: "default"
48
45
  });
49
46
  }
50
47
  });
@@ -1 +1 @@
1
- {"version":3,"file":"create-temp-operation.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/create-temp-operation.ts"],"sourcesContent":["import type { WorkspaceEventBus } from '@scalar/workspace-store/events'\n\n/**\n * Generates a unique temporary operation path for a new operation.\n * Tries up to 10 times to generate a non-colliding path, then falls back to a static path.\n *\n * Example:\n * const existingPaths = new Set(['/tempabcd1234', '/tempdeadbeef']);\n * const newPath = generateUniquePath('my-doc', existingPaths); // e.g. \"/tempa1b2c3d4\"\n *\n * @param existingPaths - Set of paths already present in the document to avoid collisions\n * @param attempts - Used internally to limit recursion (default: 0)\n * @returns A unique operation path (e.g., \"/temp1234abcd\")\n */\nconst generateUniquePath = (existingPaths: Set<string>, attempts: number = 0) => {\n if (attempts > 10) {\n // After 10 failed attempts, fallback to a generic path\n return '/temp-path'\n }\n\n // Generate a random path using a truncated UUID for uniqueness\n const path = `/temp${crypto.randomUUID().slice(0, 8)}`\n\n if (existingPaths.has(path)) {\n // If path exists, try again recursively with incremented attempts\n return generateUniquePath(existingPaths, attempts + 1)\n }\n\n return path\n}\n\n/**\n * Creates a temporary operation with a unique path, emits its creation on the event bus,\n * then navigates to the operation and focuses the address bar if successful.\n * @param documentName - The name of the document to add the operation to\n * @param existingPaths - Set of existing operation paths for uniqueness checking\n * @param eventBus - The workspace event bus to emit events on\n */\nexport const createTempOperation = (\n documentName: string,\n options: {\n existingPaths: Set<string>\n eventBus: WorkspaceEventBus\n tags?: string[]\n },\n) => {\n const uniquePath = generateUniquePath(options.existingPaths)\n\n options.eventBus.emit('operation:create:operation', {\n documentName,\n path: uniquePath,\n method: 'get',\n operation: {\n summary: 'New operation',\n tags: options.tags ?? [],\n },\n callback: (success) => {\n if (success) {\n options.eventBus.emit('ui:navigate', {\n page: 'example',\n documentSlug: documentName,\n path: uniquePath,\n method: 'get',\n exampleName: 'default',\n callback: async () => {\n await new Promise((resolve) => requestAnimationFrame(resolve))\n // Focus the address bar, clearing its contents after navigation\n options.eventBus.emit('ui:focus:address-bar', {\n clear: true,\n })\n },\n })\n }\n },\n })\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAM,sBAAsB,eAA4B,WAAmB,MAAM;AAC/E,KAAI,WAAW,GAEb,QAAO;CAIT,MAAM,OAAO,QAAQ,OAAO,YAAY,CAAC,MAAM,GAAG,EAAE;AAEpD,KAAI,cAAc,IAAI,KAAK,CAEzB,QAAO,mBAAmB,eAAe,WAAW,EAAE;AAGxD,QAAO;;;;;;;;;AAUT,IAAa,uBACX,cACA,YAKG;CACH,MAAM,aAAa,mBAAmB,QAAQ,cAAc;AAE5D,SAAQ,SAAS,KAAK,8BAA8B;EAClD;EACA,MAAM;EACN,QAAQ;EACR,WAAW;GACT,SAAS;GACT,MAAM,QAAQ,QAAQ,EAAE;GACzB;EACD,WAAW,YAAY;AACrB,OAAI,QACF,SAAQ,SAAS,KAAK,eAAe;IACnC,MAAM;IACN,cAAc;IACd,MAAM;IACN,QAAQ;IACR,aAAa;IACb,UAAU,YAAY;AACpB,WAAM,IAAI,SAAS,YAAY,sBAAsB,QAAQ,CAAC;AAE9D,aAAQ,SAAS,KAAK,wBAAwB,EAC5C,OAAO,MACR,CAAC;;IAEL,CAAC;;EAGP,CAAC"}
1
+ {"version":3,"file":"create-temp-operation.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/create-temp-operation.ts"],"sourcesContent":["import type { WorkspaceEventBus } from '@scalar/workspace-store/events'\n\n/**\n * Generates a unique temporary operation path for a new operation.\n * Tries up to 10 times to generate a non-colliding path, then falls back to a static path.\n *\n * Example:\n * const existingPaths = new Set(['/tempabcd1234', '/tempdeadbeef']);\n * const newPath = generateUniquePath('my-doc', existingPaths); // e.g. \"/tempa1b2c3d4\"\n *\n * @param existingPaths - Set of paths already present in the document to avoid collisions\n * @param attempts - Used internally to limit recursion (default: 0)\n * @returns A unique operation path (e.g., \"/temp1234abcd\")\n */\nconst generateUniquePath = (existingPaths: Set<string>, attempts: number = 0) => {\n if (attempts > 10) {\n // After 10 failed attempts, fallback to a generic path\n return '/_scalar_temp'\n }\n\n // Generate a random path using a truncated UUID for uniqueness\n const path = `/_scalar_temp${crypto.randomUUID().slice(0, 8)}`\n\n if (existingPaths.has(path)) {\n // If path exists, try again recursively with incremented attempts\n return generateUniquePath(existingPaths, attempts + 1)\n }\n\n return path\n}\n\n/**\n * Creates a temporary operation with a unique path, emits its creation on the event bus,\n * then navigates to the operation and focuses the address bar if successful.\n * @param documentName - The name of the document to add the operation to\n * @param existingPaths - Set of existing operation paths for uniqueness checking\n * @param eventBus - The workspace event bus to emit events on\n */\nexport const createTempOperation = (\n documentName: string,\n options: {\n existingPaths: Set<string>\n eventBus: WorkspaceEventBus\n tags?: string[]\n },\n) => {\n const uniquePath = generateUniquePath(options.existingPaths)\n\n options.eventBus.emit('operation:create:operation', {\n documentName,\n path: uniquePath,\n method: 'get',\n operation: {\n summary: 'New operation',\n tags: options.tags ?? [],\n },\n callback: (success) => {\n if (!success) {\n return\n }\n options.eventBus.emit('ui:navigate', {\n page: 'example',\n documentSlug: documentName,\n path: uniquePath,\n method: 'get',\n exampleName: 'default',\n })\n },\n })\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAM,sBAAsB,eAA4B,WAAmB,MAAM;AAC/E,KAAI,WAAW,GAEb,QAAO;CAIT,MAAM,OAAO,gBAAgB,OAAO,YAAY,CAAC,MAAM,GAAG,EAAE;AAE5D,KAAI,cAAc,IAAI,KAAK,CAEzB,QAAO,mBAAmB,eAAe,WAAW,EAAE;AAGxD,QAAO;;;;;;;;;AAUT,IAAa,uBACX,cACA,YAKG;CACH,MAAM,aAAa,mBAAmB,QAAQ,cAAc;AAE5D,SAAQ,SAAS,KAAK,8BAA8B;EAClD;EACA,MAAM;EACN,QAAQ;EACR,WAAW;GACT,SAAS;GACT,MAAM,QAAQ,QAAQ,EAAE;GACzB;EACD,WAAW,YAAY;AACrB,OAAI,CAAC,QACH;AAEF,WAAQ,SAAS,KAAK,eAAe;IACnC,MAAM;IACN,cAAc;IACd,MAAM;IACN,QAAQ;IACR,aAAa;IACd,CAAC;;EAEL,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Detect whether merging an upstream document with the local edits would
3
+ * produce conflicts.
4
+ *
5
+ * The check is a classic three-way comparison:
6
+ * 1. Diff the original (last-known remote) document against the local
7
+ * editable copy - this captures the user's edits.
8
+ * 2. Diff the original against the new remote document - this captures the
9
+ * upstream changes.
10
+ * 3. Run `merge` from `@scalar/json-magic/diff` over both diff lists. The
11
+ * merge yields a `conflicts` array for paths that were touched by both
12
+ * sides in incompatible ways. Any non-empty array means the user must
13
+ * resolve the conflicts manually.
14
+ *
15
+ * The function is pure - callers are responsible for fetching the remote
16
+ * document and persisting the result on the workspace document.
17
+ */
18
+ export declare const detectDocumentConflicts: ({ original, local, remote, }: {
19
+ /** Last-known remote document (the baseline both sides diverged from). */
20
+ original: Record<string, unknown>;
21
+ /** Current editable workspace document, including any local edits. */
22
+ local: Record<string, unknown>;
23
+ /** Newly-fetched remote document we want to merge in. */
24
+ remote: Record<string, unknown>;
25
+ }) => boolean;
26
+ //# sourceMappingURL=detect-document-conflicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-document-conflicts.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/detect-document-conflicts.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,GAAI,8BAIrC;IACD,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,KAAG,OAKH,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { diff, merge } from "@scalar/json-magic/diff";
2
+ //#region src/v2/features/app/helpers/detect-document-conflicts.ts
3
+ /**
4
+ * Detect whether merging an upstream document with the local edits would
5
+ * produce conflicts.
6
+ *
7
+ * The check is a classic three-way comparison:
8
+ * 1. Diff the original (last-known remote) document against the local
9
+ * editable copy - this captures the user's edits.
10
+ * 2. Diff the original against the new remote document - this captures the
11
+ * upstream changes.
12
+ * 3. Run `merge` from `@scalar/json-magic/diff` over both diff lists. The
13
+ * merge yields a `conflicts` array for paths that were touched by both
14
+ * sides in incompatible ways. Any non-empty array means the user must
15
+ * resolve the conflicts manually.
16
+ *
17
+ * The function is pure - callers are responsible for fetching the remote
18
+ * document and persisting the result on the workspace document.
19
+ */
20
+ var detectDocumentConflicts = ({ original, local, remote }) => {
21
+ const { conflicts } = merge(diff(original, local), diff(original, remote));
22
+ return conflicts.length > 0;
23
+ };
24
+ //#endregion
25
+ export { detectDocumentConflicts };
26
+
27
+ //# sourceMappingURL=detect-document-conflicts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-document-conflicts.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/detect-document-conflicts.ts"],"sourcesContent":["import { diff, merge } from '@scalar/json-magic/diff'\n\n/**\n * Detect whether merging an upstream document with the local edits would\n * produce conflicts.\n *\n * The check is a classic three-way comparison:\n * 1. Diff the original (last-known remote) document against the local\n * editable copy - this captures the user's edits.\n * 2. Diff the original against the new remote document - this captures the\n * upstream changes.\n * 3. Run `merge` from `@scalar/json-magic/diff` over both diff lists. The\n * merge yields a `conflicts` array for paths that were touched by both\n * sides in incompatible ways. Any non-empty array means the user must\n * resolve the conflicts manually.\n *\n * The function is pure - callers are responsible for fetching the remote\n * document and persisting the result on the workspace document.\n */\nexport const detectDocumentConflicts = ({\n original,\n local,\n remote,\n}: {\n /** Last-known remote document (the baseline both sides diverged from). */\n original: Record<string, unknown>\n /** Current editable workspace document, including any local edits. */\n local: Record<string, unknown>\n /** Newly-fetched remote document we want to merge in. */\n remote: Record<string, unknown>\n}): boolean => {\n const localChanges = diff(original, local)\n const remoteChanges = diff(original, remote)\n const { conflicts } = merge(localChanges, remoteChanges)\n return conflicts.length > 0\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,2BAA2B,EACtC,UACA,OACA,aAQa;CAGb,MAAM,EAAE,cAAc,MAFD,KAAK,UAAU,MAAM,EACpB,KAAK,UAAU,OAAO,CACY;AACxD,QAAO,UAAU,SAAS"}