@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,10 @@
|
|
|
1
|
+
|
|
2
|
+
> @scalar/workspace-store@0.1.0 build /home/runner/work/scalar/scalar/packages/workspace-store
|
|
3
|
+
> scalar-build-esbuild
|
|
4
|
+
|
|
5
|
+
[32mUpdating package.json exports field…[0m
|
|
6
|
+
[34m@scalar/workspace-store: Build completed in 41.47ms[39m
|
|
7
|
+
|
|
8
|
+
> @scalar/workspace-store@0.1.0 types:build /home/runner/work/scalar/scalar/packages/workspace-store
|
|
9
|
+
> scalar-types-build
|
|
10
|
+
|
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# @scalar/workspace-store
|
|
2
|
+
|
|
3
|
+
A powerful data store for managing OpenAPI documents. This package provides a flexible solution for handling multiple OpenAPI documents in a workspace environment
|
|
4
|
+
|
|
5
|
+
## Server-Side workspace store
|
|
6
|
+
|
|
7
|
+
Server side data store which enables document chunking to reduce initial loading time specially when working with large openapi documents
|
|
8
|
+
|
|
9
|
+
#### Usage
|
|
10
|
+
Create a new store in SSR mode
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
// Create the store
|
|
14
|
+
const store = createServerWorkspaceStore({
|
|
15
|
+
baseUrl: 'example.com',
|
|
16
|
+
mode: 'ssr',
|
|
17
|
+
meta: { 'x-scalar-active-document': 'document-name' },
|
|
18
|
+
documents: [
|
|
19
|
+
{
|
|
20
|
+
name: 'document-name',
|
|
21
|
+
meta: {},
|
|
22
|
+
document: {
|
|
23
|
+
openapi: '3.1.1',
|
|
24
|
+
info: {
|
|
25
|
+
title: 'Hello World',
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
},
|
|
28
|
+
components: {
|
|
29
|
+
schemas: {
|
|
30
|
+
Person: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
name: { type: 'string' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
User: {
|
|
37
|
+
$ref: '#/components/schemas/Person',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// Add a new document to the store
|
|
47
|
+
store.addDocument({
|
|
48
|
+
openapi: '3.1.1',
|
|
49
|
+
info: {
|
|
50
|
+
title: 'Hello World',
|
|
51
|
+
version: '1.0.0',
|
|
52
|
+
},
|
|
53
|
+
components: {
|
|
54
|
+
schemas: {
|
|
55
|
+
Person: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
name: { type: 'string' },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
User: {
|
|
62
|
+
$ref: '#/components/schemas/Person',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
}, {
|
|
67
|
+
name: 'document-2',
|
|
68
|
+
"x-scalar-active-server": "server1"
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Get the workspace
|
|
72
|
+
// Workspace is going to keep all the sparse documents
|
|
73
|
+
const workspace = store.getWorkspace()
|
|
74
|
+
|
|
75
|
+
// Get chucks using json pointers
|
|
76
|
+
const chunk = store.get('#/document-name/components/schemas/Person')
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
Create a new store in static mode
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
// Create the store
|
|
85
|
+
const store = createServerWorkspaceStore({
|
|
86
|
+
directory: 'assets',
|
|
87
|
+
mode: 'static',
|
|
88
|
+
meta: { 'x-scalar-active-document': 'document-name' },
|
|
89
|
+
documents: [
|
|
90
|
+
{
|
|
91
|
+
name: 'document-name',
|
|
92
|
+
meta: {},
|
|
93
|
+
document: {
|
|
94
|
+
openapi: '3.1.1',
|
|
95
|
+
info: {
|
|
96
|
+
title: 'Hello World',
|
|
97
|
+
version: '1.0.0',
|
|
98
|
+
},
|
|
99
|
+
components: {
|
|
100
|
+
schemas: {
|
|
101
|
+
Person: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
properties: {
|
|
104
|
+
name: { type: 'string' },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
User: {
|
|
108
|
+
$ref: '#/components/schemas/Person',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Add a new document to the store
|
|
118
|
+
store.addDocument({
|
|
119
|
+
openapi: '3.1.1',
|
|
120
|
+
info: {
|
|
121
|
+
title: 'Hello World',
|
|
122
|
+
version: '1.0.0',
|
|
123
|
+
},
|
|
124
|
+
components: {
|
|
125
|
+
schemas: {
|
|
126
|
+
Person: {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: {
|
|
129
|
+
name: { type: 'string' },
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
User: {
|
|
133
|
+
$ref: '#/components/schemas/Person',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
}, {
|
|
138
|
+
name: 'document-2',
|
|
139
|
+
"x-scalar-active-server": "server1"
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Generate the workspace file system
|
|
143
|
+
// This will write in the filesystem the workspace and all the chucks
|
|
144
|
+
// which can be resolved by the consumer
|
|
145
|
+
const workspace = await store.generateWorkspaceChunks()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Client-Side Workspace Store
|
|
149
|
+
|
|
150
|
+
A reactive workspace store for managing OpenAPI documents with automatic reference resolution and chunked loading capabilities. Works seamlessly with server-side stores to handle large documents efficiently.
|
|
151
|
+
|
|
152
|
+
#### Usage
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
|
|
156
|
+
// Initialize a new workspace store with default document
|
|
157
|
+
const store = await createWorkspaceStore({
|
|
158
|
+
documents: [
|
|
159
|
+
{
|
|
160
|
+
name: 'default',
|
|
161
|
+
document: {
|
|
162
|
+
info: {
|
|
163
|
+
title: 'OpenApi document',
|
|
164
|
+
version: '1.0.0',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
meta: {
|
|
170
|
+
'x-scalar-active-document': 'default',
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
// Add another OpenAPI document to the workspace
|
|
175
|
+
store.addDocument({
|
|
176
|
+
document: {
|
|
177
|
+
info: {
|
|
178
|
+
title: 'OpenApi document',
|
|
179
|
+
version: '1.0.0',
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
name: 'document',
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// Get the currently active document
|
|
186
|
+
store.workspace.activeDocument
|
|
187
|
+
|
|
188
|
+
// Retrieve a specific document by name
|
|
189
|
+
store.workspace.documents['document']
|
|
190
|
+
|
|
191
|
+
// Update global workspace settings
|
|
192
|
+
store.update('x-scalar-dark-mode', true)
|
|
193
|
+
|
|
194
|
+
// Update settings for the active document
|
|
195
|
+
store.updateDocument('active', "x-scalar-active-auth", '<value>')
|
|
196
|
+
|
|
197
|
+
// Resolve and load document chunks including any $ref references
|
|
198
|
+
await store.resolve(['paths', '/users', 'get'])
|
|
199
|
+
```
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
|
+
import type { WorkspaceDocumentMeta, WorkspaceMeta } from './schemas/server-workspace.js';
|
|
3
|
+
export declare const WORKSPACE_FILE_NAME = "scalar-workspace.json";
|
|
4
|
+
type CreateServerWorkspaceStore = {
|
|
5
|
+
directory?: string;
|
|
6
|
+
mode: 'static';
|
|
7
|
+
documents: {
|
|
8
|
+
name: string;
|
|
9
|
+
document: Record<string, unknown> | string;
|
|
10
|
+
meta?: WorkspaceDocumentMeta;
|
|
11
|
+
}[];
|
|
12
|
+
meta?: WorkspaceMeta;
|
|
13
|
+
} | {
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
mode: 'ssr';
|
|
16
|
+
documents: {
|
|
17
|
+
name: string;
|
|
18
|
+
document: Record<string, unknown> | string;
|
|
19
|
+
meta?: WorkspaceDocumentMeta;
|
|
20
|
+
}[];
|
|
21
|
+
meta?: WorkspaceMeta;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Filters an OpenAPI PathsObject to only include standard HTTP methods.
|
|
25
|
+
* Removes any vendor extensions or other non-HTTP properties.
|
|
26
|
+
*
|
|
27
|
+
* @param paths - The OpenAPI PathsObject to filter
|
|
28
|
+
* @returns A new PathsObject containing only standard HTTP methods
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* Input: {
|
|
32
|
+
* "/users": {
|
|
33
|
+
* "get": {...},
|
|
34
|
+
* "x-custom": {...},
|
|
35
|
+
* "post": {...}
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* Output: {
|
|
39
|
+
* "/users": {
|
|
40
|
+
* "get": {...},
|
|
41
|
+
* "post": {...}
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
export declare function filterHttpMethodsOnly(paths: OpenAPIV3_1.PathsObject): OpenAPIV3_1.PathsObject<{}, {}>;
|
|
46
|
+
/**
|
|
47
|
+
* Escapes path keys in an OpenAPI PathsObject to be JSON Pointer compatible.
|
|
48
|
+
* This is necessary because OpenAPI paths can contain characters that need to be escaped
|
|
49
|
+
* when used as JSON Pointer references (like '/' and '~').
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* Input: { "/users/{id}": { ... } }
|
|
53
|
+
* Output: { "/users~1{id}": { ... } }
|
|
54
|
+
*/
|
|
55
|
+
export declare function escapePaths(paths: OpenAPIV3_1.PathsObject): OpenAPIV3_1.PathsObject<{}, {}>;
|
|
56
|
+
/**
|
|
57
|
+
* Externalizes components by turning them into refs.
|
|
58
|
+
*/
|
|
59
|
+
export declare function externalizeComponentReferences(document: OpenAPIV3_1.Document, meta: {
|
|
60
|
+
mode: 'ssr';
|
|
61
|
+
name: string;
|
|
62
|
+
baseUrl: string;
|
|
63
|
+
} | {
|
|
64
|
+
mode: 'static';
|
|
65
|
+
name: string;
|
|
66
|
+
directory: string;
|
|
67
|
+
}): Record<string, any>;
|
|
68
|
+
/**
|
|
69
|
+
* Externalizes paths operations by turning them into refs.
|
|
70
|
+
*/
|
|
71
|
+
export declare function externalizePathReferences(document: OpenAPIV3_1.Document, meta: {
|
|
72
|
+
mode: 'ssr';
|
|
73
|
+
name: string;
|
|
74
|
+
baseUrl: string;
|
|
75
|
+
} | {
|
|
76
|
+
mode: 'static';
|
|
77
|
+
name: string;
|
|
78
|
+
directory: string;
|
|
79
|
+
}): Record<string, any>;
|
|
80
|
+
/**
|
|
81
|
+
* Create server state workspace store
|
|
82
|
+
*/
|
|
83
|
+
export declare function createServerWorkspaceStore(workspaceProps: CreateServerWorkspaceStore): {
|
|
84
|
+
/**
|
|
85
|
+
* Generates workspace chunks by writing components and operations to the filesystem.
|
|
86
|
+
*
|
|
87
|
+
* This method is only available in static mode. It creates a directory structure containing:
|
|
88
|
+
* - A workspace file with metadata and document references
|
|
89
|
+
* - Component chunks split by type (schemas, parameters, etc)
|
|
90
|
+
* - Operation chunks split by path and HTTP method
|
|
91
|
+
*
|
|
92
|
+
* The generated workspace references will be relative file paths pointing to these chunks.
|
|
93
|
+
*
|
|
94
|
+
* @throws {Error} If called when mode is not 'static'
|
|
95
|
+
*/
|
|
96
|
+
generateWorkspaceChunks: () => Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Returns the workspace document containing metadata and all sparse documents.
|
|
99
|
+
*
|
|
100
|
+
* The workspace document includes:
|
|
101
|
+
* - Global workspace metadata (theme, active document, etc)
|
|
102
|
+
* - Document metadata and sparse document
|
|
103
|
+
* - In SSR mode: References point to in-memory chunks
|
|
104
|
+
* - In static mode: References point to filesystem chunks
|
|
105
|
+
*
|
|
106
|
+
* @returns The complete workspace document
|
|
107
|
+
*/
|
|
108
|
+
getWorkspace: () => {
|
|
109
|
+
documents: Record<string, Record<string, unknown>>;
|
|
110
|
+
'x-scalar-dark-mode'?: boolean | undefined;
|
|
111
|
+
'x-scalar-default-client'?: string | undefined;
|
|
112
|
+
'x-scalar-active-document'?: string | undefined;
|
|
113
|
+
'x-scalar-theme'?: string | undefined;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Retrieves a chunk of data from the workspace using a JSON Pointer
|
|
117
|
+
*
|
|
118
|
+
* A JSON Pointer is a string that references a specific location in a JSON document.
|
|
119
|
+
* Only components and operations chunks can be retrieved.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* // Get a component
|
|
124
|
+
* get('#/document-name/components/schemas/User')
|
|
125
|
+
*
|
|
126
|
+
* // Get an operation
|
|
127
|
+
* get('#/document-name/operations/pets/get')
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @param pointer - The JSON Pointer string to locate the chunk
|
|
131
|
+
* @returns The chunk data if found, undefined otherwise
|
|
132
|
+
*/
|
|
133
|
+
get: (pointer: string) => unknown;
|
|
134
|
+
/**
|
|
135
|
+
* Adds a new document to the workspace.
|
|
136
|
+
*
|
|
137
|
+
* The document will be:
|
|
138
|
+
* - Upgraded to OpenAPI 3.1 if needed
|
|
139
|
+
* - Split into components and operations chunks
|
|
140
|
+
* - Have its references externalized based on the workspace mode
|
|
141
|
+
* - Added to the workspace with its metadata
|
|
142
|
+
*
|
|
143
|
+
* @param document - The OpenAPI document to add
|
|
144
|
+
* @param meta - Document metadata including required name and optional settings
|
|
145
|
+
*/
|
|
146
|
+
addDocument: (document: Record<string, unknown>, meta: {
|
|
147
|
+
name: string;
|
|
148
|
+
} & WorkspaceDocumentMeta) => void;
|
|
149
|
+
};
|
|
150
|
+
export {};
|
|
151
|
+
//# sourceMappingURL=create-server-workspace-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-server-workspace-store.d.ts","sourceRoot":"","sources":["../src/create-server-workspace-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAGtF,eAAO,MAAM,mBAAmB,0BAA0B,CAAA;AAE1D,KAAK,0BAA0B,GAC3B;IACE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;QAC1C,IAAI,CAAC,EAAE,qBAAqB,CAAA;KAC7B,EAAE,CAAA;IACH,IAAI,CAAC,EAAE,aAAa,CAAA;CACrB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,KAAK,CAAA;IACX,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;QAC1C,IAAI,CAAC,EAAE,qBAAqB,CAAA;KAC7B,EAAE,CAAA;IACH,IAAI,CAAC,EAAE,aAAa,CAAA;CACrB,CAAA;AAIL;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,CAAC,WAAW,mCAsBnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,WAAW,mCAOzD;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,IAAI,EAAE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,uBAqB3G;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,IAAI,EAAE;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,uBA8B3G;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,0BAA0B;IAkDjF;;;;;;;;;;;OAWG;;IAwCH;;;;;;;;;;OAUG;;;;;;;;IAIH;;;;;;;;;;;;;;;;;OAiBG;mBACY,MAAM;IAGrB;;;;;;;;;;;OAWG;4BACqB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,qBAAqB;EAwBlG"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { escapeJsonPointer, upgrade } from "@scalar/openapi-parser";
|
|
2
|
+
import { getValueByPath, parseJsonPointer } from "./helpers/json-path-utils.js";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import { cwd } from "node:process";
|
|
5
|
+
const DEFAULT_ASSETS_FOLDER = "assets";
|
|
6
|
+
const WORKSPACE_FILE_NAME = "scalar-workspace.json";
|
|
7
|
+
const httpMethods = /* @__PURE__ */ new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
|
|
8
|
+
function filterHttpMethodsOnly(paths) {
|
|
9
|
+
const result = {};
|
|
10
|
+
for (const [path, methods] of Object.entries(paths)) {
|
|
11
|
+
if (!methods) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const filteredMethods = {};
|
|
15
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
16
|
+
if (httpMethods.has(method.toLowerCase())) {
|
|
17
|
+
filteredMethods[method] = operation;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (Object.keys(filteredMethods).length > 0) {
|
|
21
|
+
result[path] = filteredMethods;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
function escapePaths(paths) {
|
|
27
|
+
const result = {};
|
|
28
|
+
Object.keys(paths).forEach((path) => {
|
|
29
|
+
result[escapeJsonPointer(path)] = paths[path];
|
|
30
|
+
});
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function externalizeComponentReferences(document, meta) {
|
|
34
|
+
const result = {};
|
|
35
|
+
if (!document.components) {
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
Object.entries(document.components).forEach(([type, component]) => {
|
|
39
|
+
result[type] = {};
|
|
40
|
+
Object.keys(component).forEach((name) => {
|
|
41
|
+
const ref = meta.mode === "ssr" ? `${meta.baseUrl}/${meta.name}/components/${type}/${name}#` : `${meta.directory}/chunks/${meta.name}/components/${type}/${name}.json#`;
|
|
42
|
+
result[type][name] = { "$ref": ref };
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
function externalizePathReferences(document, meta) {
|
|
48
|
+
const result = {};
|
|
49
|
+
if (!document.paths) {
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
Object.entries(document.paths).forEach(([path, pathItem]) => {
|
|
53
|
+
if (!pathItem) {
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
result[path] = {};
|
|
57
|
+
const escapedPath = escapeJsonPointer(path);
|
|
58
|
+
Object.keys(pathItem).forEach((type) => {
|
|
59
|
+
if (httpMethods.has(type)) {
|
|
60
|
+
const ref = meta.mode === "ssr" ? `${meta.baseUrl}/${meta.name}/operations/${escapedPath}/${type}#` : `${meta.directory}/chunks/${meta.name}/operations/${escapedPath}/${type}.json#`;
|
|
61
|
+
result[path][type] = { "$ref": ref };
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function createServerWorkspaceStore(workspaceProps) {
|
|
68
|
+
const documents = workspaceProps.documents.map((el) => {
|
|
69
|
+
const document = upgrade(el.document).specification;
|
|
70
|
+
return { ...el, document };
|
|
71
|
+
});
|
|
72
|
+
const assets = documents.reduce((acc, { name, document }) => {
|
|
73
|
+
acc[name] = {
|
|
74
|
+
components: document.components,
|
|
75
|
+
operations: document.paths && escapePaths(filterHttpMethodsOnly(document.paths))
|
|
76
|
+
};
|
|
77
|
+
return acc;
|
|
78
|
+
}, {});
|
|
79
|
+
const workspace = {
|
|
80
|
+
...workspaceProps.meta,
|
|
81
|
+
documents: documents.reduce((acc, { name, document, meta }) => {
|
|
82
|
+
const options = workspaceProps.mode === "ssr" ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl } : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER };
|
|
83
|
+
const components = externalizeComponentReferences(document, options);
|
|
84
|
+
const paths = externalizePathReferences(document, options);
|
|
85
|
+
acc[name] = { ...meta, ...document, components, paths };
|
|
86
|
+
return acc;
|
|
87
|
+
}, {})
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
/**
|
|
91
|
+
* Generates workspace chunks by writing components and operations to the filesystem.
|
|
92
|
+
*
|
|
93
|
+
* This method is only available in static mode. It creates a directory structure containing:
|
|
94
|
+
* - A workspace file with metadata and document references
|
|
95
|
+
* - Component chunks split by type (schemas, parameters, etc)
|
|
96
|
+
* - Operation chunks split by path and HTTP method
|
|
97
|
+
*
|
|
98
|
+
* The generated workspace references will be relative file paths pointing to these chunks.
|
|
99
|
+
*
|
|
100
|
+
* @throws {Error} If called when mode is not 'static'
|
|
101
|
+
*/
|
|
102
|
+
generateWorkspaceChunks: async () => {
|
|
103
|
+
if (workspaceProps.mode !== "static") {
|
|
104
|
+
throw "Mode has to be set to `static` to generate filesystem workspace chunks";
|
|
105
|
+
}
|
|
106
|
+
const basePath = `${cwd()}/${workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER}`;
|
|
107
|
+
await fs.mkdir(basePath, { recursive: true });
|
|
108
|
+
await fs.writeFile(`${basePath}/${WORKSPACE_FILE_NAME}`, JSON.stringify(workspace));
|
|
109
|
+
for (const [name, { components, operations }] of Object.entries(assets)) {
|
|
110
|
+
if (components) {
|
|
111
|
+
for (const [type, component] of Object.entries(components)) {
|
|
112
|
+
const componentPath = `${basePath}/chunks/${name}/components/${type}`;
|
|
113
|
+
await fs.mkdir(componentPath, { recursive: true });
|
|
114
|
+
for (const [key, value] of Object.entries(component)) {
|
|
115
|
+
await fs.writeFile(`${componentPath}/${key}.json`, JSON.stringify(value));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (operations) {
|
|
120
|
+
for (const [path, methods] of Object.entries(operations)) {
|
|
121
|
+
const operationPath = `${basePath}/chunks/${name}/operations/${path}`;
|
|
122
|
+
await fs.mkdir(operationPath, { recursive: true });
|
|
123
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
124
|
+
await fs.writeFile(`${operationPath}/${method}.json`, JSON.stringify(operation));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
/**
|
|
131
|
+
* Returns the workspace document containing metadata and all sparse documents.
|
|
132
|
+
*
|
|
133
|
+
* The workspace document includes:
|
|
134
|
+
* - Global workspace metadata (theme, active document, etc)
|
|
135
|
+
* - Document metadata and sparse document
|
|
136
|
+
* - In SSR mode: References point to in-memory chunks
|
|
137
|
+
* - In static mode: References point to filesystem chunks
|
|
138
|
+
*
|
|
139
|
+
* @returns The complete workspace document
|
|
140
|
+
*/
|
|
141
|
+
getWorkspace: () => {
|
|
142
|
+
return workspace;
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Retrieves a chunk of data from the workspace using a JSON Pointer
|
|
146
|
+
*
|
|
147
|
+
* A JSON Pointer is a string that references a specific location in a JSON document.
|
|
148
|
+
* Only components and operations chunks can be retrieved.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* // Get a component
|
|
153
|
+
* get('#/document-name/components/schemas/User')
|
|
154
|
+
*
|
|
155
|
+
* // Get an operation
|
|
156
|
+
* get('#/document-name/operations/pets/get')
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @param pointer - The JSON Pointer string to locate the chunk
|
|
160
|
+
* @returns The chunk data if found, undefined otherwise
|
|
161
|
+
*/
|
|
162
|
+
get: (pointer) => {
|
|
163
|
+
return getValueByPath(assets, parseJsonPointer(pointer));
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Adds a new document to the workspace.
|
|
167
|
+
*
|
|
168
|
+
* The document will be:
|
|
169
|
+
* - Upgraded to OpenAPI 3.1 if needed
|
|
170
|
+
* - Split into components and operations chunks
|
|
171
|
+
* - Have its references externalized based on the workspace mode
|
|
172
|
+
* - Added to the workspace with its metadata
|
|
173
|
+
*
|
|
174
|
+
* @param document - The OpenAPI document to add
|
|
175
|
+
* @param meta - Document metadata including required name and optional settings
|
|
176
|
+
*/
|
|
177
|
+
addDocument: (document, meta) => {
|
|
178
|
+
const { name, ...documentMeta } = meta;
|
|
179
|
+
const documentV3 = upgrade(document).specification;
|
|
180
|
+
assets[meta.name] = {
|
|
181
|
+
components: documentV3.schema?.components,
|
|
182
|
+
operations: documentV3.schema?.paths && escapePaths(filterHttpMethodsOnly(documentV3.schema.paths))
|
|
183
|
+
};
|
|
184
|
+
const options = workspaceProps.mode === "ssr" ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl } : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER };
|
|
185
|
+
const components = externalizeComponentReferences(documentV3, options);
|
|
186
|
+
const paths = externalizePathReferences(documentV3, options);
|
|
187
|
+
workspace.documents[meta.name] = { ...documentMeta, ...documentV3, components, paths };
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
export {
|
|
192
|
+
WORKSPACE_FILE_NAME,
|
|
193
|
+
createServerWorkspaceStore,
|
|
194
|
+
escapePaths,
|
|
195
|
+
externalizeComponentReferences,
|
|
196
|
+
externalizePathReferences,
|
|
197
|
+
filterHttpMethodsOnly
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=create-server-workspace-store.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/create-server-workspace-store.ts"],
|
|
4
|
+
"sourcesContent": ["import { escapeJsonPointer, upgrade } from '@scalar/openapi-parser'\nimport type { OpenAPIV3_1 } from '@scalar/openapi-types'\nimport { getValueByPath, parseJsonPointer } from './helpers/json-path-utils'\nimport fs from 'node:fs/promises'\nimport { cwd } from 'node:process'\nimport type { WorkspaceDocumentMeta, WorkspaceMeta } from './schemas/server-workspace'\n\nconst DEFAULT_ASSETS_FOLDER = 'assets'\nexport const WORKSPACE_FILE_NAME = 'scalar-workspace.json'\n\ntype CreateServerWorkspaceStore =\n | {\n directory?: string\n mode: 'static'\n documents: {\n name: string\n document: Record<string, unknown> | string\n meta?: WorkspaceDocumentMeta\n }[]\n meta?: WorkspaceMeta\n }\n | {\n baseUrl: string\n mode: 'ssr'\n documents: {\n name: string\n document: Record<string, unknown> | string\n meta?: WorkspaceDocumentMeta\n }[]\n meta?: WorkspaceMeta\n }\n\nconst httpMethods = new Set(['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'])\n\n/**\n * Filters an OpenAPI PathsObject to only include standard HTTP methods.\n * Removes any vendor extensions or other non-HTTP properties.\n *\n * @param paths - The OpenAPI PathsObject to filter\n * @returns A new PathsObject containing only standard HTTP methods\n *\n * @example\n * Input: {\n * \"/users\": {\n * \"get\": {...},\n * \"x-custom\": {...},\n * \"post\": {...}\n * }\n * }\n * Output: {\n * \"/users\": {\n * \"get\": {...},\n * \"post\": {...}\n * }\n * }\n */\nexport function filterHttpMethodsOnly(paths: OpenAPIV3_1.PathsObject) {\n const result: OpenAPIV3_1.PathsObject = {}\n\n for (const [path, methods] of Object.entries(paths)) {\n if (!methods) {\n continue\n }\n\n const filteredMethods: Record<string, any> = {}\n\n for (const [method, operation] of Object.entries(methods)) {\n if (httpMethods.has(method.toLowerCase())) {\n filteredMethods[method] = operation\n }\n }\n\n if (Object.keys(filteredMethods).length > 0) {\n result[path] = filteredMethods\n }\n }\n\n return result\n}\n\n/**\n * Escapes path keys in an OpenAPI PathsObject to be JSON Pointer compatible.\n * This is necessary because OpenAPI paths can contain characters that need to be escaped\n * when used as JSON Pointer references (like '/' and '~').\n *\n * @example\n * Input: { \"/users/{id}\": { ... } }\n * Output: { \"/users~1{id}\": { ... } }\n */\nexport function escapePaths(paths: OpenAPIV3_1.PathsObject) {\n const result: OpenAPIV3_1.PathsObject = {}\n Object.keys(paths).forEach((path) => {\n result[escapeJsonPointer(path)] = paths[path]\n })\n\n return result\n}\n\n/**\n * Externalizes components by turning them into refs.\n */\nexport function externalizeComponentReferences(\n document: OpenAPIV3_1.Document,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.components) {\n return result\n }\n\n Object.entries(document.components).forEach(([type, component]) => {\n result[type] = {}\n Object.keys(component).forEach((name) => {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/components/${type}/${name}#`\n : `${meta.directory}/chunks/${meta.name}/components/${type}/${name}.json#`\n\n result[type][name] = { '$ref': ref }\n })\n })\n\n return result\n}\n\n/**\n * Externalizes paths operations by turning them into refs.\n */\nexport function externalizePathReferences(\n document: OpenAPIV3_1.Document,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.paths) {\n return result\n }\n\n Object.entries(document.paths).forEach(([path, pathItem]) => {\n if (!pathItem) {\n return result\n }\n\n result[path] = {}\n\n const escapedPath = escapeJsonPointer(path)\n\n Object.keys(pathItem).forEach((type) => {\n if (httpMethods.has(type)) {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/operations/${escapedPath}/${type}#`\n : `${meta.directory}/chunks/${meta.name}/operations/${escapedPath}/${type}.json#`\n\n result[path][type] = { '$ref': ref }\n }\n })\n })\n\n return result\n}\n\n/**\n * Create server state workspace store\n */\nexport function createServerWorkspaceStore(workspaceProps: CreateServerWorkspaceStore) {\n const documents = workspaceProps.documents.map((el) => {\n const document = upgrade(el.document).specification\n\n return { ...el, document }\n })\n\n /**\n * A map of document chunks that can be loaded asynchronously by the client.\n * Each document is split into components and operations to enable lazy loading.\n * The keys are document names and values contain the components and operations\n * for that document.\n */\n const assets = documents.reduce<\n Record<string, { components?: OpenAPIV3_1.ComponentsObject; operations?: Record<string, unknown> }>\n >((acc, { name, document }) => {\n acc[name] = {\n components: document.components,\n operations: document.paths && escapePaths(filterHttpMethodsOnly(document.paths)),\n }\n return acc\n }, {})\n\n /**\n * Base workspace document containing essential metadata and document references.\n *\n * This workspace document provides the minimal information needed for initial rendering.\n * All components and path operations are replaced with references to enable lazy loading.\n *\n * In SSR mode, references point to API endpoints.\n * In static mode, references point to filesystem chunks.\n */\n const workspace = {\n ...workspaceProps.meta,\n documents: documents.reduce<Record<string, Record<string, unknown>>>((acc, { name, document, meta }) => {\n const options =\n workspaceProps.mode === 'ssr'\n ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl }\n : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER }\n\n // Transform the original document by setting all the components and paths operations on refs\n const components = externalizeComponentReferences(document, options)\n const paths = externalizePathReferences(document, options)\n\n acc[name] = { ...meta, ...document, components, paths }\n return acc\n }, {}),\n }\n\n return {\n /**\n * Generates workspace chunks by writing components and operations to the filesystem.\n *\n * This method is only available in static mode. It creates a directory structure containing:\n * - A workspace file with metadata and document references\n * - Component chunks split by type (schemas, parameters, etc)\n * - Operation chunks split by path and HTTP method\n *\n * The generated workspace references will be relative file paths pointing to these chunks.\n *\n * @throws {Error} If called when mode is not 'static'\n */\n generateWorkspaceChunks: async () => {\n if (workspaceProps.mode !== 'static') {\n throw 'Mode has to be set to `static` to generate filesystem workspace chunks'\n }\n\n // Write the workspace document\n const basePath = `${cwd()}/${workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER}`\n await fs.mkdir(basePath, { recursive: true })\n\n // Write the workspace contents on the file system\n await fs.writeFile(`${basePath}/${WORKSPACE_FILE_NAME}`, JSON.stringify(workspace))\n\n // Write the chunks\n for (const [name, { components, operations }] of Object.entries(assets)) {\n // Write the components chunks\n if (components) {\n for (const [type, component] of Object.entries(components as Record<string, Record<string, unknown>>)) {\n const componentPath = `${basePath}/chunks/${name}/components/${type}`\n await fs.mkdir(componentPath, { recursive: true })\n\n for (const [key, value] of Object.entries(component)) {\n await fs.writeFile(`${componentPath}/${key}.json`, JSON.stringify(value))\n }\n }\n }\n\n // Write the operations chunks\n if (operations) {\n for (const [path, methods] of Object.entries(operations as Record<string, Record<string, unknown>>)) {\n const operationPath = `${basePath}/chunks/${name}/operations/${path}`\n await fs.mkdir(operationPath, { recursive: true })\n\n for (const [method, operation] of Object.entries(methods)) {\n await fs.writeFile(`${operationPath}/${method}.json`, JSON.stringify(operation))\n }\n }\n }\n }\n },\n /**\n * Returns the workspace document containing metadata and all sparse documents.\n *\n * The workspace document includes:\n * - Global workspace metadata (theme, active document, etc)\n * - Document metadata and sparse document\n * - In SSR mode: References point to in-memory chunks\n * - In static mode: References point to filesystem chunks\n *\n * @returns The complete workspace document\n */\n getWorkspace: () => {\n return workspace\n },\n /**\n * Retrieves a chunk of data from the workspace using a JSON Pointer\n *\n * A JSON Pointer is a string that references a specific location in a JSON document.\n * Only components and operations chunks can be retrieved.\n *\n * @example\n * ```ts\n * // Get a component\n * get('#/document-name/components/schemas/User')\n *\n * // Get an operation\n * get('#/document-name/operations/pets/get')\n * ```\n *\n * @param pointer - The JSON Pointer string to locate the chunk\n * @returns The chunk data if found, undefined otherwise\n */\n get: (pointer: string) => {\n return getValueByPath(assets, parseJsonPointer(pointer))\n },\n /**\n * Adds a new document to the workspace.\n *\n * The document will be:\n * - Upgraded to OpenAPI 3.1 if needed\n * - Split into components and operations chunks\n * - Have its references externalized based on the workspace mode\n * - Added to the workspace with its metadata\n *\n * @param document - The OpenAPI document to add\n * @param meta - Document metadata including required name and optional settings\n */\n addDocument: (document: Record<string, unknown>, meta: { name: string } & WorkspaceDocumentMeta) => {\n const { name, ...documentMeta } = meta\n\n const documentV3 = upgrade(document).specification\n\n // add the assets\n assets[meta.name] = {\n components: documentV3.schema?.components,\n operations: documentV3.schema?.paths && escapePaths(filterHttpMethodsOnly(documentV3.schema.paths as any)),\n }\n\n const options =\n workspaceProps.mode === 'ssr'\n ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl }\n : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER }\n\n const components = externalizeComponentReferences(documentV3, options)\n const paths = externalizePathReferences(documentV3, options)\n\n // The document is now a minimal version with externalized references to components and operations.\n // These references will be resolved asynchronously when needed through the workspace's get() method.\n workspace.documents[meta.name] = { ...documentMeta, ...documentV3, components, paths }\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|