@scalar/workspace-store 0.17.0 → 0.18.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 +64 -0
- package/dist/client.d.ts +38 -26
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +286 -84
- package/dist/client.js.map +3 -3
- package/dist/events/bus.d.ts +86 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +58 -0
- package/dist/events/bus.js.map +7 -0
- package/dist/events/definitions/analytics.d.ts +27 -0
- package/dist/events/definitions/analytics.d.ts.map +1 -0
- package/dist/events/definitions/analytics.js +1 -0
- package/dist/events/definitions/analytics.js.map +7 -0
- package/dist/events/definitions/auth.d.ts +30 -0
- package/dist/events/definitions/auth.d.ts.map +1 -0
- package/dist/events/definitions/auth.js +1 -0
- package/dist/events/definitions/auth.js.map +7 -0
- package/dist/events/definitions/document.d.ts +14 -0
- package/dist/events/definitions/document.d.ts.map +1 -0
- package/dist/events/definitions/document.js +1 -0
- package/dist/events/definitions/document.js.map +7 -0
- package/dist/events/definitions/index.d.ts +10 -0
- package/dist/events/definitions/index.d.ts.map +1 -0
- package/dist/events/definitions/index.js +1 -0
- package/dist/events/definitions/index.js.map +7 -0
- package/dist/events/definitions/meta.d.ts +11 -0
- package/dist/events/definitions/meta.d.ts.map +1 -0
- package/dist/events/definitions/meta.js +1 -0
- package/dist/events/definitions/meta.js.map +7 -0
- package/dist/events/definitions/operation.d.ts +11 -0
- package/dist/events/definitions/operation.d.ts.map +1 -0
- package/dist/events/definitions/operation.js +1 -0
- package/dist/events/definitions/operation.js.map +7 -0
- package/dist/events/definitions/server.d.ts +50 -0
- package/dist/events/definitions/server.d.ts.map +1 -0
- package/dist/events/definitions/server.js +1 -0
- package/dist/events/definitions/server.js.map +7 -0
- package/dist/events/definitions/ui.d.ts +52 -0
- package/dist/events/definitions/ui.d.ts.map +1 -0
- package/dist/events/definitions/ui.js +1 -0
- package/dist/events/definitions/ui.js.map +7 -0
- package/dist/events/index.d.ts +2 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +3 -1
- package/dist/events/index.js.map +2 -2
- package/dist/events/listeners.d.ts +2 -1
- package/dist/events/listeners.d.ts.map +1 -1
- package/dist/events/listeners.js.map +2 -2
- package/dist/events/{definitions.d.ts → old-definitions.d.ts} +35 -11
- package/dist/events/old-definitions.d.ts.map +1 -0
- package/dist/events/{definitions.js → old-definitions.js} +1 -1
- package/dist/events/old-definitions.js.map +7 -0
- package/dist/helpers/debounce.d.ts +28 -0
- package/dist/helpers/debounce.d.ts.map +1 -0
- package/dist/helpers/debounce.js +31 -0
- package/dist/helpers/debounce.js.map +7 -0
- package/dist/helpers/detect-changes-proxy.d.ts +47 -0
- package/dist/helpers/detect-changes-proxy.d.ts.map +1 -0
- package/dist/helpers/detect-changes-proxy.js +59 -0
- package/dist/helpers/detect-changes-proxy.js.map +7 -0
- package/dist/helpers/overrides-proxy.d.ts +17 -6
- package/dist/helpers/overrides-proxy.d.ts.map +1 -1
- package/dist/helpers/overrides-proxy.js +33 -18
- package/dist/helpers/overrides-proxy.js.map +3 -3
- package/dist/helpers/unpack-proxy.d.ts +6 -0
- package/dist/helpers/unpack-proxy.d.ts.map +1 -0
- package/dist/helpers/unpack-proxy.js +9 -0
- package/dist/helpers/unpack-proxy.js.map +7 -0
- package/dist/mutators/request.d.ts +1 -1
- package/dist/mutators/request.d.ts.map +1 -1
- package/dist/mutators/request.js.map +1 -1
- package/dist/navigation/get-navigation-options.d.ts +1 -1
- package/dist/navigation/get-navigation-options.d.ts.map +1 -1
- package/dist/navigation/get-navigation-options.js +66 -54
- package/dist/navigation/get-navigation-options.js.map +2 -2
- package/dist/navigation/helpers/get-tag.d.ts +7 -2
- package/dist/navigation/helpers/get-tag.d.ts.map +1 -1
- package/dist/navigation/helpers/get-tag.js +16 -2
- package/dist/navigation/helpers/get-tag.js.map +2 -2
- package/dist/navigation/helpers/traverse-description.d.ts +7 -2
- package/dist/navigation/helpers/traverse-description.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-description.js +24 -6
- package/dist/navigation/helpers/traverse-description.js.map +2 -2
- package/dist/navigation/helpers/traverse-document.d.ts +5 -2
- package/dist/navigation/helpers/traverse-document.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-document.js +53 -15
- package/dist/navigation/helpers/traverse-document.js.map +2 -2
- package/dist/navigation/helpers/traverse-paths.d.ts +9 -3
- package/dist/navigation/helpers/traverse-paths.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-paths.js +63 -9
- package/dist/navigation/helpers/traverse-paths.js.map +2 -2
- package/dist/navigation/helpers/traverse-schemas.d.ts +7 -8
- package/dist/navigation/helpers/traverse-schemas.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-schemas.js +35 -7
- package/dist/navigation/helpers/traverse-schemas.js.map +2 -2
- package/dist/navigation/helpers/traverse-tags.d.ts +8 -4
- package/dist/navigation/helpers/traverse-tags.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-tags.js +65 -17
- package/dist/navigation/helpers/traverse-tags.js.map +2 -2
- package/dist/navigation/helpers/traverse-webhooks.d.ts +9 -3
- package/dist/navigation/helpers/traverse-webhooks.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-webhooks.js +43 -17
- package/dist/navigation/helpers/traverse-webhooks.js.map +2 -2
- package/dist/navigation/types.d.ts +5 -24
- package/dist/navigation/types.d.ts.map +1 -1
- package/dist/persistence/index.d.ts +86 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +196 -0
- package/dist/persistence/index.js.map +7 -0
- package/dist/persistence/indexdb.d.ts +87 -0
- package/dist/persistence/indexdb.d.ts.map +1 -0
- package/dist/persistence/indexdb.js +125 -0
- package/dist/persistence/indexdb.js.map +7 -0
- package/dist/{plugins.d.ts → plugins/bundler/index.d.ts} +1 -1
- package/dist/plugins/bundler/index.d.ts.map +1 -0
- package/dist/{plugins.js → plugins/bundler/index.js} +2 -2
- package/dist/{plugins.js.map → plugins/bundler/index.js.map} +1 -1
- package/dist/plugins/client/index.d.ts +3 -0
- package/dist/plugins/client/index.d.ts.map +1 -0
- package/dist/plugins/client/index.js +5 -0
- package/dist/plugins/client/index.js.map +7 -0
- package/dist/plugins/client/persistence.d.ts +13 -0
- package/dist/plugins/client/persistence.d.ts.map +1 -0
- package/dist/plugins/client/persistence.js +57 -0
- package/dist/plugins/client/persistence.js.map +7 -0
- package/dist/schemas/extensions.d.ts +1 -0
- package/dist/schemas/extensions.d.ts.map +1 -1
- package/dist/schemas/extensions.js +1 -0
- package/dist/schemas/extensions.js.map +2 -2
- package/dist/schemas/inmemory-workspace.d.ts +73 -14
- package/dist/schemas/inmemory-workspace.d.ts.map +1 -1
- package/dist/schemas/inmemory-workspace.js +1 -9
- package/dist/schemas/inmemory-workspace.js.map +2 -2
- package/dist/schemas/navigation.d.ts +128 -1
- package/dist/schemas/navigation.d.ts.map +1 -1
- package/dist/schemas/navigation.js +20 -1
- package/dist/schemas/navigation.js.map +2 -2
- package/dist/schemas/reference-config/index.d.ts +233 -200
- package/dist/schemas/reference-config/index.d.ts.map +1 -1
- package/dist/schemas/reference-config/index.js.map +2 -2
- package/dist/schemas/reference-config/settings.d.ts +35 -3
- package/dist/schemas/reference-config/settings.d.ts.map +1 -1
- package/dist/schemas/reference-config/settings.js +1 -1
- package/dist/schemas/reference-config/settings.js.map +1 -1
- package/dist/schemas/v3.1/strict/openapi-document.d.ts +1165 -71
- package/dist/schemas/v3.1/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/openapi-document.js +16 -9
- package/dist/schemas/v3.1/strict/openapi-document.js.map +2 -2
- package/dist/schemas/v3.1/strict/parameter.d.ts +23 -1
- package/dist/schemas/v3.1/strict/parameter.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/parameter.js +5 -1
- package/dist/schemas/v3.1/strict/parameter.js.map +2 -2
- package/dist/schemas/v3.1/strict/ref-definitions.d.ts +2 -0
- package/dist/schemas/v3.1/strict/ref-definitions.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/ref-definitions.js +4 -1
- package/dist/schemas/v3.1/strict/ref-definitions.js.map +2 -2
- package/dist/schemas/v3.1/strict/schema.d.ts +2 -2
- package/dist/schemas/v3.1/strict/schema.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/schema.js +1 -1
- package/dist/schemas/v3.1/strict/schema.js.map +2 -2
- package/dist/schemas/workspace-specification/config.d.ts +35 -8
- package/dist/schemas/workspace-specification/config.d.ts.map +1 -1
- package/dist/schemas/workspace-specification/config.js.map +1 -1
- package/dist/schemas/workspace-specification/index.d.ts +38 -5
- package/dist/schemas/workspace-specification/index.d.ts.map +1 -1
- package/dist/schemas/workspace-specification/index.js.map +1 -1
- package/dist/schemas/workspace.d.ts +245 -17
- package/dist/schemas/workspace.d.ts.map +1 -1
- package/dist/schemas/workspace.js +3 -1
- package/dist/schemas/workspace.js.map +2 -2
- package/dist/server.d.ts +4 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +7 -6
- package/dist/server.js.map +2 -2
- package/dist/workspace-plugin.d.ts +49 -0
- package/dist/workspace-plugin.d.ts.map +1 -0
- package/dist/workspace-plugin.js +1 -0
- package/dist/workspace-plugin.js.map +7 -0
- package/package.json +22 -10
- package/dist/events/definitions.d.ts.map +0 -1
- package/dist/events/definitions.js.map +0 -7
- package/dist/plugins.d.ts.map +0 -1
package/dist/client.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { generateHash } from "@scalar/helpers/crypto/generate-hash";
|
|
1
2
|
import { measureAsync, measureSync } from "@scalar/helpers/testing/measure";
|
|
2
3
|
import { bundle } from "@scalar/json-magic/bundle";
|
|
3
4
|
import { fetchUrls } from "@scalar/json-magic/bundle/plugins/browser";
|
|
@@ -5,16 +6,18 @@ import { apply, diff, merge } from "@scalar/json-magic/diff";
|
|
|
5
6
|
import { createMagicProxy, getRaw } from "@scalar/json-magic/magic-proxy";
|
|
6
7
|
import { upgrade } from "@scalar/openapi-upgrader";
|
|
7
8
|
import { Value } from "@scalar/typebox/value";
|
|
8
|
-
import { reactive } from "vue";
|
|
9
|
+
import { reactive, toRaw } from "vue";
|
|
9
10
|
import YAML from "yaml";
|
|
10
11
|
import { applySelectiveUpdates } from "./helpers/apply-selective-updates.js";
|
|
11
12
|
import { deepClone } from "./helpers/deep-clone.js";
|
|
13
|
+
import { createDetectChangesProxy } from "./helpers/detect-changes-proxy.js";
|
|
12
14
|
import { isObject, safeAssign } from "./helpers/general.js";
|
|
13
15
|
import { getValueByPath } from "./helpers/json-path-utils.js";
|
|
14
16
|
import { mergeObjects } from "./helpers/merge-object.js";
|
|
15
|
-
import { createOverridesProxy } from "./helpers/overrides-proxy.js";
|
|
17
|
+
import { createOverridesProxy, unpackOverridesProxy } from "./helpers/overrides-proxy.js";
|
|
18
|
+
import { unpackProxyObject } from "./helpers/unpack-proxy.js";
|
|
16
19
|
import { createNavigation } from "./navigation/index.js";
|
|
17
|
-
import { externalValueResolver, loadingStatus, refsEverywhere, restoreOriginalRefs } from "./plugins.js";
|
|
20
|
+
import { externalValueResolver, loadingStatus, refsEverywhere, restoreOriginalRefs } from "./plugins/bundler/index.js";
|
|
18
21
|
import { getServersFromDocument } from "./preprocessing/server.js";
|
|
19
22
|
import { extensions } from "./schemas/extensions.js";
|
|
20
23
|
import { InMemoryWorkspaceSchema } from "./schemas/inmemory-workspace.js";
|
|
@@ -26,14 +29,16 @@ import {
|
|
|
26
29
|
const defaultConfig = {
|
|
27
30
|
"x-scalar-reference-config": defaultReferenceConfig
|
|
28
31
|
};
|
|
29
|
-
|
|
32
|
+
function loadDocument(workspaceDocument) {
|
|
30
33
|
if ("url" in workspaceDocument) {
|
|
31
34
|
return fetchUrls({ fetch: workspaceDocument.fetch }).exec(workspaceDocument.url);
|
|
32
35
|
}
|
|
33
|
-
return {
|
|
36
|
+
return Promise.resolve({
|
|
34
37
|
ok: true,
|
|
35
|
-
data: workspaceDocument.document
|
|
36
|
-
|
|
38
|
+
data: workspaceDocument.document,
|
|
39
|
+
// string version of the raw document for hashing purposes
|
|
40
|
+
raw: JSON.stringify(workspaceDocument.document)
|
|
41
|
+
});
|
|
37
42
|
}
|
|
38
43
|
const getDocumentSource = (input) => {
|
|
39
44
|
if ("url" in input) {
|
|
@@ -42,37 +47,176 @@ const getDocumentSource = (input) => {
|
|
|
42
47
|
return void 0;
|
|
43
48
|
};
|
|
44
49
|
const createWorkspaceStore = (workspaceProps) => {
|
|
45
|
-
const originalDocuments = {};
|
|
46
|
-
const intermediateDocuments = {};
|
|
47
|
-
const documentConfigs = {};
|
|
48
|
-
const overrides = {};
|
|
49
|
-
const documentMeta = {};
|
|
50
50
|
const extraDocumentConfigurations = {};
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
const fireWorkspaceChange = (event) => {
|
|
52
|
+
workspaceProps?.plugins?.forEach((plugin) => plugin.hooks?.onWorkspaceStateChanges?.(event));
|
|
53
|
+
};
|
|
54
|
+
const workspace = reactive(
|
|
55
|
+
createDetectChangesProxy(
|
|
56
|
+
{
|
|
57
|
+
...workspaceProps?.meta,
|
|
58
|
+
documents: {},
|
|
59
|
+
/**
|
|
60
|
+
* Returns the currently active document from the workspace.
|
|
61
|
+
* The active document is determined by the 'x-scalar-active-document' metadata field,
|
|
62
|
+
* falling back to the first document in the workspace if no active document is specified.
|
|
63
|
+
*
|
|
64
|
+
* @returns The active document or undefined if no document is found
|
|
65
|
+
*/
|
|
66
|
+
get activeDocument() {
|
|
67
|
+
return workspace.documents[getActiveDocumentName()];
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
hooks: {
|
|
72
|
+
onAfterChange(path) {
|
|
73
|
+
const type = path[0];
|
|
74
|
+
if (type === "documents") {
|
|
75
|
+
if (path.length < 2) {
|
|
76
|
+
console.log("[WARN]: Overriding entire documents object is not supported");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const documentName = path[1];
|
|
80
|
+
const event2 = {
|
|
81
|
+
type: "documents",
|
|
82
|
+
documentName,
|
|
83
|
+
value: unpackProxyObject(
|
|
84
|
+
workspace.documents[documentName] ?? {
|
|
85
|
+
openapi: "3.1.0",
|
|
86
|
+
info: { title: "", version: "" },
|
|
87
|
+
"x-scalar-original-document-hash": ""
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
};
|
|
91
|
+
fireWorkspaceChange(event2);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (type === "activeDocument") {
|
|
95
|
+
const documentName = getActiveDocumentName();
|
|
96
|
+
const event2 = {
|
|
97
|
+
type: "documents",
|
|
98
|
+
documentName,
|
|
99
|
+
value: unpackProxyObject(
|
|
100
|
+
workspace.documents[documentName] ?? {
|
|
101
|
+
openapi: "3.1.0",
|
|
102
|
+
info: { title: "", version: "" },
|
|
103
|
+
"x-scalar-original-document-hash": ""
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
};
|
|
107
|
+
fireWorkspaceChange(event2);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const { activeDocument: _a, documents: _d, ...meta } = workspace;
|
|
111
|
+
const event = {
|
|
112
|
+
type: "meta",
|
|
113
|
+
value: unpackProxyObject(meta)
|
|
114
|
+
};
|
|
115
|
+
fireWorkspaceChange(event);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
const { originalDocuments, intermediateDocuments, overrides, documentConfigs } = createDetectChangesProxy(
|
|
123
|
+
{
|
|
124
|
+
/**
|
|
125
|
+
* Holds the original, unmodified documents as they were initially loaded into the workspace.
|
|
126
|
+
* These documents are stored in their raw form—prior to any reactive wrapping, dereferencing, or bundling.
|
|
127
|
+
* This map preserves the pristine structure of each document, using deep clones to ensure that
|
|
128
|
+
* subsequent mutations in the workspace do not affect the originals.
|
|
129
|
+
* The originals are retained so that we can restore, compare, or sync with the remote registry as needed.
|
|
130
|
+
*/
|
|
131
|
+
originalDocuments: {},
|
|
132
|
+
/**
|
|
133
|
+
* Stores the intermediate state of documents after local edits but before syncing with the remote registry.
|
|
134
|
+
*
|
|
135
|
+
* This map acts as a local "saved" version of the document, reflecting the user's changes after they hit "save".
|
|
136
|
+
* The `originalDocuments` map, by contrast, always mirrors the document as it exists in the remote registry.
|
|
137
|
+
*
|
|
138
|
+
* Use this map to stage local changes that are ready to be propagated back to the remote registry.
|
|
139
|
+
* This separation allows us to distinguish between:
|
|
140
|
+
* - The last known remote version (`originalDocuments`)
|
|
141
|
+
* - The latest locally saved version (`intermediateDocuments`)
|
|
142
|
+
* - The current in-memory (possibly unsaved) workspace document (`workspace.documents`)
|
|
143
|
+
*/
|
|
144
|
+
intermediateDocuments: {},
|
|
145
|
+
/**
|
|
146
|
+
* A map of document configurations keyed by document name.
|
|
147
|
+
* This stores the configuration options for each document in the workspace,
|
|
148
|
+
* allowing for document-specific settings like navigation options, appearance,
|
|
149
|
+
* and other reference configuration.
|
|
150
|
+
*/
|
|
151
|
+
documentConfigs: {},
|
|
152
|
+
/**
|
|
153
|
+
* Stores per-document overrides for OpenAPI documents.
|
|
154
|
+
* This object is used to override specific fields of a document
|
|
155
|
+
* when you cannot (or should not) modify the source document directly.
|
|
156
|
+
* For example, this enables UI-driven or temporary changes to be applied
|
|
157
|
+
* on top of the original document, without mutating the source.
|
|
158
|
+
* The key is the document name, and the value is a deep partial
|
|
159
|
+
* OpenAPI document representing the overridden fields.
|
|
160
|
+
*/
|
|
161
|
+
overrides: {}
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
hooks: {
|
|
165
|
+
onAfterChange(path) {
|
|
166
|
+
const type = path[0];
|
|
167
|
+
if (!type) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (path.length < 2) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const documentName = path[1];
|
|
174
|
+
if (type === "originalDocuments") {
|
|
175
|
+
const event = {
|
|
176
|
+
type,
|
|
177
|
+
documentName,
|
|
178
|
+
value: unpackProxyObject(originalDocuments[documentName] ?? {})
|
|
179
|
+
};
|
|
180
|
+
fireWorkspaceChange(event);
|
|
181
|
+
}
|
|
182
|
+
if (type === "intermediateDocuments") {
|
|
183
|
+
const event = {
|
|
184
|
+
type,
|
|
185
|
+
documentName,
|
|
186
|
+
value: unpackProxyObject(intermediateDocuments[documentName] ?? {})
|
|
187
|
+
};
|
|
188
|
+
fireWorkspaceChange(event);
|
|
189
|
+
}
|
|
190
|
+
if (type === "documentConfigs") {
|
|
191
|
+
const event = {
|
|
192
|
+
type,
|
|
193
|
+
documentName,
|
|
194
|
+
value: unpackProxyObject(documentConfigs[documentName] ?? {})
|
|
195
|
+
};
|
|
196
|
+
fireWorkspaceChange(event);
|
|
197
|
+
}
|
|
198
|
+
if (type === "overrides") {
|
|
199
|
+
const event = {
|
|
200
|
+
type,
|
|
201
|
+
documentName,
|
|
202
|
+
value: unpackProxyObject(overrides[documentName] ?? {})
|
|
203
|
+
};
|
|
204
|
+
fireWorkspaceChange(event);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
64
208
|
}
|
|
65
|
-
|
|
209
|
+
);
|
|
66
210
|
function getActiveDocumentName() {
|
|
67
211
|
return workspace[extensions.workspace.activeDocument] ?? Object.keys(workspace.documents)[0] ?? "";
|
|
68
212
|
}
|
|
69
|
-
function exportDocument(documentName, format) {
|
|
213
|
+
function exportDocument(documentName, format, minify) {
|
|
70
214
|
const intermediateDocument = intermediateDocuments[documentName];
|
|
71
215
|
if (!intermediateDocument) {
|
|
72
216
|
return;
|
|
73
217
|
}
|
|
74
218
|
if (format === "json") {
|
|
75
|
-
return JSON.stringify(intermediateDocument);
|
|
219
|
+
return minify ? JSON.stringify(intermediateDocument) : JSON.stringify(intermediateDocument, null, 2);
|
|
76
220
|
}
|
|
77
221
|
return YAML.stringify(intermediateDocument);
|
|
78
222
|
}
|
|
@@ -106,20 +250,27 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
106
250
|
};
|
|
107
251
|
async function addInMemoryDocument(input) {
|
|
108
252
|
const { name, meta } = input;
|
|
109
|
-
const
|
|
110
|
-
const inputDocument = measureSync("upgrade", () => upgrade(cloned, "3.1"));
|
|
253
|
+
const clonedRawInputDocument = measureSync("deepClone", () => deepClone(input.document));
|
|
111
254
|
measureSync("initialize", () => {
|
|
112
255
|
if (input.initialize !== false) {
|
|
113
|
-
originalDocuments[name] = deepClone(
|
|
114
|
-
intermediateDocuments[name] = deepClone(
|
|
256
|
+
originalDocuments[name] = deepClone(clonedRawInputDocument);
|
|
257
|
+
intermediateDocuments[name] = deepClone(clonedRawInputDocument);
|
|
115
258
|
documentConfigs[name] = input.config ?? {};
|
|
116
259
|
overrides[name] = input.overrides ?? {};
|
|
117
|
-
documentMeta[name] = { documentSource: input.documentSource };
|
|
118
260
|
extraDocumentConfigurations[name] = { fetch: input.fetch };
|
|
119
261
|
}
|
|
120
262
|
});
|
|
121
|
-
const
|
|
122
|
-
strictDocument
|
|
263
|
+
const inputDocument = measureSync("upgrade", () => upgrade(deepClone(clonedRawInputDocument), "3.1"));
|
|
264
|
+
const strictDocument = createMagicProxy(
|
|
265
|
+
{
|
|
266
|
+
...inputDocument,
|
|
267
|
+
...meta,
|
|
268
|
+
"x-original-oas-version": originalDocuments[name]?.openapi ?? originalDocuments[name]?.swagger,
|
|
269
|
+
"x-scalar-original-document-hash": input.documentHash,
|
|
270
|
+
"x-scalar-original-source-url": input.documentSource
|
|
271
|
+
},
|
|
272
|
+
{ showInternal: true }
|
|
273
|
+
);
|
|
123
274
|
if (strictDocument[extensions.document.navigation] === void 0) {
|
|
124
275
|
await measureAsync(
|
|
125
276
|
"bundle",
|
|
@@ -133,7 +284,7 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
133
284
|
refsEverywhere()
|
|
134
285
|
],
|
|
135
286
|
urlMap: true,
|
|
136
|
-
origin:
|
|
287
|
+
origin: input.documentSource
|
|
137
288
|
// use the document origin (if provided) as the base URL for resolution
|
|
138
289
|
})
|
|
139
290
|
);
|
|
@@ -141,7 +292,7 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
141
292
|
"coerceValue",
|
|
142
293
|
() => coerceValue(OpenAPIDocumentSchemaStrict, deepClone(strictDocument))
|
|
143
294
|
);
|
|
144
|
-
|
|
295
|
+
measureSync("mergeObjects", () => mergeObjects(strictDocument, coerced));
|
|
145
296
|
}
|
|
146
297
|
const isValid = Value.Check(OpenAPIDocumentSchemaStrict, strictDocument);
|
|
147
298
|
if (!isValid) {
|
|
@@ -157,17 +308,16 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
157
308
|
);
|
|
158
309
|
}
|
|
159
310
|
if (strictDocument[extensions.document.navigation] === void 0) {
|
|
160
|
-
const navigation = createNavigation(strictDocument, input.config);
|
|
161
|
-
strictDocument[extensions.document.navigation] = navigation
|
|
311
|
+
const navigation = createNavigation(name, strictDocument, input.config);
|
|
312
|
+
strictDocument[extensions.document.navigation] = navigation;
|
|
162
313
|
processDocument(getRaw(strictDocument), {
|
|
163
314
|
...documentConfigs[name] ?? {},
|
|
164
315
|
documentSource: input.documentSource
|
|
165
316
|
});
|
|
166
317
|
}
|
|
167
|
-
workspace.documents[name] = createOverridesProxy(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
);
|
|
318
|
+
workspace.documents[name] = createOverridesProxy(createMagicProxy(getRaw(strictDocument)), {
|
|
319
|
+
overrides: overrides[name]
|
|
320
|
+
});
|
|
171
321
|
}
|
|
172
322
|
async function addDocument(input) {
|
|
173
323
|
const { name, meta } = input;
|
|
@@ -184,7 +334,8 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
184
334
|
info: {
|
|
185
335
|
title: `Document '${name}' could not be loaded`,
|
|
186
336
|
version: "unknown"
|
|
187
|
-
}
|
|
337
|
+
},
|
|
338
|
+
"x-scalar-original-document-hash": "not-a-hash"
|
|
188
339
|
};
|
|
189
340
|
return;
|
|
190
341
|
}
|
|
@@ -196,14 +347,16 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
196
347
|
info: {
|
|
197
348
|
title: `Document '${name}' could not be loaded`,
|
|
198
349
|
version: "unknown"
|
|
199
|
-
}
|
|
350
|
+
},
|
|
351
|
+
"x-scalar-original-document-hash": "not-a-hash"
|
|
200
352
|
};
|
|
201
353
|
return;
|
|
202
354
|
}
|
|
203
355
|
await addInMemoryDocument({
|
|
204
356
|
...input,
|
|
205
357
|
document: resolve.data,
|
|
206
|
-
documentSource: getDocumentSource(input)
|
|
358
|
+
documentSource: getDocumentSource(input),
|
|
359
|
+
documentHash: await generateHash(resolve.raw)
|
|
207
360
|
});
|
|
208
361
|
});
|
|
209
362
|
}
|
|
@@ -240,6 +393,8 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
240
393
|
name: documentName,
|
|
241
394
|
document: input,
|
|
242
395
|
// Preserve the current metadata
|
|
396
|
+
documentSource: currentDocument["x-scalar-original-source-url"],
|
|
397
|
+
documentHash: currentDocument["x-scalar-original-document-hash"],
|
|
243
398
|
meta: {
|
|
244
399
|
"x-scalar-active-auth": currentDocument["x-scalar-active-auth"],
|
|
245
400
|
"x-scalar-active-server": currentDocument["x-scalar-active-server"]
|
|
@@ -247,14 +402,14 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
247
402
|
initialize: false
|
|
248
403
|
});
|
|
249
404
|
},
|
|
250
|
-
resolve:
|
|
405
|
+
resolve: (path) => {
|
|
251
406
|
const activeDocument = workspace.activeDocument;
|
|
252
407
|
const target = getValueByPath(activeDocument, path);
|
|
253
408
|
if (!isObject(target)) {
|
|
254
409
|
console.error(
|
|
255
410
|
`Invalid path provided for resolution. Path: [${path.join(", ")}]. Found value of type: ${typeof target}. Expected an object.`
|
|
256
411
|
);
|
|
257
|
-
return;
|
|
412
|
+
return Promise.resolve();
|
|
258
413
|
}
|
|
259
414
|
return bundle(target, {
|
|
260
415
|
root: activeDocument,
|
|
@@ -269,7 +424,7 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
269
424
|
return getDocumentConfiguration(getActiveDocumentName());
|
|
270
425
|
},
|
|
271
426
|
exportDocument,
|
|
272
|
-
exportActiveDocument: (format) => exportDocument(getActiveDocumentName(), format),
|
|
427
|
+
exportActiveDocument: (format, minify) => exportDocument(getActiveDocumentName(), format, minify),
|
|
273
428
|
saveDocument,
|
|
274
429
|
async revertDocumentChanges(documentName) {
|
|
275
430
|
const workspaceDocument = workspace.documents[documentName];
|
|
@@ -280,6 +435,8 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
280
435
|
await addInMemoryDocument({
|
|
281
436
|
name: documentName,
|
|
282
437
|
document: intermediate,
|
|
438
|
+
documentSource: workspaceDocument["x-scalar-original-source-url"],
|
|
439
|
+
documentHash: workspaceDocument["x-scalar-original-document-hash"],
|
|
283
440
|
initialize: false
|
|
284
441
|
});
|
|
285
442
|
},
|
|
@@ -287,14 +444,14 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
287
444
|
console.warn(`Commit operation for document '${documentName}' is not implemented yet.`);
|
|
288
445
|
},
|
|
289
446
|
exportWorkspace() {
|
|
290
|
-
return
|
|
447
|
+
return {
|
|
291
448
|
documents: {
|
|
292
449
|
...Object.fromEntries(
|
|
293
450
|
Object.entries(workspace.documents).map(([name, doc]) => [
|
|
294
451
|
name,
|
|
295
452
|
// Extract the raw document data for export, removing any Vue reactivity wrappers.
|
|
296
453
|
// When importing, the document can be wrapped again in a magic proxy.
|
|
297
|
-
getRaw(doc)
|
|
454
|
+
toRaw(getRaw(unpackOverridesProxy(doc)))
|
|
298
455
|
])
|
|
299
456
|
)
|
|
300
457
|
},
|
|
@@ -302,18 +459,19 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
302
459
|
documentConfigs,
|
|
303
460
|
originalDocuments,
|
|
304
461
|
intermediateDocuments,
|
|
305
|
-
overrides
|
|
306
|
-
|
|
307
|
-
});
|
|
462
|
+
overrides
|
|
463
|
+
};
|
|
308
464
|
},
|
|
309
465
|
loadWorkspace(input) {
|
|
310
|
-
const result = coerceValue(InMemoryWorkspaceSchema,
|
|
466
|
+
const result = coerceValue(InMemoryWorkspaceSchema, input);
|
|
311
467
|
safeAssign(
|
|
312
468
|
workspace.documents,
|
|
313
469
|
Object.fromEntries(
|
|
314
470
|
Object.entries(result.documents).map(([name, doc]) => [
|
|
315
471
|
name,
|
|
316
|
-
createOverridesProxy(createMagicProxy(doc),
|
|
472
|
+
createOverridesProxy(createMagicProxy(doc), {
|
|
473
|
+
overrides: result.overrides[name]
|
|
474
|
+
})
|
|
317
475
|
])
|
|
318
476
|
)
|
|
319
477
|
);
|
|
@@ -322,7 +480,6 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
322
480
|
safeAssign(documentConfigs, result.documentConfigs);
|
|
323
481
|
safeAssign(overrides, result.overrides);
|
|
324
482
|
safeAssign(workspace, result.meta);
|
|
325
|
-
safeAssign(documentMeta, result.documentMeta);
|
|
326
483
|
},
|
|
327
484
|
importWorkspaceFromSpecification: (specification) => {
|
|
328
485
|
const { documents, overrides: overrides2, info: _info, workspace: _workspaceVersion, ...meta } = specification;
|
|
@@ -333,37 +490,82 @@ const createWorkspaceStore = (workspaceProps) => {
|
|
|
333
490
|
)
|
|
334
491
|
);
|
|
335
492
|
},
|
|
336
|
-
rebaseDocument: (
|
|
337
|
-
const
|
|
338
|
-
const originalDocument = originalDocuments[
|
|
339
|
-
const intermediateDocument = intermediateDocuments[
|
|
340
|
-
const activeDocument = workspace.documents[
|
|
493
|
+
rebaseDocument: async (input) => {
|
|
494
|
+
const { name } = input;
|
|
495
|
+
const originalDocument = originalDocuments[name];
|
|
496
|
+
const intermediateDocument = intermediateDocuments[name];
|
|
497
|
+
const activeDocument = workspace.documents[name] ? toRaw(getRaw(unpackOverridesProxy(workspace.documents[name]))) : void 0;
|
|
341
498
|
if (!originalDocument || !intermediateDocument || !activeDocument) {
|
|
342
|
-
return
|
|
499
|
+
return {
|
|
500
|
+
ok: false,
|
|
501
|
+
type: "CORRUPTED_STATE",
|
|
502
|
+
message: `Cannot rebase document '${name}': missing original, intermediate, or active document state`
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
const resolve = await measureAsync(
|
|
506
|
+
"loadDocument",
|
|
507
|
+
async () => await loadDocument({ ...input, fetch: input.fetch ?? workspaceProps?.fetch })
|
|
508
|
+
);
|
|
509
|
+
if (!resolve.ok || !isObject(resolve.data)) {
|
|
510
|
+
return {
|
|
511
|
+
ok: false,
|
|
512
|
+
type: "FETCH_FAILED",
|
|
513
|
+
message: `Failed to fetch document '${name}': request was not successful or returned invalid data`
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
const newHash = await generateHash(resolve.raw);
|
|
517
|
+
if (activeDocument["x-scalar-original-document-hash"] === newHash) {
|
|
518
|
+
return {
|
|
519
|
+
ok: false,
|
|
520
|
+
type: "NO_CHANGES_DETECTED",
|
|
521
|
+
message: `No changes detected for document '${name}': document hash matches the active document`
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const newDocumentOrigin = resolve.data;
|
|
525
|
+
documentConfigs[name] = input.config ?? {};
|
|
526
|
+
overrides[name] = input.overrides ?? {};
|
|
527
|
+
extraDocumentConfigurations[name] = { fetch: input.fetch };
|
|
528
|
+
const changelogAA = diff(originalDocument, newDocumentOrigin);
|
|
529
|
+
if (changelogAA.length === 0) {
|
|
530
|
+
return {
|
|
531
|
+
ok: false,
|
|
532
|
+
type: "NO_CHANGES_DETECTED",
|
|
533
|
+
message: `No changes detected for document '${name}' after fetching the latest version.`
|
|
534
|
+
};
|
|
343
535
|
}
|
|
344
|
-
const changelogAA = diff(originalDocument, newOrigin);
|
|
345
536
|
const changelogAB = diff(originalDocument, intermediateDocument);
|
|
346
537
|
const changesA = merge(changelogAA, changelogAB);
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
538
|
+
return {
|
|
539
|
+
ok: true,
|
|
540
|
+
conflicts: changesA.conflicts,
|
|
541
|
+
applyChanges: async (resolvedConflicts) => {
|
|
542
|
+
const changesetA = changesA.diffs.concat(resolvedConflicts);
|
|
543
|
+
const newIntermediateDocument = apply(deepClone(originalDocument), changesetA);
|
|
544
|
+
intermediateDocuments[name] = newIntermediateDocument;
|
|
545
|
+
originalDocuments[name] = newDocumentOrigin;
|
|
546
|
+
const changelogBA = diff(intermediateDocument, newIntermediateDocument);
|
|
547
|
+
const changelogBB = diff(intermediateDocument, activeDocument);
|
|
548
|
+
const changesB = merge(changelogBA, changelogBB);
|
|
549
|
+
const changesetB = changesB.diffs.concat(changesB.conflicts.flatMap((it) => it[0]));
|
|
550
|
+
const newActiveDocument = coerceValue(
|
|
551
|
+
OpenAPIDocumentSchemaStrict,
|
|
552
|
+
apply(deepClone(newIntermediateDocument), changesetB)
|
|
553
|
+
);
|
|
554
|
+
await addInMemoryDocument({
|
|
555
|
+
...input,
|
|
556
|
+
document: {
|
|
557
|
+
...newActiveDocument,
|
|
558
|
+
// force regeneration of navigation
|
|
559
|
+
// when we are rebasing, we want to ensure that the navigation is always up to date
|
|
560
|
+
[extensions.document.navigation]: void 0
|
|
561
|
+
},
|
|
562
|
+
documentSource: getDocumentSource(input),
|
|
563
|
+
// Update the original document hash
|
|
564
|
+
documentHash: await generateHash(resolve.raw),
|
|
565
|
+
initialize: false
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
};
|
|
367
569
|
}
|
|
368
570
|
};
|
|
369
571
|
};
|