@scalar/workspace-store 0.1.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/.turbo/turbo-build.log +10 -0
- package/CHANGELOG.md +13 -0
- package/README.md +199 -0
- package/dist/create-server-workspace-store.d.ts +151 -0
- package/dist/create-server-workspace-store.d.ts.map +1 -0
- package/dist/create-server-workspace-store.js +199 -0
- package/dist/create-server-workspace-store.js.map +7 -0
- package/dist/create-workspace-store.d.ts +19773 -0
- package/dist/create-workspace-store.d.ts.map +1 -0
- package/dist/create-workspace-store.js +186 -0
- package/dist/create-workspace-store.js.map +7 -0
- package/dist/helpers/general.d.ts +88 -0
- package/dist/helpers/general.d.ts.map +1 -0
- package/dist/helpers/general.js +38 -0
- package/dist/helpers/general.js.map +7 -0
- package/dist/helpers/json-path-utils.d.ts +23 -0
- package/dist/helpers/json-path-utils.d.ts.map +1 -0
- package/dist/helpers/json-path-utils.js +16 -0
- package/dist/helpers/json-path-utils.js.map +7 -0
- package/dist/helpers/proxy.d.ts +63 -0
- package/dist/helpers/proxy.d.ts.map +1 -0
- package/dist/helpers/proxy.js +100 -0
- package/dist/helpers/proxy.js.map +7 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +7 -0
- package/dist/schemas/callback.d.ts +1095 -0
- package/dist/schemas/callback.d.ts.map +1 -0
- package/dist/schemas/callback.js +11 -0
- package/dist/schemas/callback.js.map +7 -0
- package/dist/schemas/components.d.ts +2461 -0
- package/dist/schemas/components.d.ts.map +1 -0
- package/dist/schemas/components.js +38 -0
- package/dist/schemas/components.js.map +7 -0
- package/dist/schemas/contact.d.ts +10 -0
- package/dist/schemas/contact.d.ts.map +1 -0
- package/dist/schemas/contact.js +13 -0
- package/dist/schemas/contact.js.map +7 -0
- package/dist/schemas/discriminator.d.ts +12 -0
- package/dist/schemas/discriminator.d.ts.map +1 -0
- package/dist/schemas/discriminator.js +11 -0
- package/dist/schemas/discriminator.js.map +7 -0
- package/dist/schemas/encoding.d.ts +23 -0
- package/dist/schemas/encoding.d.ts.map +1 -0
- package/dist/schemas/encoding.js +13 -0
- package/dist/schemas/encoding.js.map +7 -0
- package/dist/schemas/example.d.ts +16 -0
- package/dist/schemas/example.d.ts.map +1 -0
- package/dist/schemas/example.js +15 -0
- package/dist/schemas/example.js.map +7 -0
- package/dist/schemas/external-documentation.d.ts +8 -0
- package/dist/schemas/external-documentation.d.ts.map +1 -0
- package/dist/schemas/external-documentation.js +11 -0
- package/dist/schemas/external-documentation.js.map +7 -0
- package/dist/schemas/header.d.ts +18 -0
- package/dist/schemas/header.d.ts.map +1 -0
- package/dist/schemas/header.js +13 -0
- package/dist/schemas/header.js.map +7 -0
- package/dist/schemas/info.d.ts +28 -0
- package/dist/schemas/info.d.ts.map +1 -0
- package/dist/schemas/info.js +23 -0
- package/dist/schemas/info.js.map +7 -0
- package/dist/schemas/license.d.ts +10 -0
- package/dist/schemas/license.d.ts.map +1 -0
- package/dist/schemas/license.js +13 -0
- package/dist/schemas/license.js.map +7 -0
- package/dist/schemas/link.d.ts +30 -0
- package/dist/schemas/link.d.ts.map +1 -0
- package/dist/schemas/link.js +20 -0
- package/dist/schemas/link.js.map +7 -0
- package/dist/schemas/media-type.d.ts +55 -0
- package/dist/schemas/media-type.d.ts.map +1 -0
- package/dist/schemas/media-type.js +19 -0
- package/dist/schemas/media-type.js.map +7 -0
- package/dist/schemas/oauth-flow.d.ts +12 -0
- package/dist/schemas/oauth-flow.d.ts.map +1 -0
- package/dist/schemas/oauth-flow.js +15 -0
- package/dist/schemas/oauth-flow.js.map +7 -0
- package/dist/schemas/oauthflows.d.ts +34 -0
- package/dist/schemas/oauthflows.d.ts.map +1 -0
- package/dist/schemas/oauthflows.js +16 -0
- package/dist/schemas/oauthflows.js.map +7 -0
- package/dist/schemas/openapi-document.d.ts +4683 -0
- package/dist/schemas/openapi-document.d.ts.map +1 -0
- package/dist/schemas/openapi-document.js +35 -0
- package/dist/schemas/openapi-document.js.map +7 -0
- package/dist/schemas/operation-without-callback.d.ts +190 -0
- package/dist/schemas/operation-without-callback.d.ts.map +1 -0
- package/dist/schemas/operation-without-callback.js +39 -0
- package/dist/schemas/operation-without-callback.js.map +7 -0
- package/dist/schemas/parameter.d.ts +25 -0
- package/dist/schemas/parameter.d.ts.map +1 -0
- package/dist/schemas/parameter.js +22 -0
- package/dist/schemas/parameter.js.map +7 -0
- package/dist/schemas/path-item.d.ts +1106 -0
- package/dist/schemas/path-item.d.ts.map +1 -0
- package/dist/schemas/path-item.js +37 -0
- package/dist/schemas/path-item.js.map +7 -0
- package/dist/schemas/paths.d.ts +1093 -0
- package/dist/schemas/paths.d.ts.map +1 -0
- package/dist/schemas/paths.js +11 -0
- package/dist/schemas/paths.js.map +7 -0
- package/dist/schemas/reference.d.ts +17 -0
- package/dist/schemas/reference.d.ts.map +1 -0
- package/dist/schemas/reference.js +15 -0
- package/dist/schemas/reference.js.map +7 -0
- package/dist/schemas/request-body.d.ts +54 -0
- package/dist/schemas/request-body.d.ts.map +1 -0
- package/dist/schemas/request-body.js +14 -0
- package/dist/schemas/request-body.js.map +7 -0
- package/dist/schemas/response.d.ts +84 -0
- package/dist/schemas/response.d.ts.map +1 -0
- package/dist/schemas/response.js +19 -0
- package/dist/schemas/response.js.map +7 -0
- package/dist/schemas/responses.d.ts +94 -0
- package/dist/schemas/responses.d.ts.map +1 -0
- package/dist/schemas/responses.js +8 -0
- package/dist/schemas/responses.js.map +7 -0
- package/dist/schemas/schema.d.ts +34 -0
- package/dist/schemas/schema.d.ts.map +1 -0
- package/dist/schemas/schema.js +22 -0
- package/dist/schemas/schema.js.map +7 -0
- package/dist/schemas/security-requirement.d.ts +11 -0
- package/dist/schemas/security-requirement.d.ts.map +1 -0
- package/dist/schemas/security-requirement.js +10 -0
- package/dist/schemas/security-requirement.js.map +7 -0
- package/dist/schemas/security-scheme.d.ts +137 -0
- package/dist/schemas/security-scheme.d.ts.map +1 -0
- package/dist/schemas/security-scheme.js +56 -0
- package/dist/schemas/security-scheme.js.map +7 -0
- package/dist/schemas/server-variable.d.ts +10 -0
- package/dist/schemas/server-variable.d.ts.map +1 -0
- package/dist/schemas/server-variable.js +13 -0
- package/dist/schemas/server-variable.js.map +7 -0
- package/dist/schemas/server-workspace.d.ts +14043 -0
- package/dist/schemas/server-workspace.d.ts.map +1 -0
- package/dist/schemas/server-workspace.js +29 -0
- package/dist/schemas/server-workspace.js.map +7 -0
- package/dist/schemas/server.d.ts +14 -0
- package/dist/schemas/server.d.ts.map +1 -0
- package/dist/schemas/server.js +14 -0
- package/dist/schemas/server.js.map +7 -0
- package/dist/schemas/tag.d.ts +13 -0
- package/dist/schemas/tag.d.ts.map +1 -0
- package/dist/schemas/tag.js +14 -0
- package/dist/schemas/tag.js.map +7 -0
- package/dist/schemas/xml.d.ts +18 -0
- package/dist/schemas/xml.d.ts.map +1 -0
- package/dist/schemas/xml.js +17 -0
- package/dist/schemas/xml.js.map +7 -0
- package/esbuild.ts +6 -0
- package/package.json +54 -0
- package/src/create-server-workspace-store.test.ts +429 -0
- package/src/create-server-workspace-store.ts +339 -0
- package/src/create-workspace-store.test.ts +488 -0
- package/src/create-workspace-store.ts +282 -0
- package/src/helpers/general.ts +115 -0
- package/src/helpers/json-path-utils.test.ts +13 -0
- package/src/helpers/json-path-utils.ts +38 -0
- package/src/helpers/proxy.test.ts +61 -0
- package/src/helpers/proxy.ts +213 -0
- package/src/index.ts +8 -0
- package/src/schemas/callback.ts +13 -0
- package/src/schemas/components.ts +36 -0
- package/src/schemas/contact.ts +11 -0
- package/src/schemas/discriminator.ts +13 -0
- package/src/schemas/encoding.ts +17 -0
- package/src/schemas/example.ts +17 -0
- package/src/schemas/external-documentation.ts +9 -0
- package/src/schemas/header.ts +19 -0
- package/src/schemas/info.ts +23 -0
- package/src/schemas/license.ts +11 -0
- package/src/schemas/link.ts +24 -0
- package/src/schemas/media-type.ts +21 -0
- package/src/schemas/oauth-flow.ts +13 -0
- package/src/schemas/oauthflows.ts +16 -0
- package/src/schemas/openapi-document.ts +34 -0
- package/src/schemas/operation-without-callback.ts +37 -0
- package/src/schemas/parameter.ts +26 -0
- package/src/schemas/path-item.ts +35 -0
- package/src/schemas/paths.ts +11 -0
- package/src/schemas/reference.ts +18 -0
- package/src/schemas/request-body.ts +12 -0
- package/src/schemas/response.ts +16 -0
- package/src/schemas/responses.ts +14 -0
- package/src/schemas/schema.ts +26 -0
- package/src/schemas/security-requirement.ts +16 -0
- package/src/schemas/security-scheme.ts +58 -0
- package/src/schemas/server-variable.ts +11 -0
- package/src/schemas/server-workspace.ts +36 -0
- package/src/schemas/server.ts +12 -0
- package/src/schemas/tag.ts +12 -0
- package/src/schemas/xml.ts +19 -0
- package/test/helpers.ts +16 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +8 -0
- package/vite.config.ts +9 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { createServerWorkspaceStore, WORKSPACE_FILE_NAME } from '@/create-server-workspace-store'
|
|
2
|
+
import { createWorkspaceStore } from '@/create-workspace-store'
|
|
3
|
+
import { beforeEach, describe, expect, test } from 'vitest'
|
|
4
|
+
import fastify, { type FastifyInstance } from 'fastify'
|
|
5
|
+
import { afterEach } from 'node:test'
|
|
6
|
+
import { cwd } from 'node:process'
|
|
7
|
+
import fs from 'node:fs/promises'
|
|
8
|
+
import type { Workspace } from '@/schemas/server-workspace'
|
|
9
|
+
|
|
10
|
+
// Test document
|
|
11
|
+
const document = {
|
|
12
|
+
openapi: '3.0.0',
|
|
13
|
+
info: { title: 'My API' },
|
|
14
|
+
components: {
|
|
15
|
+
schemas: {
|
|
16
|
+
User: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
id: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'The user ID',
|
|
22
|
+
},
|
|
23
|
+
name: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'The user name',
|
|
26
|
+
},
|
|
27
|
+
email: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
format: 'email',
|
|
30
|
+
description: 'The user email',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
paths: {
|
|
37
|
+
'/users': {
|
|
38
|
+
get: {
|
|
39
|
+
summary: 'Get all users',
|
|
40
|
+
responses: {
|
|
41
|
+
'200': {
|
|
42
|
+
description: 'Successful response',
|
|
43
|
+
content: {
|
|
44
|
+
'application/json': {
|
|
45
|
+
schema: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
items: {
|
|
48
|
+
$ref: '#/components/schemas/User',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe('create-workspace-store', () => {
|
|
61
|
+
let server: FastifyInstance
|
|
62
|
+
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
server = fastify({ logger: false })
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
afterEach(async () => {
|
|
68
|
+
await server.close()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('should correctly update workspace metadata', async () => {
|
|
72
|
+
const store = await createWorkspaceStore({
|
|
73
|
+
meta: {
|
|
74
|
+
'x-scalar-theme': 'default',
|
|
75
|
+
'x-scalar-dark-mode': false,
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
store.update('x-scalar-dark-mode', true)
|
|
80
|
+
store.update('x-scalar-theme', 'saturn')
|
|
81
|
+
|
|
82
|
+
expect(store.rawWorkspace['x-scalar-dark-mode']).toBe(true)
|
|
83
|
+
expect(store.rawWorkspace['x-scalar-theme']).toBe('saturn')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('should correctly update document metadata', async () => {
|
|
87
|
+
const store = await createWorkspaceStore({
|
|
88
|
+
documents: [
|
|
89
|
+
{
|
|
90
|
+
name: 'default',
|
|
91
|
+
document: {
|
|
92
|
+
openapi: '3.0.0',
|
|
93
|
+
info: { title: 'My API' },
|
|
94
|
+
},
|
|
95
|
+
meta: {
|
|
96
|
+
'x-scalar-active-auth': 'Bearer',
|
|
97
|
+
'x-scalar-active-server': 'server-1',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Should update the active document
|
|
104
|
+
store.updateDocument('active', 'x-scalar-active-server', 'server-2')
|
|
105
|
+
store.updateDocument('active', 'x-scalar-active-auth', undefined)
|
|
106
|
+
expect(store.rawWorkspace.documents['default']['x-scalar-active-auth']).toBe(undefined)
|
|
107
|
+
expect(store.rawWorkspace.documents['default']['x-scalar-active-server']).toBe('server-2')
|
|
108
|
+
|
|
109
|
+
// Should update a specific document
|
|
110
|
+
store.updateDocument('default', 'x-scalar-active-server', 'server-3')
|
|
111
|
+
store.updateDocument('default', 'x-scalar-active-auth', 'Bearer')
|
|
112
|
+
expect(store.rawWorkspace.documents['default']['x-scalar-active-auth']).toBe('Bearer')
|
|
113
|
+
expect(store.rawWorkspace.documents['default']['x-scalar-active-server']).toBe('server-3')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('should correctly get the correct document', async () => {
|
|
117
|
+
const store = await createWorkspaceStore({
|
|
118
|
+
documents: [
|
|
119
|
+
{
|
|
120
|
+
name: 'default',
|
|
121
|
+
document: {
|
|
122
|
+
openapi: '3.0.0',
|
|
123
|
+
info: { title: 'My API' },
|
|
124
|
+
},
|
|
125
|
+
meta: {
|
|
126
|
+
'x-scalar-active-auth': 'Bearer',
|
|
127
|
+
'x-scalar-active-server': 'server-1',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'document2',
|
|
132
|
+
document: {
|
|
133
|
+
openapi: '3.0.0',
|
|
134
|
+
info: { title: 'Second API' },
|
|
135
|
+
},
|
|
136
|
+
meta: {
|
|
137
|
+
'x-scalar-active-auth': 'Bearer',
|
|
138
|
+
'x-scalar-active-server': 'server-1',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
meta: {
|
|
143
|
+
'x-scalar-active-document': 'default',
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// Correctly gets the active document
|
|
148
|
+
expect(store.workspace.activeDocument?.info?.title).toBe('My API')
|
|
149
|
+
|
|
150
|
+
store.update('x-scalar-active-document', 'document2')
|
|
151
|
+
expect(store.workspace.activeDocument?.info?.title).toBe('Second API')
|
|
152
|
+
|
|
153
|
+
// Correctly get a specific document
|
|
154
|
+
expect(store.workspace.documents['default'].info?.title).toBe('My API')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
test('should correctly add new documents', async () => {
|
|
158
|
+
const store = await createWorkspaceStore({
|
|
159
|
+
documents: [],
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
await store.addDocument({
|
|
163
|
+
document: {
|
|
164
|
+
openapi: '3.0.0',
|
|
165
|
+
info: { title: 'My API' },
|
|
166
|
+
},
|
|
167
|
+
name: 'default',
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
store.update('x-scalar-active-document', 'default')
|
|
171
|
+
expect(store.workspace.activeDocument?.info?.title).toBe('My API')
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
test('should correctly resolve refs on the fly', async () => {
|
|
175
|
+
const store = await createWorkspaceStore({
|
|
176
|
+
documents: [
|
|
177
|
+
{
|
|
178
|
+
name: 'default',
|
|
179
|
+
document: {
|
|
180
|
+
openapi: '3.0.0',
|
|
181
|
+
info: { title: 'My API' },
|
|
182
|
+
components: {
|
|
183
|
+
schemas: {
|
|
184
|
+
User: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {
|
|
187
|
+
id: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'The user ID',
|
|
190
|
+
},
|
|
191
|
+
name: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
description: 'The user name',
|
|
194
|
+
},
|
|
195
|
+
email: {
|
|
196
|
+
type: 'string',
|
|
197
|
+
format: 'email',
|
|
198
|
+
description: 'The user email',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
paths: {
|
|
205
|
+
'/users': {
|
|
206
|
+
get: {
|
|
207
|
+
summary: 'Get all users',
|
|
208
|
+
responses: {
|
|
209
|
+
'200': {
|
|
210
|
+
description: 'Successful response',
|
|
211
|
+
content: {
|
|
212
|
+
'application/json': {
|
|
213
|
+
schema: {
|
|
214
|
+
type: 'array',
|
|
215
|
+
items: {
|
|
216
|
+
$ref: '#/components/schemas/User',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
expect(
|
|
232
|
+
(store.workspace.activeDocument?.paths?.['/users'].get as any)?.responses?.[200].content['application/json']
|
|
233
|
+
.schema.items.properties.name,
|
|
234
|
+
).toEqual({
|
|
235
|
+
type: 'string',
|
|
236
|
+
description: 'The user name',
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
test('should correctly resolve chunks from the remote server', async () => {
|
|
241
|
+
server.get('/*', (req, res) => {
|
|
242
|
+
const path = req.url
|
|
243
|
+
const contents = serverStore.get(path)
|
|
244
|
+
|
|
245
|
+
res.send(contents)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
const PORT = 9988
|
|
249
|
+
await server.listen({ port: PORT })
|
|
250
|
+
|
|
251
|
+
const serverStore = createServerWorkspaceStore({
|
|
252
|
+
mode: 'ssr',
|
|
253
|
+
baseUrl: `http://localhost:${PORT}`,
|
|
254
|
+
documents: [
|
|
255
|
+
{
|
|
256
|
+
name: 'default',
|
|
257
|
+
document,
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const store = await createWorkspaceStore({
|
|
263
|
+
documents: [
|
|
264
|
+
{
|
|
265
|
+
name: 'default',
|
|
266
|
+
document: serverStore.getWorkspace().documents['default'],
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// The operation should not be resolved on the fly
|
|
272
|
+
expect(store.workspace.activeDocument?.paths?.['/users'].get).toEqual({
|
|
273
|
+
'$ref': 'http://localhost:9988/default/operations/~1users/get#',
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
// We resolve the ref
|
|
277
|
+
await store.resolve(['paths', '/users', 'get'])
|
|
278
|
+
|
|
279
|
+
// We expect the ref to have been resolved with the correct contents
|
|
280
|
+
expect(store.workspace.activeDocument?.paths?.['/users'].get?.summary).toEqual(document.paths['/users'].get.summary)
|
|
281
|
+
|
|
282
|
+
expect(
|
|
283
|
+
(store.workspace.activeDocument?.paths?.['/users'].get as any).responses[200].content['application/json'].schema
|
|
284
|
+
.items,
|
|
285
|
+
).toEqual(document.components.schemas.User)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
test('should correctly resolve chunks from the file system', async () => {
|
|
289
|
+
const randomSeed = () => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)
|
|
290
|
+
const path = `temp-${randomSeed()}`
|
|
291
|
+
|
|
292
|
+
const serverStore = createServerWorkspaceStore({
|
|
293
|
+
mode: 'static',
|
|
294
|
+
directory: path,
|
|
295
|
+
documents: [
|
|
296
|
+
{
|
|
297
|
+
name: 'default',
|
|
298
|
+
document: document,
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
await serverStore.generateWorkspaceChunks()
|
|
304
|
+
|
|
305
|
+
const buildPath = `${cwd()}/${path}`
|
|
306
|
+
|
|
307
|
+
// Read the workspace file to get the sparse document
|
|
308
|
+
const workspace = JSON.parse(
|
|
309
|
+
await fs.readFile(`${buildPath}/${WORKSPACE_FILE_NAME}`, { encoding: 'utf-8' }),
|
|
310
|
+
) as Workspace
|
|
311
|
+
|
|
312
|
+
const store = await createWorkspaceStore({
|
|
313
|
+
documents: [
|
|
314
|
+
{
|
|
315
|
+
name: 'default',
|
|
316
|
+
document: workspace.documents['default'],
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
// The operation should not be resolved on the fly
|
|
322
|
+
expect(store.workspace.activeDocument?.paths?.['/users'].get).toEqual({
|
|
323
|
+
'$ref': `${path}/chunks/default/operations/~1users/get.json#`,
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
// We resolve the ref
|
|
327
|
+
await store.resolve(['paths', '/users', 'get'])
|
|
328
|
+
await fs.rm(`${cwd()}/${path}`, { recursive: true })
|
|
329
|
+
|
|
330
|
+
// We expect the ref to have been resolved with the correct contents
|
|
331
|
+
expect(store.workspace.activeDocument?.paths?.['/users'].get?.summary).toEqual(document.paths['/users'].get.summary)
|
|
332
|
+
|
|
333
|
+
expect(
|
|
334
|
+
(store.workspace.activeDocument?.paths?.['/users'].get as any).responses[200].content['application/json'].schema
|
|
335
|
+
.items,
|
|
336
|
+
).toEqual(document.components.schemas.User)
|
|
337
|
+
|
|
338
|
+
// clean up generated files
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
test('should load files form the remote url', async () => {
|
|
342
|
+
const PORT = 9989
|
|
343
|
+
const url = `http://localhost:${PORT}`
|
|
344
|
+
|
|
345
|
+
// Send the default document
|
|
346
|
+
server.get('/', (_, reply) => {
|
|
347
|
+
reply.send(document)
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
await server.listen({ port: PORT })
|
|
351
|
+
|
|
352
|
+
const store = await createWorkspaceStore({
|
|
353
|
+
documents: [
|
|
354
|
+
{
|
|
355
|
+
url: url,
|
|
356
|
+
name: 'default',
|
|
357
|
+
},
|
|
358
|
+
],
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
expect(Object.keys(store.workspace.documents)).toEqual(['default'])
|
|
362
|
+
expect(store.workspace.documents['default'].info?.title).toEqual(document.info.title)
|
|
363
|
+
|
|
364
|
+
// Add a new remote file
|
|
365
|
+
await store.addDocument({ name: 'new', url: url })
|
|
366
|
+
|
|
367
|
+
expect(Object.keys(store.workspace.documents)).toEqual(['default', 'new'])
|
|
368
|
+
expect(store.workspace.documents['new'].info?.title).toEqual(document.info.title)
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
test('should load files from the local file system', async () => {
|
|
372
|
+
const fileName = 'temp.json'
|
|
373
|
+
|
|
374
|
+
// write the document to a local file
|
|
375
|
+
await fs.writeFile(fileName, JSON.stringify(document))
|
|
376
|
+
|
|
377
|
+
const store = await createWorkspaceStore({
|
|
378
|
+
documents: [
|
|
379
|
+
{
|
|
380
|
+
path: fileName,
|
|
381
|
+
name: 'default',
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
expect(Object.keys(store.workspace.documents)).toEqual(['default'])
|
|
387
|
+
expect(store.workspace.documents['default'].info?.title).toEqual(document.info.title)
|
|
388
|
+
|
|
389
|
+
await store.addDocument({ name: 'new', path: fileName })
|
|
390
|
+
await fs.rm(fileName)
|
|
391
|
+
|
|
392
|
+
expect(Object.keys(store.workspace.documents)).toEqual(['default', 'new'])
|
|
393
|
+
expect(store.workspace.documents['new'].info?.title).toEqual(document.info.title)
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
test('should handle circular references when we try to resolve all remote chunks recursively', async () => {
|
|
397
|
+
const document = {
|
|
398
|
+
openapi: '3.0.0',
|
|
399
|
+
info: { title: 'My API' },
|
|
400
|
+
components: {
|
|
401
|
+
schemas: {
|
|
402
|
+
User: {
|
|
403
|
+
type: 'object',
|
|
404
|
+
properties: {
|
|
405
|
+
id: {
|
|
406
|
+
type: 'string',
|
|
407
|
+
description: 'The user ID',
|
|
408
|
+
},
|
|
409
|
+
name: {
|
|
410
|
+
$ref: '#/components/schemas/Rec',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
Rec: {
|
|
415
|
+
type: 'object',
|
|
416
|
+
properties: {
|
|
417
|
+
id: {
|
|
418
|
+
$ref: '#/components/schemas/User',
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
paths: {
|
|
425
|
+
'/users': {
|
|
426
|
+
get: {
|
|
427
|
+
summary: 'Get all users',
|
|
428
|
+
responses: {
|
|
429
|
+
'200': {
|
|
430
|
+
description: 'Successful response',
|
|
431
|
+
content: {
|
|
432
|
+
'application/json': {
|
|
433
|
+
schema: {
|
|
434
|
+
type: 'array',
|
|
435
|
+
items: {
|
|
436
|
+
$ref: '#/components/schemas/User',
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
server.get('/*', (req, res) => {
|
|
449
|
+
const path = req.url
|
|
450
|
+
const contents = serverStore.get(path)
|
|
451
|
+
|
|
452
|
+
res.send(contents)
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
const PORT = 6672
|
|
456
|
+
await server.listen({ port: PORT })
|
|
457
|
+
|
|
458
|
+
const serverStore = createServerWorkspaceStore({
|
|
459
|
+
mode: 'ssr',
|
|
460
|
+
baseUrl: `http://localhost:${PORT}`,
|
|
461
|
+
documents: [
|
|
462
|
+
{
|
|
463
|
+
name: 'default',
|
|
464
|
+
document,
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
const store = await createWorkspaceStore({
|
|
470
|
+
documents: [
|
|
471
|
+
{
|
|
472
|
+
name: 'default',
|
|
473
|
+
document: serverStore.getWorkspace().documents['default'],
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
// The operation should not be resolved on the fly
|
|
479
|
+
expect(store.workspace.activeDocument?.paths?.['/users'].get).toEqual({
|
|
480
|
+
'$ref': `http://localhost:${PORT}/default/operations/~1users/get#`,
|
|
481
|
+
})
|
|
482
|
+
|
|
483
|
+
// We resolve the ref
|
|
484
|
+
await store.resolve(['paths', '/users', 'get'])
|
|
485
|
+
|
|
486
|
+
expect((store.workspace.activeDocument?.components?.schemas?.['User'] as any)?.type).toBe('object')
|
|
487
|
+
})
|
|
488
|
+
})
|