@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.81
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/commonjs/src/add-api.action.js +39 -0
- package/commonjs/src/add-api.command.js +41 -0
- package/commonjs/src/add.command.js +24 -0
- package/commonjs/src/add.module.js +26 -0
- package/commonjs/src/cli.js +9 -0
- package/commonjs/src/create.command.js +24 -0
- package/commonjs/src/create.module.js +26 -0
- package/commonjs/src/domain/prompt.js +64 -0
- package/commonjs/src/index.js +38 -0
- package/commonjs/src/models/compose.model.js +150 -0
- package/commonjs/src/models/config-yaml.model.js +88 -0
- package/commonjs/src/models/const.js +32 -0
- package/commonjs/src/models/dev-container.model.js +116 -0
- package/commonjs/src/models/docker-image.model.js +259 -0
- package/commonjs/src/models/env-file.model.js +50 -0
- package/commonjs/src/models/gitignore.model.js +43 -0
- package/commonjs/src/models/launch-json.model.js +74 -0
- package/commonjs/src/models/package-json.model.js +149 -0
- package/commonjs/src/models/project.model.js +134 -0
- package/commonjs/src/models/source-file.js +6 -0
- package/commonjs/src/models/tsconfig.model.js +34 -0
- package/commonjs/src/models/vitest-config.model.js +35 -0
- package/commonjs/src/models/vscode-settings.model.js +31 -0
- package/commonjs/src/program.js +57 -0
- package/commonjs/src/resolve-target-dir.js +19 -0
- package/commonjs/src/services/scaffold.service.js +62 -0
- package/commonjs/src/version.js +57 -0
- package/commonjs/src/webapi/api-name.js +95 -0
- package/commonjs/src/webapi/cli-options.js +101 -0
- package/commonjs/src/webapi/const.js +50 -0
- package/commonjs/src/webapi/create-api.js +237 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.js +166 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/commonjs/src/webapi/devcontainer/host-scripts.js +52 -0
- package/commonjs/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/commonjs/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/commonjs/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/commonjs/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/commonjs/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/commonjs/src/webapi/features/auth.feature.js +441 -0
- package/commonjs/src/webapi/features/auth0-cli.js +435 -0
- package/commonjs/src/webapi/features/biome-format.js +49 -0
- package/commonjs/src/webapi/features/database.feature.js +433 -0
- package/commonjs/src/webapi/features/finalize.feature.js +95 -0
- package/commonjs/src/webapi/features/postman.feature.js +324 -0
- package/commonjs/src/webapi/models/api-package-json.model.js +60 -0
- package/commonjs/src/webapi/models/auth-config.model.js +26 -0
- package/commonjs/src/webapi/models/controller-source-file.model.js +193 -0
- package/commonjs/src/webapi/models/github-ci.model.js +193 -0
- package/commonjs/src/webapi/models/main-source-file.model.js +167 -0
- package/commonjs/src/webapi/models/production-dockerfile.model.js +157 -0
- package/commonjs/src/webapi/models/sample-files.model.js +60 -0
- package/commonjs/src/webapi/models/webapi-image.model.js +27 -0
- package/commonjs/src/webapi/postman/hello-openapi.js +175 -0
- package/commonjs/src/webapi/postman/local-view.js +184 -0
- package/commonjs/src/webapi/postman/openapi-to-postman.js +202 -0
- package/commonjs/src/webapi/workspace-readme.js +110 -0
- package/commonjs/src/webapi.action.js +30 -0
- package/commonjs/src/webapi.command.js +45 -0
- package/es6/src/add-api.action.js +29 -0
- package/es6/src/add-api.command.js +31 -0
- package/es6/src/add.command.js +14 -0
- package/es6/src/add.module.js +16 -0
- package/es6/src/cli.js +5 -0
- package/es6/src/create.command.js +14 -0
- package/es6/src/create.module.js +16 -0
- package/es6/src/domain/prompt.js +43 -0
- package/es6/src/index.js +8 -0
- package/es6/src/models/compose.model.js +144 -0
- package/es6/src/models/config-yaml.model.js +76 -0
- package/es6/src/models/const.js +22 -0
- package/es6/src/models/dev-container.model.js +106 -0
- package/es6/src/models/docker-image.model.js +217 -0
- package/es6/src/models/env-file.model.js +46 -0
- package/es6/src/models/gitignore.model.js +33 -0
- package/es6/src/models/launch-json.model.js +64 -0
- package/es6/src/models/package-json.model.js +137 -0
- package/es6/src/models/project.model.js +119 -0
- package/es6/src/models/source-file.js +3 -0
- package/es6/src/models/tsconfig.model.js +24 -0
- package/es6/src/models/vitest-config.model.js +25 -0
- package/es6/src/models/vscode-settings.model.js +21 -0
- package/es6/src/program.js +39 -0
- package/es6/src/resolve-target-dir.js +9 -0
- package/es6/src/services/scaffold.service.js +52 -0
- package/es6/src/version.js +36 -0
- package/es6/src/webapi/api-name.js +59 -0
- package/es6/src/webapi/cli-options.js +36 -0
- package/es6/src/webapi/const.js +20 -0
- package/es6/src/webapi/create-api.js +217 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.js +156 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/es6/src/webapi/devcontainer/host-scripts.js +31 -0
- package/es6/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/es6/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/es6/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/es6/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/es6/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/es6/src/webapi/features/auth.feature.js +390 -0
- package/es6/src/webapi/features/auth0-cli.js +375 -0
- package/es6/src/webapi/features/biome-format.js +42 -0
- package/es6/src/webapi/features/database.feature.js +423 -0
- package/es6/src/webapi/features/finalize.feature.js +85 -0
- package/es6/src/webapi/features/postman.feature.js +258 -0
- package/es6/src/webapi/models/api-package-json.model.js +55 -0
- package/es6/src/webapi/models/auth-config.model.js +22 -0
- package/es6/src/webapi/models/controller-source-file.model.js +184 -0
- package/es6/src/webapi/models/github-ci.model.js +186 -0
- package/es6/src/webapi/models/main-source-file.model.js +163 -0
- package/es6/src/webapi/models/production-dockerfile.model.js +148 -0
- package/es6/src/webapi/models/sample-files.model.js +42 -0
- package/es6/src/webapi/models/webapi-image.model.js +20 -0
- package/es6/src/webapi/postman/hello-openapi.js +168 -0
- package/es6/src/webapi/postman/local-view.js +169 -0
- package/es6/src/webapi/postman/openapi-to-postman.js +179 -0
- package/es6/src/webapi/workspace-readme.js +89 -0
- package/es6/src/webapi.action.js +20 -0
- package/es6/src/webapi.command.js +35 -0
- package/package.json +8 -8
- package/types/src/add-api.action.d.ts +13 -0
- package/types/src/add-api.command.d.ts +7 -0
- package/types/src/add.command.d.ts +6 -0
- package/types/src/add.module.d.ts +14 -0
- package/types/src/cli.d.ts +2 -0
- package/types/src/create.command.d.ts +6 -0
- package/types/src/create.module.d.ts +14 -0
- package/types/src/domain/prompt.d.ts +4 -0
- package/types/src/models/compose.model.d.ts +64 -0
- package/types/src/models/config-yaml.model.d.ts +27 -0
- package/types/src/models/const.d.ts +20 -0
- package/types/src/models/dev-container.model.d.ts +37 -0
- package/types/src/models/docker-image.model.d.ts +84 -0
- package/types/src/models/env-file.model.d.ts +16 -0
- package/types/src/models/gitignore.model.d.ts +7 -0
- package/types/src/models/launch-json.model.d.ts +7 -0
- package/types/src/models/package-json.model.d.ts +35 -0
- package/types/src/models/project.model.d.ts +60 -0
- package/{src/models/source-file.ts → types/src/models/source-file.d.ts} +4 -6
- package/types/src/models/tsconfig.model.d.ts +5 -0
- package/types/src/models/vitest-config.model.d.ts +5 -0
- package/types/src/models/vscode-settings.model.d.ts +7 -0
- package/types/src/program.d.ts +3 -0
- package/{src/resolve-target-dir.ts → types/src/resolve-target-dir.d.ts} +1 -4
- package/types/src/services/scaffold.service.d.ts +22 -0
- package/types/src/version.d.ts +6 -0
- package/types/src/webapi/api-name.d.ts +14 -0
- package/types/src/webapi/cli-options.d.ts +6 -0
- package/{src/webapi/const.ts → types/src/webapi/const.d.ts} +7 -21
- package/types/src/webapi/create-api.d.ts +15 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.d.ts +32 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/types/src/webapi/devcontainer/host-scripts.d.ts +7 -0
- package/types/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/types/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/types/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/types/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/types/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/types/src/webapi/features/auth.feature.d.ts +10 -0
- package/types/src/webapi/features/auth0-cli.d.ts +80 -0
- package/types/src/webapi/features/biome-format.d.ts +5 -0
- package/types/src/webapi/features/database.feature.d.ts +7 -0
- package/types/src/webapi/features/finalize.feature.d.ts +2 -0
- package/types/src/webapi/features/postman.feature.d.ts +16 -0
- package/types/src/webapi/models/api-package-json.model.d.ts +18 -0
- package/types/src/webapi/models/auth-config.model.d.ts +26 -0
- package/types/src/webapi/models/controller-source-file.model.d.ts +46 -0
- package/types/src/webapi/models/github-ci.model.d.ts +9 -0
- package/types/src/webapi/models/main-source-file.model.d.ts +54 -0
- package/types/src/webapi/models/production-dockerfile.model.d.ts +23 -0
- package/types/src/webapi/models/sample-files.model.d.ts +7 -0
- package/types/src/webapi/models/webapi-image.model.d.ts +12 -0
- package/types/src/webapi/postman/hello-openapi.d.ts +19 -0
- package/types/src/webapi/postman/local-view.d.ts +17 -0
- package/types/src/webapi/postman/openapi-to-postman.d.ts +62 -0
- package/types/src/webapi/workspace-readme.d.ts +18 -0
- package/types/src/webapi.action.d.ts +14 -0
- package/types/src/webapi.command.d.ts +11 -0
- package/src/add-api.action.ts +0 -25
- package/src/add-api.command.ts +0 -31
- package/src/add.command.ts +0 -20
- package/src/add.module.ts +0 -11
- package/src/cli.ts +0 -4
- package/src/create.command.ts +0 -20
- package/src/create.module.ts +0 -11
- package/src/domain/prompt.ts +0 -50
- package/src/models/compose.model.ts +0 -205
- package/src/models/config-yaml.model.ts +0 -83
- package/src/models/const.ts +0 -20
- package/src/models/dev-container.model.ts +0 -136
- package/src/models/docker-image.model.ts +0 -343
- package/src/models/env-file.model.ts +0 -45
- package/src/models/gitignore.model.ts +0 -35
- package/src/models/launch-json.model.ts +0 -60
- package/src/models/package-json.model.ts +0 -169
- package/src/models/project.model.ts +0 -141
- package/src/models/tsconfig.model.ts +0 -29
- package/src/models/vitest-config.model.ts +0 -26
- package/src/models/vscode-settings.model.ts +0 -24
- package/src/program.ts +0 -63
- package/src/services/scaffold.service.ts +0 -89
- package/src/version.ts +0 -56
- package/src/webapi/api-name.ts +0 -73
- package/src/webapi/cli-options.ts +0 -56
- package/src/webapi/create-api.ts +0 -275
- package/src/webapi/devcontainer/host-scripts.ts +0 -35
- package/src/webapi/features/auth.feature.ts +0 -454
- package/src/webapi/features/auth0-cli.ts +0 -421
- package/src/webapi/features/biome-format.ts +0 -34
- package/src/webapi/features/database.feature.ts +0 -522
- package/src/webapi/features/finalize.feature.ts +0 -112
- package/src/webapi/features/postman.feature.ts +0 -287
- package/src/webapi/models/api-package-json.model.ts +0 -60
- package/src/webapi/models/auth-config.model.ts +0 -36
- package/src/webapi/models/controller-source-file.model.ts +0 -232
- package/src/webapi/models/github-ci.model.ts +0 -188
- package/src/webapi/models/main-source-file.model.ts +0 -208
- package/src/webapi/models/production-dockerfile.model.ts +0 -162
- package/src/webapi/models/sample-files.model.ts +0 -45
- package/src/webapi/models/webapi-image.model.ts +0 -21
- package/src/webapi/postman/hello-openapi.ts +0 -92
- package/src/webapi/postman/local-view.ts +0 -195
- package/src/webapi/postman/openapi-to-postman.ts +0 -208
- package/src/webapi/workspace-readme.ts +0 -192
- package/src/webapi.action.ts +0 -22
- package/src/webapi.command.ts +0 -41
- package/tests/auth-postman.wiring.spec.ts +0 -263
- package/tests/auth0-cli.spec.ts +0 -232
- package/tests/biome-format.spec.ts +0 -49
- package/tests/cli.integration.spec.ts +0 -658
- package/tests/compose.model.spec.ts +0 -51
- package/tests/container-image.model.spec.ts +0 -162
- package/tests/dev-container.model.spec.ts +0 -29
- package/tests/devcontainer-base-image.spec.ts +0 -32
- package/tests/hello-di-inject.scaffold.spec.ts +0 -18
- package/tests/hello-route.contract.spec.ts +0 -94
- package/tests/package-json.order.spec.ts +0 -59
- package/tests/postman-from-openapi.spec.ts +0 -197
- package/tests/seed-devcontainer-templates.ts +0 -40
- package/tests/webapi/devcontainer/codebase-rag-mcp.spec.ts +0 -96
- /package/{src/index.ts → types/src/index.d.ts} +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/** Minimal OpenAPI 3 document shape used for Postman conversion. */ /**
|
|
2
|
+
* Canonical Hello WebAPI OpenAPI document used to generate Postman requests.
|
|
3
|
+
* Keep paths aligned with scaffolded HelloController (`/hello`, `/hello/{id}`).
|
|
4
|
+
*/ export function buildHelloOpenApiDocument(projectName) {
|
|
5
|
+
return {
|
|
6
|
+
openapi: "3.0.3",
|
|
7
|
+
info: {
|
|
8
|
+
title: `${projectName} WebAPI`,
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
description: "Generated from OpenAPI for Postman. Auth/env overlays are applied separately."
|
|
11
|
+
},
|
|
12
|
+
servers: [
|
|
13
|
+
{
|
|
14
|
+
url: "{{baseUrl}}"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
paths: {
|
|
18
|
+
"/hello": {
|
|
19
|
+
get: {
|
|
20
|
+
operationId: "HelloController.getAll",
|
|
21
|
+
summary: "List (anonymous)",
|
|
22
|
+
tags: [
|
|
23
|
+
"Hello"
|
|
24
|
+
],
|
|
25
|
+
parameters: [
|
|
26
|
+
{
|
|
27
|
+
name: "filter",
|
|
28
|
+
in: "query",
|
|
29
|
+
required: false,
|
|
30
|
+
schema: {
|
|
31
|
+
type: "string"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
responses: {
|
|
36
|
+
"200": {
|
|
37
|
+
description: "Successful response"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
post: {
|
|
42
|
+
operationId: "HelloController.create",
|
|
43
|
+
summary: "Create",
|
|
44
|
+
tags: [
|
|
45
|
+
"Hello"
|
|
46
|
+
],
|
|
47
|
+
requestBody: {
|
|
48
|
+
required: true,
|
|
49
|
+
content: {
|
|
50
|
+
"application/json": {
|
|
51
|
+
schema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
message: {
|
|
55
|
+
type: "string"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
required: [
|
|
59
|
+
"message"
|
|
60
|
+
],
|
|
61
|
+
example: {
|
|
62
|
+
message: "hello"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
responses: {
|
|
69
|
+
"200": {
|
|
70
|
+
description: "Successful response"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"/hello/{id}": {
|
|
76
|
+
get: {
|
|
77
|
+
operationId: "HelloController.getOne",
|
|
78
|
+
summary: "Get by id",
|
|
79
|
+
tags: [
|
|
80
|
+
"Hello"
|
|
81
|
+
],
|
|
82
|
+
parameters: [
|
|
83
|
+
{
|
|
84
|
+
name: "id",
|
|
85
|
+
in: "path",
|
|
86
|
+
required: true,
|
|
87
|
+
schema: {
|
|
88
|
+
type: "string"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
responses: {
|
|
93
|
+
"200": {
|
|
94
|
+
description: "Successful response"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
put: {
|
|
99
|
+
operationId: "HelloController.update",
|
|
100
|
+
summary: "Update",
|
|
101
|
+
tags: [
|
|
102
|
+
"Hello"
|
|
103
|
+
],
|
|
104
|
+
parameters: [
|
|
105
|
+
{
|
|
106
|
+
name: "id",
|
|
107
|
+
in: "path",
|
|
108
|
+
required: true,
|
|
109
|
+
schema: {
|
|
110
|
+
type: "string"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
requestBody: {
|
|
115
|
+
required: true,
|
|
116
|
+
content: {
|
|
117
|
+
"application/json": {
|
|
118
|
+
schema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {
|
|
121
|
+
message: {
|
|
122
|
+
type: "string"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
required: [
|
|
126
|
+
"message"
|
|
127
|
+
],
|
|
128
|
+
example: {
|
|
129
|
+
message: "updated"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
responses: {
|
|
136
|
+
"200": {
|
|
137
|
+
description: "Successful response"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
delete: {
|
|
142
|
+
operationId: "HelloController.remove",
|
|
143
|
+
summary: "Delete",
|
|
144
|
+
tags: [
|
|
145
|
+
"Hello"
|
|
146
|
+
],
|
|
147
|
+
parameters: [
|
|
148
|
+
{
|
|
149
|
+
name: "id",
|
|
150
|
+
in: "path",
|
|
151
|
+
required: true,
|
|
152
|
+
schema: {
|
|
153
|
+
type: "string"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
responses: {
|
|
158
|
+
"200": {
|
|
159
|
+
description: "Successful response"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvcG9zdG1hbi9oZWxsby1vcGVuYXBpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBNaW5pbWFsIE9wZW5BUEkgMyBkb2N1bWVudCBzaGFwZSB1c2VkIGZvciBQb3N0bWFuIGNvbnZlcnNpb24uICovXG5leHBvcnQgdHlwZSBTY2FmZm9sZE9wZW5BcGlEb2N1bWVudCA9IHtcblx0b3BlbmFwaTogXCIzLjAuM1wiO1xuXHRpbmZvOiB7IHRpdGxlOiBzdHJpbmc7IHZlcnNpb246IHN0cmluZzsgZGVzY3JpcHRpb24/OiBzdHJpbmcgfTtcblx0c2VydmVycz86IEFycmF5PHsgdXJsOiBzdHJpbmc7IGRlc2NyaXB0aW9uPzogc3RyaW5nIH0+O1xuXHRwYXRoczogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xufTtcblxuLyoqXG4gKiBDYW5vbmljYWwgSGVsbG8gV2ViQVBJIE9wZW5BUEkgZG9jdW1lbnQgdXNlZCB0byBnZW5lcmF0ZSBQb3N0bWFuIHJlcXVlc3RzLlxuICogS2VlcCBwYXRocyBhbGlnbmVkIHdpdGggc2NhZmZvbGRlZCBIZWxsb0NvbnRyb2xsZXIgKGAvaGVsbG9gLCBgL2hlbGxvL3tpZH1gKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkSGVsbG9PcGVuQXBpRG9jdW1lbnQocHJvamVjdE5hbWU6IHN0cmluZyk6IFNjYWZmb2xkT3BlbkFwaURvY3VtZW50IHtcblx0cmV0dXJuIHtcblx0XHRvcGVuYXBpOiBcIjMuMC4zXCIsXG5cdFx0aW5mbzoge1xuXHRcdFx0dGl0bGU6IGAke3Byb2plY3ROYW1lfSBXZWJBUElgLFxuXHRcdFx0dmVyc2lvbjogXCIxLjAuMFwiLFxuXHRcdFx0ZGVzY3JpcHRpb246XG5cdFx0XHRcdFwiR2VuZXJhdGVkIGZyb20gT3BlbkFQSSBmb3IgUG9zdG1hbi4gQXV0aC9lbnYgb3ZlcmxheXMgYXJlIGFwcGxpZWQgc2VwYXJhdGVseS5cIixcblx0XHR9LFxuXHRcdHNlcnZlcnM6IFt7IHVybDogXCJ7e2Jhc2VVcmx9fVwiIH1dLFxuXHRcdHBhdGhzOiB7XG5cdFx0XHRcIi9oZWxsb1wiOiB7XG5cdFx0XHRcdGdldDoge1xuXHRcdFx0XHRcdG9wZXJhdGlvbklkOiBcIkhlbGxvQ29udHJvbGxlci5nZXRBbGxcIixcblx0XHRcdFx0XHRzdW1tYXJ5OiBcIkxpc3QgKGFub255bW91cylcIixcblx0XHRcdFx0XHR0YWdzOiBbXCJIZWxsb1wiXSxcblx0XHRcdFx0XHRwYXJhbWV0ZXJzOiBbXG5cdFx0XHRcdFx0XHR7IG5hbWU6IFwiZmlsdGVyXCIsIGluOiBcInF1ZXJ5XCIsIHJlcXVpcmVkOiBmYWxzZSwgc2NoZW1hOiB7IHR5cGU6IFwic3RyaW5nXCIgfSB9LFxuXHRcdFx0XHRcdF0sXG5cdFx0XHRcdFx0cmVzcG9uc2VzOiB7IFwiMjAwXCI6IHsgZGVzY3JpcHRpb246IFwiU3VjY2Vzc2Z1bCByZXNwb25zZVwiIH0gfSxcblx0XHRcdFx0fSxcblx0XHRcdFx0cG9zdDoge1xuXHRcdFx0XHRcdG9wZXJhdGlvbklkOiBcIkhlbGxvQ29udHJvbGxlci5jcmVhdGVcIixcblx0XHRcdFx0XHRzdW1tYXJ5OiBcIkNyZWF0ZVwiLFxuXHRcdFx0XHRcdHRhZ3M6IFtcIkhlbGxvXCJdLFxuXHRcdFx0XHRcdHJlcXVlc3RCb2R5OiB7XG5cdFx0XHRcdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdGNvbnRlbnQ6IHtcblx0XHRcdFx0XHRcdFx0XCJhcHBsaWNhdGlvbi9qc29uXCI6IHtcblx0XHRcdFx0XHRcdFx0XHRzY2hlbWE6IHtcblx0XHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwib2JqZWN0XCIsXG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9wZXJ0aWVzOiB7IG1lc3NhZ2U6IHsgdHlwZTogXCJzdHJpbmdcIiB9IH0sXG5cdFx0XHRcdFx0XHRcdFx0XHRyZXF1aXJlZDogW1wibWVzc2FnZVwiXSxcblx0XHRcdFx0XHRcdFx0XHRcdGV4YW1wbGU6IHsgbWVzc2FnZTogXCJoZWxsb1wiIH0sXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRyZXNwb25zZXM6IHsgXCIyMDBcIjogeyBkZXNjcmlwdGlvbjogXCJTdWNjZXNzZnVsIHJlc3BvbnNlXCIgfSB9LFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHRcdFwiL2hlbGxvL3tpZH1cIjoge1xuXHRcdFx0XHRnZXQ6IHtcblx0XHRcdFx0XHRvcGVyYXRpb25JZDogXCJIZWxsb0NvbnRyb2xsZXIuZ2V0T25lXCIsXG5cdFx0XHRcdFx0c3VtbWFyeTogXCJHZXQgYnkgaWRcIixcblx0XHRcdFx0XHR0YWdzOiBbXCJIZWxsb1wiXSxcblx0XHRcdFx0XHRwYXJhbWV0ZXJzOiBbeyBuYW1lOiBcImlkXCIsIGluOiBcInBhdGhcIiwgcmVxdWlyZWQ6IHRydWUsIHNjaGVtYTogeyB0eXBlOiBcInN0cmluZ1wiIH0gfV0sXG5cdFx0XHRcdFx0cmVzcG9uc2VzOiB7IFwiMjAwXCI6IHsgZGVzY3JpcHRpb246IFwiU3VjY2Vzc2Z1bCByZXNwb25zZVwiIH0gfSxcblx0XHRcdFx0fSxcblx0XHRcdFx0cHV0OiB7XG5cdFx0XHRcdFx0b3BlcmF0aW9uSWQ6IFwiSGVsbG9Db250cm9sbGVyLnVwZGF0ZVwiLFxuXHRcdFx0XHRcdHN1bW1hcnk6IFwiVXBkYXRlXCIsXG5cdFx0XHRcdFx0dGFnczogW1wiSGVsbG9cIl0sXG5cdFx0XHRcdFx0cGFyYW1ldGVyczogW3sgbmFtZTogXCJpZFwiLCBpbjogXCJwYXRoXCIsIHJlcXVpcmVkOiB0cnVlLCBzY2hlbWE6IHsgdHlwZTogXCJzdHJpbmdcIiB9IH1dLFxuXHRcdFx0XHRcdHJlcXVlc3RCb2R5OiB7XG5cdFx0XHRcdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdGNvbnRlbnQ6IHtcblx0XHRcdFx0XHRcdFx0XCJhcHBsaWNhdGlvbi9qc29uXCI6IHtcblx0XHRcdFx0XHRcdFx0XHRzY2hlbWE6IHtcblx0XHRcdFx0XHRcdFx0XHRcdHR5cGU6IFwib2JqZWN0XCIsXG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9wZXJ0aWVzOiB7IG1lc3NhZ2U6IHsgdHlwZTogXCJzdHJpbmdcIiB9IH0sXG5cdFx0XHRcdFx0XHRcdFx0XHRyZXF1aXJlZDogW1wibWVzc2FnZVwiXSxcblx0XHRcdFx0XHRcdFx0XHRcdGV4YW1wbGU6IHsgbWVzc2FnZTogXCJ1cGRhdGVkXCIgfSxcblx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHJlc3BvbnNlczogeyBcIjIwMFwiOiB7IGRlc2NyaXB0aW9uOiBcIlN1Y2Nlc3NmdWwgcmVzcG9uc2VcIiB9IH0sXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGRlbGV0ZToge1xuXHRcdFx0XHRcdG9wZXJhdGlvbklkOiBcIkhlbGxvQ29udHJvbGxlci5yZW1vdmVcIixcblx0XHRcdFx0XHRzdW1tYXJ5OiBcIkRlbGV0ZVwiLFxuXHRcdFx0XHRcdHRhZ3M6IFtcIkhlbGxvXCJdLFxuXHRcdFx0XHRcdHBhcmFtZXRlcnM6IFt7IG5hbWU6IFwiaWRcIiwgaW46IFwicGF0aFwiLCByZXF1aXJlZDogdHJ1ZSwgc2NoZW1hOiB7IHR5cGU6IFwic3RyaW5nXCIgfSB9XSxcblx0XHRcdFx0XHRyZXNwb25zZXM6IHsgXCIyMDBcIjogeyBkZXNjcmlwdGlvbjogXCJTdWNjZXNzZnVsIHJlc3BvbnNlXCIgfSB9LFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9LFxuXHR9O1xufVxuIl0sIm5hbWVzIjpbImJ1aWxkSGVsbG9PcGVuQXBpRG9jdW1lbnQiLCJwcm9qZWN0TmFtZSIsIm9wZW5hcGkiLCJpbmZvIiwidGl0bGUiLCJ2ZXJzaW9uIiwiZGVzY3JpcHRpb24iLCJzZXJ2ZXJzIiwidXJsIiwicGF0aHMiLCJnZXQiLCJvcGVyYXRpb25JZCIsInN1bW1hcnkiLCJ0YWdzIiwicGFyYW1ldGVycyIsIm5hbWUiLCJpbiIsInJlcXVpcmVkIiwic2NoZW1hIiwidHlwZSIsInJlc3BvbnNlcyIsInBvc3QiLCJyZXF1ZXN0Qm9keSIsImNvbnRlbnQiLCJwcm9wZXJ0aWVzIiwibWVzc2FnZSIsImV4YW1wbGUiLCJwdXQiLCJkZWxldGUiXSwibWFwcGluZ3MiOiJBQUFBLGtFQUFrRSxHQVFsRTs7O0NBR0MsR0FDRCxPQUFPLFNBQVNBLDBCQUEwQkMsV0FBbUI7SUFDNUQsT0FBTztRQUNOQyxTQUFTO1FBQ1RDLE1BQU07WUFDTEMsT0FBTyxHQUFHSCxZQUFZLE9BQU8sQ0FBQztZQUM5QkksU0FBUztZQUNUQyxhQUNDO1FBQ0Y7UUFDQUMsU0FBUztZQUFDO2dCQUFFQyxLQUFLO1lBQWM7U0FBRTtRQUNqQ0MsT0FBTztZQUNOLFVBQVU7Z0JBQ1RDLEtBQUs7b0JBQ0pDLGFBQWE7b0JBQ2JDLFNBQVM7b0JBQ1RDLE1BQU07d0JBQUM7cUJBQVE7b0JBQ2ZDLFlBQVk7d0JBQ1g7NEJBQUVDLE1BQU07NEJBQVVDLElBQUk7NEJBQVNDLFVBQVU7NEJBQU9DLFFBQVE7Z0NBQUVDLE1BQU07NEJBQVM7d0JBQUU7cUJBQzNFO29CQUNEQyxXQUFXO3dCQUFFLE9BQU87NEJBQUVkLGFBQWE7d0JBQXNCO29CQUFFO2dCQUM1RDtnQkFDQWUsTUFBTTtvQkFDTFYsYUFBYTtvQkFDYkMsU0FBUztvQkFDVEMsTUFBTTt3QkFBQztxQkFBUTtvQkFDZlMsYUFBYTt3QkFDWkwsVUFBVTt3QkFDVk0sU0FBUzs0QkFDUixvQkFBb0I7Z0NBQ25CTCxRQUFRO29DQUNQQyxNQUFNO29DQUNOSyxZQUFZO3dDQUFFQyxTQUFTOzRDQUFFTixNQUFNO3dDQUFTO29DQUFFO29DQUMxQ0YsVUFBVTt3Q0FBQztxQ0FBVTtvQ0FDckJTLFNBQVM7d0NBQUVELFNBQVM7b0NBQVE7Z0NBQzdCOzRCQUNEO3dCQUNEO29CQUNEO29CQUNBTCxXQUFXO3dCQUFFLE9BQU87NEJBQUVkLGFBQWE7d0JBQXNCO29CQUFFO2dCQUM1RDtZQUNEO1lBQ0EsZUFBZTtnQkFDZEksS0FBSztvQkFDSkMsYUFBYTtvQkFDYkMsU0FBUztvQkFDVEMsTUFBTTt3QkFBQztxQkFBUTtvQkFDZkMsWUFBWTt3QkFBQzs0QkFBRUMsTUFBTTs0QkFBTUMsSUFBSTs0QkFBUUMsVUFBVTs0QkFBTUMsUUFBUTtnQ0FBRUMsTUFBTTs0QkFBUzt3QkFBRTtxQkFBRTtvQkFDcEZDLFdBQVc7d0JBQUUsT0FBTzs0QkFBRWQsYUFBYTt3QkFBc0I7b0JBQUU7Z0JBQzVEO2dCQUNBcUIsS0FBSztvQkFDSmhCLGFBQWE7b0JBQ2JDLFNBQVM7b0JBQ1RDLE1BQU07d0JBQUM7cUJBQVE7b0JBQ2ZDLFlBQVk7d0JBQUM7NEJBQUVDLE1BQU07NEJBQU1DLElBQUk7NEJBQVFDLFVBQVU7NEJBQU1DLFFBQVE7Z0NBQUVDLE1BQU07NEJBQVM7d0JBQUU7cUJBQUU7b0JBQ3BGRyxhQUFhO3dCQUNaTCxVQUFVO3dCQUNWTSxTQUFTOzRCQUNSLG9CQUFvQjtnQ0FDbkJMLFFBQVE7b0NBQ1BDLE1BQU07b0NBQ05LLFlBQVk7d0NBQUVDLFNBQVM7NENBQUVOLE1BQU07d0NBQVM7b0NBQUU7b0NBQzFDRixVQUFVO3dDQUFDO3FDQUFVO29DQUNyQlMsU0FBUzt3Q0FBRUQsU0FBUztvQ0FBVTtnQ0FDL0I7NEJBQ0Q7d0JBQ0Q7b0JBQ0Q7b0JBQ0FMLFdBQVc7d0JBQUUsT0FBTzs0QkFBRWQsYUFBYTt3QkFBc0I7b0JBQUU7Z0JBQzVEO2dCQUNBc0IsUUFBUTtvQkFDUGpCLGFBQWE7b0JBQ2JDLFNBQVM7b0JBQ1RDLE1BQU07d0JBQUM7cUJBQVE7b0JBQ2ZDLFlBQVk7d0JBQUM7NEJBQUVDLE1BQU07NEJBQU1DLElBQUk7NEJBQVFDLFVBQVU7NEJBQU1DLFFBQVE7Z0NBQUVDLE1BQU07NEJBQVM7d0JBQUU7cUJBQUU7b0JBQ3BGQyxXQUFXO3dCQUFFLE9BQU87NEJBQUVkLGFBQWE7d0JBQXNCO29CQUFFO2dCQUM1RDtZQUNEO1FBQ0Q7SUFDRDtBQUNEIn0=
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { openApiPathParamsToColon } from "./openapi-to-postman.js";
|
|
3
|
+
function yamlQuote(value) {
|
|
4
|
+
if (/[:#{}[\],&*?|<>=!%@`]/.test(value) || value.includes("\n") || value === "") {
|
|
5
|
+
return JSON.stringify(value);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
/** Local View / Native Git environment (YAML). */ export function buildEnvironmentYaml(name, auth, options) {
|
|
10
|
+
const values = [
|
|
11
|
+
{
|
|
12
|
+
key: "baseUrl",
|
|
13
|
+
value: "http://localhost:3000"
|
|
14
|
+
}
|
|
15
|
+
];
|
|
16
|
+
if (auth?.auth0Domain) {
|
|
17
|
+
values.push({
|
|
18
|
+
key: "auth0Domain",
|
|
19
|
+
value: auth.auth0Domain
|
|
20
|
+
}, {
|
|
21
|
+
key: "auth0Audience",
|
|
22
|
+
value: auth.auth0Audience ?? ""
|
|
23
|
+
}, {
|
|
24
|
+
key: "auth0ClientId",
|
|
25
|
+
value: auth.auth0ClientId ?? ""
|
|
26
|
+
}, {
|
|
27
|
+
key: "authUrl",
|
|
28
|
+
value: `https://${auth.auth0Domain}/authorize?audience=${auth.auth0Audience ?? ""}`
|
|
29
|
+
}, {
|
|
30
|
+
key: "accessTokenUrl",
|
|
31
|
+
value: `https://${auth.auth0Domain}/oauth/token`
|
|
32
|
+
}, {
|
|
33
|
+
key: "callbackUrl",
|
|
34
|
+
value: options.callbacks[0]
|
|
35
|
+
}, {
|
|
36
|
+
key: "scope",
|
|
37
|
+
value: options.scopes
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const lines = [
|
|
41
|
+
`name: ${yamlQuote(name)}`,
|
|
42
|
+
"values:"
|
|
43
|
+
];
|
|
44
|
+
for (const v of values){
|
|
45
|
+
lines.push(` - key: ${v.key}`);
|
|
46
|
+
lines.push(` value: ${yamlQuote(v.value)}`);
|
|
47
|
+
lines.push(" enabled: true");
|
|
48
|
+
}
|
|
49
|
+
return `${lines.join("\n")}\n`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build Postman Local View multi-file YAML from a v2.1 collection (routes)
|
|
53
|
+
* plus hand-authored Auth0 overlay.
|
|
54
|
+
*/ export function buildLocalViewFilesFromCollection(collection, projectName, auth, options) {
|
|
55
|
+
const collectionDir = `postman/collections/${projectName} WebAPI`;
|
|
56
|
+
const files = [];
|
|
57
|
+
const authBlock = auth?.auth0Domain ? [
|
|
58
|
+
"auth:",
|
|
59
|
+
` - id: ${randomUUID()}`,
|
|
60
|
+
" type: oauth2",
|
|
61
|
+
" name: OAuth 2.0",
|
|
62
|
+
" credentials:",
|
|
63
|
+
" addTokenTo: header",
|
|
64
|
+
" grant_type: authorization_code_with_pkce",
|
|
65
|
+
` authUrl: https://${auth.auth0Domain}/authorize?audience=${auth.auth0Audience ?? ""}`,
|
|
66
|
+
` accessTokenUrl: https://${auth.auth0Domain}/oauth/token`,
|
|
67
|
+
` clientId: ${yamlQuote(auth.auth0ClientId ?? "")}`,
|
|
68
|
+
` scope: ${yamlQuote(options.scopes)}`,
|
|
69
|
+
` redirect_uri: ${options.callbacks[0]}`,
|
|
70
|
+
" useBrowser: true",
|
|
71
|
+
" challengeAlgorithm: S256",
|
|
72
|
+
" client_authentication: body",
|
|
73
|
+
' clientSecret: ""',
|
|
74
|
+
` tokenName: ${yamlQuote(`${projectName} Access Token`)}`,
|
|
75
|
+
""
|
|
76
|
+
].join("\n") : "";
|
|
77
|
+
files.push({
|
|
78
|
+
filePath: `${collectionDir}/.resources/definition.yaml`,
|
|
79
|
+
content: [
|
|
80
|
+
"$kind: collection",
|
|
81
|
+
`name: ${yamlQuote(`${projectName} WebAPI`)}`,
|
|
82
|
+
"schemaVersion: '3.0'",
|
|
83
|
+
"description: >-",
|
|
84
|
+
" Open this project root in Postman Local View (Files → Open folder).",
|
|
85
|
+
" Select the Local environment, then Authorization → Get New Access Token (PKCE).",
|
|
86
|
+
" Route requests are generated from OpenAPI; Auth0 overlay is hand-authored.",
|
|
87
|
+
authBlock
|
|
88
|
+
].filter((l)=>l !== undefined).join("\n").replace(/\n+$/, "\n")
|
|
89
|
+
});
|
|
90
|
+
let folderOrder = 1000;
|
|
91
|
+
for (const folder of collection.item ?? []){
|
|
92
|
+
if (folder.item == null) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const folderName = folder.name ?? "Requests";
|
|
96
|
+
files.push({
|
|
97
|
+
filePath: `${collectionDir}/${folderName}/.resources/definition.yaml`,
|
|
98
|
+
content: [
|
|
99
|
+
"$kind: folder",
|
|
100
|
+
`name: ${yamlQuote(folderName)}`,
|
|
101
|
+
`order: ${folderOrder}`,
|
|
102
|
+
""
|
|
103
|
+
].join("\n")
|
|
104
|
+
});
|
|
105
|
+
folderOrder += 1000;
|
|
106
|
+
let requestOrder = 1000;
|
|
107
|
+
for (const child of folder.item){
|
|
108
|
+
const yaml = requestToLocalViewYaml(child, requestOrder);
|
|
109
|
+
if (yaml == null) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const fileName = `${sanitizeFileName(child.name ?? "Request")}.request.yaml`;
|
|
113
|
+
files.push({
|
|
114
|
+
filePath: `${collectionDir}/${folderName}/${fileName}`,
|
|
115
|
+
content: yaml
|
|
116
|
+
});
|
|
117
|
+
requestOrder += 1000;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return files;
|
|
121
|
+
}
|
|
122
|
+
function requestToLocalViewYaml(item, order) {
|
|
123
|
+
const request = item.request;
|
|
124
|
+
if (request == null) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
128
|
+
const url = requestUrlForLocalView(request);
|
|
129
|
+
const lines = [
|
|
130
|
+
"$kind: http-request",
|
|
131
|
+
`name: ${yamlQuote(item.name ?? method)}`,
|
|
132
|
+
`method: ${method}`,
|
|
133
|
+
`url: ${yamlQuote(url)}`
|
|
134
|
+
];
|
|
135
|
+
if (request.auth?.type === "noauth") {
|
|
136
|
+
lines.push("auth:", " type: noauth");
|
|
137
|
+
}
|
|
138
|
+
const contentType = request.header?.find((h)=>h.key.toLowerCase() === "content-type")?.value;
|
|
139
|
+
const rawBody = request.body?.raw?.trim();
|
|
140
|
+
if (rawBody) {
|
|
141
|
+
lines.push("headers:");
|
|
142
|
+
lines.push(` Content-Type: ${contentType ?? "application/json"}`);
|
|
143
|
+
lines.push("body:");
|
|
144
|
+
lines.push(" type: json");
|
|
145
|
+
lines.push(" content: |-");
|
|
146
|
+
for (const bodyLine of rawBody.split("\n")){
|
|
147
|
+
lines.push(` ${bodyLine}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
lines.push(`order: ${order}`, "");
|
|
151
|
+
return lines.join("\n");
|
|
152
|
+
}
|
|
153
|
+
function requestUrlForLocalView(request) {
|
|
154
|
+
const url = request.url;
|
|
155
|
+
if (typeof url === "string") {
|
|
156
|
+
return openApiPathParamsToColon(url);
|
|
157
|
+
}
|
|
158
|
+
if (url?.raw) {
|
|
159
|
+
return openApiPathParamsToColon(url.raw);
|
|
160
|
+
}
|
|
161
|
+
const host = url?.host?.[0] ?? "{{baseUrl}}";
|
|
162
|
+
const path = (url?.path ?? []).map((segment)=>openApiPathParamsToColon(String(segment))).join("/");
|
|
163
|
+
return path ? `${host}/${path}` : host;
|
|
164
|
+
}
|
|
165
|
+
function sanitizeFileName(name) {
|
|
166
|
+
return name.replace(/[^\w\s()-]+/g, "").trim() || "Request";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvcG9zdG1hbi9sb2NhbC12aWV3LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7XG5cdHR5cGUgQXV0aDBFbnYsXG5cdG9wZW5BcGlQYXRoUGFyYW1zVG9Db2xvbixcblx0dHlwZSBQb3N0bWFuQ29sbGVjdGlvbixcblx0dHlwZSBQb3N0bWFuSXRlbSxcblx0dHlwZSBQb3N0bWFuUmVxdWVzdCxcbn0gZnJvbSBcIi4vb3BlbmFwaS10by1wb3N0bWFuLmpzXCI7XG5cbmZ1bmN0aW9uIHlhbWxRdW90ZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcblx0aWYgKC9bOiN7fVtcXF0sJio/fDw+PSElQGBdLy50ZXN0KHZhbHVlKSB8fCB2YWx1ZS5pbmNsdWRlcyhcIlxcblwiKSB8fCB2YWx1ZSA9PT0gXCJcIikge1xuXHRcdHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cdH1cblx0cmV0dXJuIHZhbHVlO1xufVxuXG4vKiogTG9jYWwgVmlldyAvIE5hdGl2ZSBHaXQgZW52aXJvbm1lbnQgKFlBTUwpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkRW52aXJvbm1lbnRZYW1sKFxuXHRuYW1lOiBzdHJpbmcsXG5cdGF1dGg6IEF1dGgwRW52IHwgdW5kZWZpbmVkLFxuXHRvcHRpb25zOiB7IGNhbGxiYWNrczogcmVhZG9ubHkgc3RyaW5nW107IHNjb3Blczogc3RyaW5nIH0sXG4pOiBzdHJpbmcge1xuXHRjb25zdCB2YWx1ZXM6IEFycmF5PHsga2V5OiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfT4gPSBbXG5cdFx0eyBrZXk6IFwiYmFzZVVybFwiLCB2YWx1ZTogXCJodHRwOi8vbG9jYWxob3N0OjMwMDBcIiB9LFxuXHRdO1xuXHRpZiAoYXV0aD8uYXV0aDBEb21haW4pIHtcblx0XHR2YWx1ZXMucHVzaChcblx0XHRcdHsga2V5OiBcImF1dGgwRG9tYWluXCIsIHZhbHVlOiBhdXRoLmF1dGgwRG9tYWluIH0sXG5cdFx0XHR7IGtleTogXCJhdXRoMEF1ZGllbmNlXCIsIHZhbHVlOiBhdXRoLmF1dGgwQXVkaWVuY2UgPz8gXCJcIiB9LFxuXHRcdFx0eyBrZXk6IFwiYXV0aDBDbGllbnRJZFwiLCB2YWx1ZTogYXV0aC5hdXRoMENsaWVudElkID8/IFwiXCIgfSxcblx0XHRcdHtcblx0XHRcdFx0a2V5OiBcImF1dGhVcmxcIixcblx0XHRcdFx0dmFsdWU6IGBodHRwczovLyR7YXV0aC5hdXRoMERvbWFpbn0vYXV0aG9yaXplP2F1ZGllbmNlPSR7YXV0aC5hdXRoMEF1ZGllbmNlID8/IFwiXCJ9YCxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGtleTogXCJhY2Nlc3NUb2tlblVybFwiLFxuXHRcdFx0XHR2YWx1ZTogYGh0dHBzOi8vJHthdXRoLmF1dGgwRG9tYWlufS9vYXV0aC90b2tlbmAsXG5cdFx0XHR9LFxuXHRcdFx0eyBrZXk6IFwiY2FsbGJhY2tVcmxcIiwgdmFsdWU6IG9wdGlvbnMuY2FsbGJhY2tzWzBdIH0sXG5cdFx0XHR7IGtleTogXCJzY29wZVwiLCB2YWx1ZTogb3B0aW9ucy5zY29wZXMgfSxcblx0XHQpO1xuXHR9XG5cblx0Y29uc3QgbGluZXMgPSBbYG5hbWU6ICR7eWFtbFF1b3RlKG5hbWUpfWAsIFwidmFsdWVzOlwiXTtcblx0Zm9yIChjb25zdCB2IG9mIHZhbHVlcykge1xuXHRcdGxpbmVzLnB1c2goYCAgLSBrZXk6ICR7di5rZXl9YCk7XG5cdFx0bGluZXMucHVzaChgICAgIHZhbHVlOiAke3lhbWxRdW90ZSh2LnZhbHVlKX1gKTtcblx0XHRsaW5lcy5wdXNoKFwiICAgIGVuYWJsZWQ6IHRydWVcIik7XG5cdH1cblx0cmV0dXJuIGAke2xpbmVzLmpvaW4oXCJcXG5cIil9XFxuYDtcbn1cblxuLyoqXG4gKiBCdWlsZCBQb3N0bWFuIExvY2FsIFZpZXcgbXVsdGktZmlsZSBZQU1MIGZyb20gYSB2Mi4xIGNvbGxlY3Rpb24gKHJvdXRlcylcbiAqIHBsdXMgaGFuZC1hdXRob3JlZCBBdXRoMCBvdmVybGF5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRMb2NhbFZpZXdGaWxlc0Zyb21Db2xsZWN0aW9uKFxuXHRjb2xsZWN0aW9uOiBQb3N0bWFuQ29sbGVjdGlvbixcblx0cHJvamVjdE5hbWU6IHN0cmluZyxcblx0YXV0aDogQXV0aDBFbnYgfCB1bmRlZmluZWQsXG5cdG9wdGlvbnM6IHsgY2FsbGJhY2tzOiByZWFkb25seSBzdHJpbmdbXTsgc2NvcGVzOiBzdHJpbmcgfSxcbik6IEFycmF5PHsgZmlsZVBhdGg6IHN0cmluZzsgY29udGVudDogc3RyaW5nIH0+IHtcblx0Y29uc3QgY29sbGVjdGlvbkRpciA9IGBwb3N0bWFuL2NvbGxlY3Rpb25zLyR7cHJvamVjdE5hbWV9IFdlYkFQSWA7XG5cdGNvbnN0IGZpbGVzOiBBcnJheTx7IGZpbGVQYXRoOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB9PiA9IFtdO1xuXG5cdGNvbnN0IGF1dGhCbG9jayA9IGF1dGg/LmF1dGgwRG9tYWluXG5cdFx0PyBbXG5cdFx0XHRcdFwiYXV0aDpcIixcblx0XHRcdFx0YCAgLSBpZDogJHtyYW5kb21VVUlEKCl9YCxcblx0XHRcdFx0XCIgICAgdHlwZTogb2F1dGgyXCIsXG5cdFx0XHRcdFwiICAgIG5hbWU6IE9BdXRoIDIuMFwiLFxuXHRcdFx0XHRcIiAgICBjcmVkZW50aWFsczpcIixcblx0XHRcdFx0XCIgICAgICBhZGRUb2tlblRvOiBoZWFkZXJcIixcblx0XHRcdFx0XCIgICAgICBncmFudF90eXBlOiBhdXRob3JpemF0aW9uX2NvZGVfd2l0aF9wa2NlXCIsXG5cdFx0XHRcdGAgICAgICBhdXRoVXJsOiBodHRwczovLyR7YXV0aC5hdXRoMERvbWFpbn0vYXV0aG9yaXplP2F1ZGllbmNlPSR7YXV0aC5hdXRoMEF1ZGllbmNlID8/IFwiXCJ9YCxcblx0XHRcdFx0YCAgICAgIGFjY2Vzc1Rva2VuVXJsOiBodHRwczovLyR7YXV0aC5hdXRoMERvbWFpbn0vb2F1dGgvdG9rZW5gLFxuXHRcdFx0XHRgICAgICAgY2xpZW50SWQ6ICR7eWFtbFF1b3RlKGF1dGguYXV0aDBDbGllbnRJZCA/PyBcIlwiKX1gLFxuXHRcdFx0XHRgICAgICAgc2NvcGU6ICR7eWFtbFF1b3RlKG9wdGlvbnMuc2NvcGVzKX1gLFxuXHRcdFx0XHRgICAgICAgcmVkaXJlY3RfdXJpOiAke29wdGlvbnMuY2FsbGJhY2tzWzBdfWAsXG5cdFx0XHRcdFwiICAgICAgdXNlQnJvd3NlcjogdHJ1ZVwiLFxuXHRcdFx0XHRcIiAgICAgIGNoYWxsZW5nZUFsZ29yaXRobTogUzI1NlwiLFxuXHRcdFx0XHRcIiAgICAgIGNsaWVudF9hdXRoZW50aWNhdGlvbjogYm9keVwiLFxuXHRcdFx0XHQnICAgICAgY2xpZW50U2VjcmV0OiBcIlwiJyxcblx0XHRcdFx0YCAgICAgIHRva2VuTmFtZTogJHt5YW1sUXVvdGUoYCR7cHJvamVjdE5hbWV9IEFjY2VzcyBUb2tlbmApfWAsXG5cdFx0XHRcdFwiXCIsXG5cdFx0XHRdLmpvaW4oXCJcXG5cIilcblx0XHQ6IFwiXCI7XG5cblx0ZmlsZXMucHVzaCh7XG5cdFx0ZmlsZVBhdGg6IGAke2NvbGxlY3Rpb25EaXJ9Ly5yZXNvdXJjZXMvZGVmaW5pdGlvbi55YW1sYCxcblx0XHRjb250ZW50OiBbXG5cdFx0XHRcIiRraW5kOiBjb2xsZWN0aW9uXCIsXG5cdFx0XHRgbmFtZTogJHt5YW1sUXVvdGUoYCR7cHJvamVjdE5hbWV9IFdlYkFQSWApfWAsXG5cdFx0XHRcInNjaGVtYVZlcnNpb246ICczLjAnXCIsXG5cdFx0XHRcImRlc2NyaXB0aW9uOiA+LVwiLFxuXHRcdFx0XCIgIE9wZW4gdGhpcyBwcm9qZWN0IHJvb3QgaW4gUG9zdG1hbiBMb2NhbCBWaWV3IChGaWxlcyDihpIgT3BlbiBmb2xkZXIpLlwiLFxuXHRcdFx0XCIgIFNlbGVjdCB0aGUgTG9jYWwgZW52aXJvbm1lbnQsIHRoZW4gQXV0aG9yaXphdGlvbiDihpIgR2V0IE5ldyBBY2Nlc3MgVG9rZW4gKFBLQ0UpLlwiLFxuXHRcdFx0XCIgIFJvdXRlIHJlcXVlc3RzIGFyZSBnZW5lcmF0ZWQgZnJvbSBPcGVuQVBJOyBBdXRoMCBvdmVybGF5IGlzIGhhbmQtYXV0aG9yZWQuXCIsXG5cdFx0XHRhdXRoQmxvY2ssXG5cdFx0XVxuXHRcdFx0LmZpbHRlcigobCkgPT4gbCAhPT0gdW5kZWZpbmVkKVxuXHRcdFx0LmpvaW4oXCJcXG5cIilcblx0XHRcdC5yZXBsYWNlKC9cXG4rJC8sIFwiXFxuXCIpLFxuXHR9KTtcblxuXHRsZXQgZm9sZGVyT3JkZXIgPSAxMDAwO1xuXHRmb3IgKGNvbnN0IGZvbGRlciBvZiBjb2xsZWN0aW9uLml0ZW0gPz8gW10pIHtcblx0XHRpZiAoZm9sZGVyLml0ZW0gPT0gbnVsbCkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXHRcdGNvbnN0IGZvbGRlck5hbWUgPSBmb2xkZXIubmFtZSA/PyBcIlJlcXVlc3RzXCI7XG5cdFx0ZmlsZXMucHVzaCh7XG5cdFx0XHRmaWxlUGF0aDogYCR7Y29sbGVjdGlvbkRpcn0vJHtmb2xkZXJOYW1lfS8ucmVzb3VyY2VzL2RlZmluaXRpb24ueWFtbGAsXG5cdFx0XHRjb250ZW50OiBbXG5cdFx0XHRcdFwiJGtpbmQ6IGZvbGRlclwiLFxuXHRcdFx0XHRgbmFtZTogJHt5YW1sUXVvdGUoZm9sZGVyTmFtZSl9YCxcblx0XHRcdFx0YG9yZGVyOiAke2ZvbGRlck9yZGVyfWAsXG5cdFx0XHRcdFwiXCIsXG5cdFx0XHRdLmpvaW4oXCJcXG5cIiksXG5cdFx0fSk7XG5cdFx0Zm9sZGVyT3JkZXIgKz0gMTAwMDtcblxuXHRcdGxldCByZXF1ZXN0T3JkZXIgPSAxMDAwO1xuXHRcdGZvciAoY29uc3QgY2hpbGQgb2YgZm9sZGVyLml0ZW0pIHtcblx0XHRcdGNvbnN0IHlhbWwgPSByZXF1ZXN0VG9Mb2NhbFZpZXdZYW1sKGNoaWxkLCByZXF1ZXN0T3JkZXIpO1xuXHRcdFx0aWYgKHlhbWwgPT0gbnVsbCkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IGZpbGVOYW1lID0gYCR7c2FuaXRpemVGaWxlTmFtZShjaGlsZC5uYW1lID8/IFwiUmVxdWVzdFwiKX0ucmVxdWVzdC55YW1sYDtcblx0XHRcdGZpbGVzLnB1c2goe1xuXHRcdFx0XHRmaWxlUGF0aDogYCR7Y29sbGVjdGlvbkRpcn0vJHtmb2xkZXJOYW1lfS8ke2ZpbGVOYW1lfWAsXG5cdFx0XHRcdGNvbnRlbnQ6IHlhbWwsXG5cdFx0XHR9KTtcblx0XHRcdHJlcXVlc3RPcmRlciArPSAxMDAwO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBmaWxlcztcbn1cblxuZnVuY3Rpb24gcmVxdWVzdFRvTG9jYWxWaWV3WWFtbChpdGVtOiBQb3N0bWFuSXRlbSwgb3JkZXI6IG51bWJlcik6IHN0cmluZyB8IG51bGwge1xuXHRjb25zdCByZXF1ZXN0ID0gaXRlbS5yZXF1ZXN0O1xuXHRpZiAocmVxdWVzdCA9PSBudWxsKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0Y29uc3QgbWV0aG9kID0gKHJlcXVlc3QubWV0aG9kID8/IFwiR0VUXCIpLnRvVXBwZXJDYXNlKCk7XG5cdGNvbnN0IHVybCA9IHJlcXVlc3RVcmxGb3JMb2NhbFZpZXcocmVxdWVzdCk7XG5cdGNvbnN0IGxpbmVzID0gW1xuXHRcdFwiJGtpbmQ6IGh0dHAtcmVxdWVzdFwiLFxuXHRcdGBuYW1lOiAke3lhbWxRdW90ZShpdGVtLm5hbWUgPz8gbWV0aG9kKX1gLFxuXHRcdGBtZXRob2Q6ICR7bWV0aG9kfWAsXG5cdFx0YHVybDogJHt5YW1sUXVvdGUodXJsKX1gLFxuXHRdO1xuXG5cdGlmIChyZXF1ZXN0LmF1dGg/LnR5cGUgPT09IFwibm9hdXRoXCIpIHtcblx0XHRsaW5lcy5wdXNoKFwiYXV0aDpcIiwgXCIgIHR5cGU6IG5vYXV0aFwiKTtcblx0fVxuXG5cdGNvbnN0IGNvbnRlbnRUeXBlID0gcmVxdWVzdC5oZWFkZXI/LmZpbmQoXG5cdFx0KGgpID0+IGgua2V5LnRvTG93ZXJDYXNlKCkgPT09IFwiY29udGVudC10eXBlXCIsXG5cdCk/LnZhbHVlO1xuXHRjb25zdCByYXdCb2R5ID0gcmVxdWVzdC5ib2R5Py5yYXc/LnRyaW0oKTtcblx0aWYgKHJhd0JvZHkpIHtcblx0XHRsaW5lcy5wdXNoKFwiaGVhZGVyczpcIik7XG5cdFx0bGluZXMucHVzaChgICBDb250ZW50LVR5cGU6ICR7Y29udGVudFR5cGUgPz8gXCJhcHBsaWNhdGlvbi9qc29uXCJ9YCk7XG5cdFx0bGluZXMucHVzaChcImJvZHk6XCIpO1xuXHRcdGxpbmVzLnB1c2goXCIgIHR5cGU6IGpzb25cIik7XG5cdFx0bGluZXMucHVzaChcIiAgY29udGVudDogfC1cIik7XG5cdFx0Zm9yIChjb25zdCBib2R5TGluZSBvZiByYXdCb2R5LnNwbGl0KFwiXFxuXCIpKSB7XG5cdFx0XHRsaW5lcy5wdXNoKGAgICAgJHtib2R5TGluZX1gKTtcblx0XHR9XG5cdH1cblxuXHRsaW5lcy5wdXNoKGBvcmRlcjogJHtvcmRlcn1gLCBcIlwiKTtcblx0cmV0dXJuIGxpbmVzLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RVcmxGb3JMb2NhbFZpZXcocmVxdWVzdDogUG9zdG1hblJlcXVlc3QpOiBzdHJpbmcge1xuXHRjb25zdCB1cmwgPSByZXF1ZXN0LnVybDtcblx0aWYgKHR5cGVvZiB1cmwgPT09IFwic3RyaW5nXCIpIHtcblx0XHRyZXR1cm4gb3BlbkFwaVBhdGhQYXJhbXNUb0NvbG9uKHVybCk7XG5cdH1cblx0aWYgKHVybD8ucmF3KSB7XG5cdFx0cmV0dXJuIG9wZW5BcGlQYXRoUGFyYW1zVG9Db2xvbih1cmwucmF3KTtcblx0fVxuXHRjb25zdCBob3N0ID0gdXJsPy5ob3N0Py5bMF0gPz8gXCJ7e2Jhc2VVcmx9fVwiO1xuXHRjb25zdCBwYXRoID0gKHVybD8ucGF0aCA/PyBbXSlcblx0XHQubWFwKChzZWdtZW50KSA9PiBvcGVuQXBpUGF0aFBhcmFtc1RvQ29sb24oU3RyaW5nKHNlZ21lbnQpKSlcblx0XHQuam9pbihcIi9cIik7XG5cdHJldHVybiBwYXRoID8gYCR7aG9zdH0vJHtwYXRofWAgOiBob3N0O1xufVxuXG5mdW5jdGlvbiBzYW5pdGl6ZUZpbGVOYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG5cdHJldHVybiBuYW1lLnJlcGxhY2UoL1teXFx3XFxzKCktXSsvZywgXCJcIikudHJpbSgpIHx8IFwiUmVxdWVzdFwiO1xufVxuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJvcGVuQXBpUGF0aFBhcmFtc1RvQ29sb24iLCJ5YW1sUXVvdGUiLCJ2YWx1ZSIsInRlc3QiLCJpbmNsdWRlcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJidWlsZEVudmlyb25tZW50WWFtbCIsIm5hbWUiLCJhdXRoIiwib3B0aW9ucyIsInZhbHVlcyIsImtleSIsImF1dGgwRG9tYWluIiwicHVzaCIsImF1dGgwQXVkaWVuY2UiLCJhdXRoMENsaWVudElkIiwiY2FsbGJhY2tzIiwic2NvcGVzIiwibGluZXMiLCJ2Iiwiam9pbiIsImJ1aWxkTG9jYWxWaWV3RmlsZXNGcm9tQ29sbGVjdGlvbiIsImNvbGxlY3Rpb24iLCJwcm9qZWN0TmFtZSIsImNvbGxlY3Rpb25EaXIiLCJmaWxlcyIsImF1dGhCbG9jayIsImZpbGVQYXRoIiwiY29udGVudCIsImZpbHRlciIsImwiLCJ1bmRlZmluZWQiLCJyZXBsYWNlIiwiZm9sZGVyT3JkZXIiLCJmb2xkZXIiLCJpdGVtIiwiZm9sZGVyTmFtZSIsInJlcXVlc3RPcmRlciIsImNoaWxkIiwieWFtbCIsInJlcXVlc3RUb0xvY2FsVmlld1lhbWwiLCJmaWxlTmFtZSIsInNhbml0aXplRmlsZU5hbWUiLCJvcmRlciIsInJlcXVlc3QiLCJtZXRob2QiLCJ0b1VwcGVyQ2FzZSIsInVybCIsInJlcXVlc3RVcmxGb3JMb2NhbFZpZXciLCJ0eXBlIiwiY29udGVudFR5cGUiLCJoZWFkZXIiLCJmaW5kIiwiaCIsInRvTG93ZXJDYXNlIiwicmF3Qm9keSIsImJvZHkiLCJyYXciLCJ0cmltIiwiYm9keUxpbmUiLCJzcGxpdCIsImhvc3QiLCJwYXRoIiwibWFwIiwic2VnbWVudCIsIlN0cmluZyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxRQUFRLGNBQWM7QUFDekMsU0FFQ0Msd0JBQXdCLFFBSWxCLDBCQUEwQjtBQUVqQyxTQUFTQyxVQUFVQyxLQUFhO0lBQy9CLElBQUksd0JBQXdCQyxJQUFJLENBQUNELFVBQVVBLE1BQU1FLFFBQVEsQ0FBQyxTQUFTRixVQUFVLElBQUk7UUFDaEYsT0FBT0csS0FBS0MsU0FBUyxDQUFDSjtJQUN2QjtJQUNBLE9BQU9BO0FBQ1I7QUFFQSxnREFBZ0QsR0FDaEQsT0FBTyxTQUFTSyxxQkFDZkMsSUFBWSxFQUNaQyxJQUEwQixFQUMxQkMsT0FBeUQ7SUFFekQsTUFBTUMsU0FBZ0Q7UUFDckQ7WUFBRUMsS0FBSztZQUFXVixPQUFPO1FBQXdCO0tBQ2pEO0lBQ0QsSUFBSU8sTUFBTUksYUFBYTtRQUN0QkYsT0FBT0csSUFBSSxDQUNWO1lBQUVGLEtBQUs7WUFBZVYsT0FBT08sS0FBS0ksV0FBVztRQUFDLEdBQzlDO1lBQUVELEtBQUs7WUFBaUJWLE9BQU9PLEtBQUtNLGFBQWEsSUFBSTtRQUFHLEdBQ3hEO1lBQUVILEtBQUs7WUFBaUJWLE9BQU9PLEtBQUtPLGFBQWEsSUFBSTtRQUFHLEdBQ3hEO1lBQ0NKLEtBQUs7WUFDTFYsT0FBTyxDQUFDLFFBQVEsRUFBRU8sS0FBS0ksV0FBVyxDQUFDLG9CQUFvQixFQUFFSixLQUFLTSxhQUFhLElBQUksSUFBSTtRQUNwRixHQUNBO1lBQ0NILEtBQUs7WUFDTFYsT0FBTyxDQUFDLFFBQVEsRUFBRU8sS0FBS0ksV0FBVyxDQUFDLFlBQVksQ0FBQztRQUNqRCxHQUNBO1lBQUVELEtBQUs7WUFBZVYsT0FBT1EsUUFBUU8sU0FBUyxDQUFDLEVBQUU7UUFBQyxHQUNsRDtZQUFFTCxLQUFLO1lBQVNWLE9BQU9RLFFBQVFRLE1BQU07UUFBQztJQUV4QztJQUVBLE1BQU1DLFFBQVE7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
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import converter from "openapi-to-postmanv2";
|
|
2
|
+
function convertAsync(data, options) {
|
|
3
|
+
return new Promise((resolve, reject)=>{
|
|
4
|
+
converter.convert({
|
|
5
|
+
type: "json",
|
|
6
|
+
data
|
|
7
|
+
}, options, (err, result)=>{
|
|
8
|
+
if (err) {
|
|
9
|
+
reject(err);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
resolve(result);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Convert an OpenAPI document to a Postman Collection v2.1 via openapi-to-postmanv2. */ export async function openApiToPostmanCollection(document) {
|
|
17
|
+
const result = await convertAsync(document, {
|
|
18
|
+
folderStrategy: "Tags",
|
|
19
|
+
requestNameSource: "Fallback",
|
|
20
|
+
includeAuthInfoInExample: false
|
|
21
|
+
});
|
|
22
|
+
if (!result.result || result.output?.[0]?.data == null) {
|
|
23
|
+
throw new Error(result.reason ?? "openapi-to-postmanv2 conversion failed");
|
|
24
|
+
}
|
|
25
|
+
return result.output[0].data;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Overlay Auth0 OAuth2 (PKCE) collection auth and fix Local View-friendly URLs.
|
|
29
|
+
* Route items come from OpenAPI; auth/env remain hand-authored.
|
|
30
|
+
*/ export function applyPostmanAuthOverlay(collection, projectName, auth, options) {
|
|
31
|
+
const next = {
|
|
32
|
+
...collection,
|
|
33
|
+
info: {
|
|
34
|
+
...collection.info,
|
|
35
|
+
name: `${projectName} WebAPI`,
|
|
36
|
+
description: options.description,
|
|
37
|
+
schema: collection.info.schema ?? "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
if (auth?.auth0Domain) {
|
|
41
|
+
next.auth = {
|
|
42
|
+
type: "oauth2",
|
|
43
|
+
oauth2: [
|
|
44
|
+
{
|
|
45
|
+
key: "grant_type",
|
|
46
|
+
value: "authorization_code_with_pkce",
|
|
47
|
+
type: "string"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: "authUrl",
|
|
51
|
+
value: "https://{{auth0Domain}}/authorize?audience={{auth0Audience}}",
|
|
52
|
+
type: "string"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: "accessTokenUrl",
|
|
56
|
+
value: "https://{{auth0Domain}}/oauth/token",
|
|
57
|
+
type: "string"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "clientId",
|
|
61
|
+
value: "{{auth0ClientId}}",
|
|
62
|
+
type: "string"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
key: "scope",
|
|
66
|
+
value: options.scopes,
|
|
67
|
+
type: "string"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
key: "redirect_uri",
|
|
71
|
+
value: options.callbacks[0],
|
|
72
|
+
type: "string"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
key: "useBrowser",
|
|
76
|
+
value: "true",
|
|
77
|
+
type: "boolean"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
key: "addTokenTo",
|
|
81
|
+
value: "header",
|
|
82
|
+
type: "string"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
key: "challengeAlgorithm",
|
|
86
|
+
value: "S256",
|
|
87
|
+
type: "string"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
key: "client_authentication",
|
|
91
|
+
value: "body",
|
|
92
|
+
type: "string"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
key: "clientSecret",
|
|
96
|
+
value: "",
|
|
97
|
+
type: "string"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
key: "tokenName",
|
|
101
|
+
value: `${projectName} Access Token`,
|
|
102
|
+
type: "string"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
next.item = rewriteCollectionItems(collection.item ?? [], {
|
|
108
|
+
markListAnonymous: true
|
|
109
|
+
});
|
|
110
|
+
return next;
|
|
111
|
+
}
|
|
112
|
+
function rewriteCollectionItems(items, opts) {
|
|
113
|
+
return items.map((item)=>{
|
|
114
|
+
if (item.item != null) {
|
|
115
|
+
return {
|
|
116
|
+
...item,
|
|
117
|
+
item: rewriteCollectionItems(item.item, opts)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const request = item.request;
|
|
121
|
+
if (request == null) {
|
|
122
|
+
return item;
|
|
123
|
+
}
|
|
124
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
125
|
+
const rawUrl = requestUrlRaw(request);
|
|
126
|
+
const nextRequest = {
|
|
127
|
+
...request,
|
|
128
|
+
url: toPostmanUrl(rawUrl)
|
|
129
|
+
};
|
|
130
|
+
// List Hello stays anonymous (matches scaffold AllowAnonymous on GET /hello).
|
|
131
|
+
if (opts.markListAnonymous && method === "GET" && normalizePath(rawUrl) === "/hello" && !rawUrl.includes("/:")) {
|
|
132
|
+
nextRequest.auth = {
|
|
133
|
+
type: "noauth"
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
...item,
|
|
138
|
+
request: nextRequest
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function requestUrlRaw(request) {
|
|
143
|
+
const url = request.url;
|
|
144
|
+
if (typeof url === "string") {
|
|
145
|
+
return url;
|
|
146
|
+
}
|
|
147
|
+
if (url?.raw) {
|
|
148
|
+
return url.raw;
|
|
149
|
+
}
|
|
150
|
+
const host = url?.host?.[0] ?? "{{baseUrl}}";
|
|
151
|
+
const path = (url?.path ?? []).join("/");
|
|
152
|
+
return path ? `${host}/${path}` : host;
|
|
153
|
+
}
|
|
154
|
+
/** OpenAPI `{id}` → Postman `:id`, without touching `{{variables}}`. */ export function openApiPathParamsToColon(url) {
|
|
155
|
+
return url.replace(/(?<!\{)\{([A-Za-z_][\w]*)\}(?!\})/g, ":$1");
|
|
156
|
+
}
|
|
157
|
+
function normalizePath(rawUrl) {
|
|
158
|
+
const withoutBase = rawUrl.replace(/\{\{baseUrl\}\}/g, "").split("?")[0] ?? "";
|
|
159
|
+
const withSlash = withoutBase.startsWith("/") ? withoutBase : `/${withoutBase}`;
|
|
160
|
+
return openApiPathParamsToColon(withSlash);
|
|
161
|
+
}
|
|
162
|
+
/** Prefer Postman template URL shape used by existing Local View / API uploads. */ function toPostmanUrl(rawUrl) {
|
|
163
|
+
let pathPart = rawUrl.replace(/\{\{baseUrl\}\}/g, "");
|
|
164
|
+
if (!pathPart.startsWith("/")) {
|
|
165
|
+
pathPart = `/${pathPart}`;
|
|
166
|
+
}
|
|
167
|
+
// openapi-to-postman uses {id}; Local View / prior collections use :id
|
|
168
|
+
pathPart = openApiPathParamsToColon(pathPart);
|
|
169
|
+
const segments = pathPart.split("/").filter(Boolean);
|
|
170
|
+
return {
|
|
171
|
+
raw: `{{baseUrl}}${pathPart}`,
|
|
172
|
+
host: [
|
|
173
|
+
"{{baseUrl}}"
|
|
174
|
+
],
|
|
175
|
+
path: segments
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvcG9zdG1hbi9vcGVuYXBpLXRvLXBvc3RtYW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNvbnZlcnRlciBmcm9tIFwib3BlbmFwaS10by1wb3N0bWFudjJcIjtcbmltcG9ydCB0eXBlIHsgU2NhZmZvbGRPcGVuQXBpRG9jdW1lbnQgfSBmcm9tIFwiLi9oZWxsby1vcGVuYXBpLmpzXCI7XG5cbmV4cG9ydCB0eXBlIFBvc3RtYW5Db2xsZWN0aW9uID0ge1xuXHRpbmZvOiB7XG5cdFx0X3Bvc3RtYW5faWQ/OiBzdHJpbmc7XG5cdFx0bmFtZTogc3RyaW5nO1xuXHRcdHNjaGVtYTogc3RyaW5nO1xuXHRcdGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXHR9O1xuXHRhdXRoPzogdW5rbm93bjtcblx0aXRlbT86IFBvc3RtYW5JdGVtW107XG5cdHZhcmlhYmxlPzogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9Pjtcblx0W2tleTogc3RyaW5nXTogdW5rbm93bjtcbn07XG5cbmV4cG9ydCB0eXBlIFBvc3RtYW5JdGVtID0ge1xuXHRuYW1lPzogc3RyaW5nO1xuXHRpdGVtPzogUG9zdG1hbkl0ZW1bXTtcblx0cmVxdWVzdD86IFBvc3RtYW5SZXF1ZXN0O1xuXHRba2V5OiBzdHJpbmddOiB1bmtub3duO1xufTtcblxuZXhwb3J0IHR5cGUgUG9zdG1hblJlcXVlc3QgPSB7XG5cdG1ldGhvZD86IHN0cmluZztcblx0aGVhZGVyPzogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9Pjtcblx0Ym9keT86IHsgbW9kZT86IHN0cmluZzsgcmF3Pzogc3RyaW5nIH07XG5cdHVybD86IHN0cmluZyB8IHsgcmF3Pzogc3RyaW5nOyBob3N0Pzogc3RyaW5nW107IHBhdGg/OiBzdHJpbmdbXTsgdmFyaWFibGU/OiB1bmtub3duW10gfTtcblx0YXV0aD86IHsgdHlwZTogc3RyaW5nOyBba2V5OiBzdHJpbmddOiB1bmtub3duIH07XG5cdFtrZXk6IHN0cmluZ106IHVua25vd247XG59O1xuXG5leHBvcnQgdHlwZSBBdXRoMEVudiA9IHtcblx0YXV0aDBEb21haW4/OiBzdHJpbmc7XG5cdGF1dGgwQXVkaWVuY2U/OiBzdHJpbmc7XG5cdGF1dGgwQ2xpZW50SWQ/OiBzdHJpbmc7XG59O1xuXG50eXBlIENvbnZlcnRSZXN1bHQgPSB7XG5cdHJlc3VsdDogYm9vbGVhbjtcblx0cmVhc29uPzogc3RyaW5nO1xuXHRvdXRwdXQ/OiBBcnJheTx7IHR5cGU6IHN0cmluZzsgZGF0YTogUG9zdG1hbkNvbGxlY3Rpb24gfT47XG59O1xuXG5mdW5jdGlvbiBjb252ZXJ0QXN5bmMoXG5cdGRhdGE6IFNjYWZmb2xkT3BlbkFwaURvY3VtZW50LFxuXHRvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IFByb21pc2U8Q29udmVydFJlc3VsdD4ge1xuXHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXHRcdGNvbnZlcnRlci5jb252ZXJ0KFxuXHRcdFx0eyB0eXBlOiBcImpzb25cIiwgZGF0YSB9LFxuXHRcdFx0b3B0aW9ucyxcblx0XHRcdChlcnI6IEVycm9yIHwgbnVsbCwgcmVzdWx0OiBDb252ZXJ0UmVzdWx0KSA9PiB7XG5cdFx0XHRcdGlmIChlcnIpIHtcblx0XHRcdFx0XHRyZWplY3QoZXJyKTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVzb2x2ZShyZXN1bHQpO1xuXHRcdFx0fSxcblx0XHQpO1xuXHR9KTtcbn1cblxuLyoqIENvbnZlcnQgYW4gT3BlbkFQSSBkb2N1bWVudCB0byBhIFBvc3RtYW4gQ29sbGVjdGlvbiB2Mi4xIHZpYSBvcGVuYXBpLXRvLXBvc3RtYW52Mi4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvcGVuQXBpVG9Qb3N0bWFuQ29sbGVjdGlvbihcblx0ZG9jdW1lbnQ6IFNjYWZmb2xkT3BlbkFwaURvY3VtZW50LFxuKTogUHJvbWlzZTxQb3N0bWFuQ29sbGVjdGlvbj4ge1xuXHRjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0QXN5bmMoZG9jdW1lbnQsIHtcblx0XHRmb2xkZXJTdHJhdGVneTogXCJUYWdzXCIsXG5cdFx0cmVxdWVzdE5hbWVTb3VyY2U6IFwiRmFsbGJhY2tcIixcblx0XHRpbmNsdWRlQXV0aEluZm9JbkV4YW1wbGU6IGZhbHNlLFxuXHR9KTtcblx0aWYgKCFyZXN1bHQucmVzdWx0IHx8IHJlc3VsdC5vdXRwdXQ/LlswXT8uZGF0YSA9PSBudWxsKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKHJlc3VsdC5yZWFzb24gPz8gXCJvcGVuYXBpLXRvLXBvc3RtYW52MiBjb252ZXJzaW9uIGZhaWxlZFwiKTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0Lm91dHB1dFswXS5kYXRhO1xufVxuXG4vKipcbiAqIE92ZXJsYXkgQXV0aDAgT0F1dGgyIChQS0NFKSBjb2xsZWN0aW9uIGF1dGggYW5kIGZpeCBMb2NhbCBWaWV3LWZyaWVuZGx5IFVSTHMuXG4gKiBSb3V0ZSBpdGVtcyBjb21lIGZyb20gT3BlbkFQSTsgYXV0aC9lbnYgcmVtYWluIGhhbmQtYXV0aG9yZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBvc3RtYW5BdXRoT3ZlcmxheShcblx0Y29sbGVjdGlvbjogUG9zdG1hbkNvbGxlY3Rpb24sXG5cdHByb2plY3ROYW1lOiBzdHJpbmcsXG5cdGF1dGg6IEF1dGgwRW52IHwgdW5kZWZpbmVkLFxuXHRvcHRpb25zOiB7XG5cdFx0Y2FsbGJhY2tzOiByZWFkb25seSBzdHJpbmdbXTtcblx0XHRzY29wZXM6IHN0cmluZztcblx0XHRkZXNjcmlwdGlvbjogc3RyaW5nO1xuXHR9LFxuKTogUG9zdG1hbkNvbGxlY3Rpb24ge1xuXHRjb25zdCBuZXh0OiBQb3N0bWFuQ29sbGVjdGlvbiA9IHtcblx0XHQuLi5jb2xsZWN0aW9uLFxuXHRcdGluZm86IHtcblx0XHRcdC4uLmNvbGxlY3Rpb24uaW5mbyxcblx0XHRcdG5hbWU6IGAke3Byb2plY3ROYW1lfSBXZWJBUElgLFxuXHRcdFx0ZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24sXG5cdFx0XHRzY2hlbWE6XG5cdFx0XHRcdGNvbGxlY3Rpb24uaW5mby5zY2hlbWEgPz9cblx0XHRcdFx0XCJodHRwczovL3NjaGVtYS5nZXRwb3N0bWFuLmNvbS9qc29uL2NvbGxlY3Rpb24vdjIuMS4wL2NvbGxlY3Rpb24uanNvblwiLFxuXHRcdH0sXG5cdH07XG5cblx0aWYgKGF1dGg/LmF1dGgwRG9tYWluKSB7XG5cdFx0bmV4dC5hdXRoID0ge1xuXHRcdFx0dHlwZTogXCJvYXV0aDJcIixcblx0XHRcdG9hdXRoMjogW1xuXHRcdFx0XHR7IGtleTogXCJncmFudF90eXBlXCIsIHZhbHVlOiBcImF1dGhvcml6YXRpb25fY29kZV93aXRoX3BrY2VcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0a2V5OiBcImF1dGhVcmxcIixcblx0XHRcdFx0XHR2YWx1ZTogXCJodHRwczovL3t7YXV0aDBEb21haW59fS9hdXRob3JpemU/YXVkaWVuY2U9e3thdXRoMEF1ZGllbmNlfX1cIixcblx0XHRcdFx0XHR0eXBlOiBcInN0cmluZ1wiLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0a2V5OiBcImFjY2Vzc1Rva2VuVXJsXCIsXG5cdFx0XHRcdFx0dmFsdWU6IFwiaHR0cHM6Ly97e2F1dGgwRG9tYWlufX0vb2F1dGgvdG9rZW5cIixcblx0XHRcdFx0XHR0eXBlOiBcInN0cmluZ1wiLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7IGtleTogXCJjbGllbnRJZFwiLCB2YWx1ZTogXCJ7e2F1dGgwQ2xpZW50SWR9fVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG5cdFx0XHRcdHsga2V5OiBcInNjb3BlXCIsIHZhbHVlOiBvcHRpb25zLnNjb3BlcywgdHlwZTogXCJzdHJpbmdcIiB9LFxuXHRcdFx0XHR7IGtleTogXCJyZWRpcmVjdF91cmlcIiwgdmFsdWU6IG9wdGlvbnMuY2FsbGJhY2tzWzBdLCB0eXBlOiBcInN0cmluZ1wiIH0sXG5cdFx0XHRcdHsga2V5OiBcInVzZUJyb3dzZXJcIiwgdmFsdWU6IFwidHJ1ZVwiLCB0eXBlOiBcImJvb2xlYW5cIiB9LFxuXHRcdFx0XHR7IGtleTogXCJhZGRUb2tlblRvXCIsIHZhbHVlOiBcImhlYWRlclwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG5cdFx0XHRcdHsga2V5OiBcImNoYWxsZW5nZUFsZ29yaXRobVwiLCB2YWx1ZTogXCJTMjU2XCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcblx0XHRcdFx0eyBrZXk6IFwiY2xpZW50X2F1dGhlbnRpY2F0aW9uXCIsIHZhbHVlOiBcImJvZHlcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuXHRcdFx0XHR7IGtleTogXCJjbGllbnRTZWNyZXRcIiwgdmFsdWU6IFwiXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcblx0XHRcdFx0eyBrZXk6IFwidG9rZW5OYW1lXCIsIHZhbHVlOiBgJHtwcm9qZWN0TmFtZX0gQWNjZXNzIFRva2VuYCwgdHlwZTogXCJzdHJpbmdcIiB9LFxuXHRcdFx0XSxcblx0XHR9O1xuXHR9XG5cblx0bmV4dC5pdGVtID0gcmV3cml0ZUNvbGxlY3Rpb25JdGVtcyhjb2xsZWN0aW9uLml0ZW0gPz8gW10sIHtcblx0XHRtYXJrTGlzdEFub255bW91czogdHJ1ZSxcblx0fSk7XG5cdHJldHVybiBuZXh0O1xufVxuXG5mdW5jdGlvbiByZXdyaXRlQ29sbGVjdGlvbkl0ZW1zKFxuXHRpdGVtczogUG9zdG1hbkl0ZW1bXSxcblx0b3B0czogeyBtYXJrTGlzdEFub255bW91czogYm9vbGVhbiB9LFxuKTogUG9zdG1hbkl0ZW1bXSB7XG5cdHJldHVybiBpdGVtcy5tYXAoKGl0ZW0pID0+IHtcblx0XHRpZiAoaXRlbS5pdGVtICE9IG51bGwpIHtcblx0XHRcdHJldHVybiB7IC4uLml0ZW0sIGl0ZW06IHJld3JpdGVDb2xsZWN0aW9uSXRlbXMoaXRlbS5pdGVtLCBvcHRzKSB9O1xuXHRcdH1cblx0XHRjb25zdCByZXF1ZXN0ID0gaXRlbS5yZXF1ZXN0O1xuXHRcdGlmIChyZXF1ZXN0ID09IG51bGwpIHtcblx0XHRcdHJldHVybiBpdGVtO1xuXHRcdH1cblx0XHRjb25zdCBtZXRob2QgPSAocmVxdWVzdC5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcblx0XHRjb25zdCByYXdVcmwgPSByZXF1ZXN0VXJsUmF3KHJlcXVlc3QpO1xuXHRcdGNvbnN0IG5leHRSZXF1ZXN0OiBQb3N0bWFuUmVxdWVzdCA9IHtcblx0XHRcdC4uLnJlcXVlc3QsXG5cdFx0XHR1cmw6IHRvUG9zdG1hblVybChyYXdVcmwpLFxuXHRcdH07XG5cdFx0Ly8gTGlzdCBIZWxsbyBzdGF5cyBhbm9ueW1vdXMgKG1hdGNoZXMgc2NhZmZvbGQgQWxsb3dBbm9ueW1vdXMgb24gR0VUIC9oZWxsbykuXG5cdFx0aWYgKFxuXHRcdFx0b3B0cy5tYXJrTGlzdEFub255bW91cyAmJlxuXHRcdFx0bWV0aG9kID09PSBcIkdFVFwiICYmXG5cdFx0XHRub3JtYWxpemVQYXRoKHJhd1VybCkgPT09IFwiL2hlbGxvXCIgJiZcblx0XHRcdCFyYXdVcmwuaW5jbHVkZXMoXCIvOlwiKVxuXHRcdCkge1xuXHRcdFx0bmV4dFJlcXVlc3QuYXV0aCA9IHsgdHlwZTogXCJub2F1dGhcIiB9O1xuXHRcdH1cblx0XHRyZXR1cm4geyAuLi5pdGVtLCByZXF1ZXN0OiBuZXh0UmVxdWVzdCB9O1xuXHR9KTtcbn1cblxuZnVuY3Rpb24gcmVxdWVzdFVybFJhdyhyZXF1ZXN0OiBQb3N0bWFuUmVxdWVzdCk6IHN0cmluZyB7XG5cdGNvbnN0IHVybCA9IHJlcXVlc3QudXJsO1xuXHRpZiAodHlwZW9mIHVybCA9PT0gXCJzdHJpbmdcIikge1xuXHRcdHJldHVybiB1cmw7XG5cdH1cblx0aWYgKHVybD8ucmF3KSB7XG5cdFx0cmV0dXJuIHVybC5yYXc7XG5cdH1cblx0Y29uc3QgaG9zdCA9IHVybD8uaG9zdD8uWzBdID8/IFwie3tiYXNlVXJsfX1cIjtcblx0Y29uc3QgcGF0aCA9ICh1cmw/LnBhdGggPz8gW10pLmpvaW4oXCIvXCIpO1xuXHRyZXR1cm4gcGF0aCA/IGAke2hvc3R9LyR7cGF0aH1gIDogaG9zdDtcbn1cblxuLyoqIE9wZW5BUEkgYHtpZH1gIOKGkiBQb3N0bWFuIGA6aWRgLCB3aXRob3V0IHRvdWNoaW5nIGB7e3ZhcmlhYmxlc319YC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVuQXBpUGF0aFBhcmFtc1RvQ29sb24odXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRyZXR1cm4gdXJsLnJlcGxhY2UoLyg/PCFcXHspXFx7KFtBLVphLXpfXVtcXHddKilcXH0oPyFcXH0pL2csIFwiOiQxXCIpO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVQYXRoKHJhd1VybDogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3Qgd2l0aG91dEJhc2UgPSByYXdVcmwucmVwbGFjZSgvXFx7XFx7YmFzZVVybFxcfVxcfS9nLCBcIlwiKS5zcGxpdChcIj9cIilbMF0gPz8gXCJcIjtcblx0Y29uc3Qgd2l0aFNsYXNoID0gd2l0aG91dEJhc2Uuc3RhcnRzV2l0aChcIi9cIikgPyB3aXRob3V0QmFzZSA6IGAvJHt3aXRob3V0QmFzZX1gO1xuXHRyZXR1cm4gb3BlbkFwaVBhdGhQYXJhbXNUb0NvbG9uKHdpdGhTbGFzaCk7XG59XG5cbi8qKiBQcmVmZXIgUG9zdG1hbiB0ZW1wbGF0ZSBVUkwgc2hhcGUgdXNlZCBieSBleGlzdGluZyBMb2NhbCBWaWV3IC8gQVBJIHVwbG9hZHMuICovXG5mdW5jdGlvbiB0b1Bvc3RtYW5VcmwocmF3VXJsOiBzdHJpbmcpOiBQb3N0bWFuUmVxdWVzdFtcInVybFwiXSB7XG5cdGxldCBwYXRoUGFydCA9IHJhd1VybC5yZXBsYWNlKC9cXHtcXHtiYXNlVXJsXFx9XFx9L2csIFwiXCIpO1xuXHRpZiAoIXBhdGhQYXJ0LnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG5cdFx0cGF0aFBhcnQgPSBgLyR7cGF0aFBhcnR9YDtcblx0fVxuXHQvLyBvcGVuYXBpLXRvLXBvc3RtYW4gdXNlcyB7aWR9OyBMb2NhbCBWaWV3IC8gcHJpb3IgY29sbGVjdGlvbnMgdXNlIDppZFxuXHRwYXRoUGFydCA9IG9wZW5BcGlQYXRoUGFyYW1zVG9Db2xvbihwYXRoUGFydCk7XG5cdGNvbnN0IHNlZ21lbnRzID0gcGF0aFBhcnQuc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKTtcblx0cmV0dXJuIHtcblx0XHRyYXc6IGB7e2Jhc2VVcmx9fSR7cGF0aFBhcnR9YCxcblx0XHRob3N0OiBbXCJ7e2Jhc2VVcmx9fVwiXSxcblx0XHRwYXRoOiBzZWdtZW50cyxcblx0fTtcbn1cbiJdLCJuYW1lcyI6WyJjb252ZXJ0ZXIiLCJjb252ZXJ0QXN5bmMiLCJkYXRhIiwib3B0aW9ucyIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiY29udmVydCIsInR5cGUiLCJlcnIiLCJyZXN1bHQiLCJvcGVuQXBpVG9Qb3N0bWFuQ29sbGVjdGlvbiIsImRvY3VtZW50IiwiZm9sZGVyU3RyYXRlZ3kiLCJyZXF1ZXN0TmFtZVNvdXJjZSIsImluY2x1ZGVBdXRoSW5mb0luRXhhbXBsZSIsIm91dHB1dCIsIkVycm9yIiwicmVhc29uIiwiYXBwbHlQb3N0bWFuQXV0aE92ZXJsYXkiLCJjb2xsZWN0aW9uIiwicHJvamVjdE5hbWUiLCJhdXRoIiwibmV4dCIsImluZm8iLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJzY2hlbWEiLCJhdXRoMERvbWFpbiIsIm9hdXRoMiIsImtleSIsInZhbHVlIiwic2NvcGVzIiwiY2FsbGJhY2tzIiwiaXRlbSIsInJld3JpdGVDb2xsZWN0aW9uSXRlbXMiLCJtYXJrTGlzdEFub255bW91cyIsIml0ZW1zIiwib3B0cyIsIm1hcCIsInJlcXVlc3QiLCJtZXRob2QiLCJ0b1VwcGVyQ2FzZSIsInJhd1VybCIsInJlcXVlc3RVcmxSYXciLCJuZXh0UmVxdWVzdCIsInVybCIsInRvUG9zdG1hblVybCIsIm5vcm1hbGl6ZVBhdGgiLCJpbmNsdWRlcyIsInJhdyIsImhvc3QiLCJwYXRoIiwiam9pbiIsIm9wZW5BcGlQYXRoUGFyYW1zVG9Db2xvbiIsInJlcGxhY2UiLCJ3aXRob3V0QmFzZSIsInNwbGl0Iiwid2l0aFNsYXNoIiwic3RhcnRzV2l0aCIsInBhdGhQYXJ0Iiwic2VnbWVudHMiLCJmaWx0ZXIiLCJCb29sZWFuIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxlQUFlLHVCQUF1QjtBQTRDN0MsU0FBU0MsYUFDUkMsSUFBNkIsRUFDN0JDLE9BQWdDO0lBRWhDLE9BQU8sSUFBSUMsUUFBUSxDQUFDQyxTQUFTQztRQUM1Qk4sVUFBVU8sT0FBTyxDQUNoQjtZQUFFQyxNQUFNO1lBQVFOO1FBQUssR0FDckJDLFNBQ0EsQ0FBQ00sS0FBbUJDO1lBQ25CLElBQUlELEtBQUs7Z0JBQ1JILE9BQU9HO2dCQUNQO1lBQ0Q7WUFDQUosUUFBUUs7UUFDVDtJQUVGO0FBQ0Q7QUFFQSx1RkFBdUYsR0FDdkYsT0FBTyxlQUFlQywyQkFDckJDLFFBQWlDO0lBRWpDLE1BQU1GLFNBQVMsTUFBTVQsYUFBYVcsVUFBVTtRQUMzQ0MsZ0JBQWdCO1FBQ2hCQyxtQkFBbUI7UUFDbkJDLDBCQUEwQjtJQUMzQjtJQUNBLElBQUksQ0FBQ0wsT0FBT0EsTUFBTSxJQUFJQSxPQUFPTSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUVkLFFBQVEsTUFBTTtRQUN2RCxNQUFNLElBQUllLE1BQU1QLE9BQU9RLE1BQU0sSUFBSTtJQUNsQztJQUNBLE9BQU9SLE9BQU9NLE1BQU0sQ0FBQyxFQUFFLENBQUNkLElBQUk7QUFDN0I7QUFFQTs7O0NBR0MsR0FDRCxPQUFPLFNBQVNpQix3QkFDZkMsVUFBNkIsRUFDN0JDLFdBQW1CLEVBQ25CQyxJQUEwQixFQUMxQm5CLE9BSUM7SUFFRCxNQUFNb0IsT0FBMEI7UUFDL0IsR0FBR0gsVUFBVTtRQUNiSSxNQUFNO1lBQ0wsR0FBR0osV0FBV0ksSUFBSTtZQUNsQkMsTUFBTSxHQUFHSixZ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
|