openapi-import 0.0.0-stage → 0.0.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/LICENSE +21 -0
- package/README.md +95 -2
- package/dist/server.js +392 -0
- package/dist/server.js.map +1 -0
- package/package.json +98 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kubb Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# openapi-import
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Import an OpenAPI spec straight into TypeScript and get the types Kubb generates, with no generated files on disk.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import type { Pet } from './petStore.openapi.yaml'
|
|
7
|
+
|
|
8
|
+
const pet: Pet = { name: 'Rex', photoUrls: [] }
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
It is a [TypeScript content mapper](https://github.com/microsoft/typescript-go/pull/4712). TypeScript 7.1 calls it for each spec file and type-checks the `@kubb/plugin-ts` output in its place.
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> Experimental. Content mappers need a TypeScript 7.1 build that supports `--runExternalCode` (`typescript@next` today). Imports are type-only: content-mapped files are not emitted to JavaScript, so values such as enum objects do not exist at run time.
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add -D kubb openapi-import typescript@next
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
npm rejects `typescript@next` against the `typescript@^7.0.2` peer range of `@kubb/plugin-ts`, so add `--legacy-peer-deps` there.
|
|
23
|
+
|
|
24
|
+
Name your specs with an `.openapi.yaml` extension, such as `petStore.openapi.yaml`, and register that extension in `tsconfig.json`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"contentMappers": [{ "package": "openapi-import", "extensions": [".openapi.yaml", ".openapi.yml"] }]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
TypeScript sends every file with a registered extension that `include` matches to the mapper, not only the files you import. A plain `.yaml` would also pick up files such as `docker-compose.yaml` and fail on them, and it would block other content mappers from `.yaml`. JSON specs cannot be mapped: TypeScript treats any extension ending in `.json` as built-in.
|
|
33
|
+
|
|
34
|
+
Run the type check with external code allowed:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
tsc --noEmit --runExternalCode
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
VS Code passes `--runExternalCode` to the TypeScript language server only in trusted workspaces.
|
|
41
|
+
|
|
42
|
+
## Editor support
|
|
43
|
+
|
|
44
|
+
Generated names link back to the keys they came from in the spec. Go to definition and find references cross from TypeScript into the YAML, and hovering a key in the YAML shows its generated type.
|
|
45
|
+
|
|
46
|
+
| Generated name | Jumps to |
|
|
47
|
+
| ------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
48
|
+
| `Pet` | `components.schemas.Pet` |
|
|
49
|
+
| `Pet['name']` | `properties.name` under `Pet`, nested objects and arrays of them included |
|
|
50
|
+
| `orderStatusEnum`, `OrderStatusEnumKey` | the `status` property the enum came from |
|
|
51
|
+
| `GetPetByIdResponse`, `GetPetByIdOptions` | the `get` operation under `/pet/{petId}` |
|
|
52
|
+
| `GetPetByIdPath`, `FindPetsByStatusQuery`, `DeletePetHeaders` | the operation's `parameters` |
|
|
53
|
+
| `GetPetByIdStatus404` | `responses.404` |
|
|
54
|
+
| `AddPetBody` | the operation's `requestBody` |
|
|
55
|
+
|
|
56
|
+
Spec errors, such as an unresolved `$ref`, show on the key or value they point at.
|
|
57
|
+
|
|
58
|
+
## Options
|
|
59
|
+
|
|
60
|
+
Set options on the `contentMappers` entry. TypeScript reports an unknown key or an invalid value on `tsconfig.json`.
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"contentMappers": [
|
|
65
|
+
{
|
|
66
|
+
"package": "openapi-import",
|
|
67
|
+
"extensions": [".openapi.yaml"],
|
|
68
|
+
"options": { "arrayType": "generic" }
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Option | Values | Default | Description |
|
|
75
|
+
| ----------- | ---------------------- | --------- | ------------------------------------------------------------------------ |
|
|
76
|
+
| `arrayType` | `'array'`, `'generic'` | `'array'` | Prints arrays as `T[]` or `Array<T>`, like the `@kubb/plugin-ts` option. |
|
|
77
|
+
|
|
78
|
+
See [`examples/pet-store`](./examples/pet-store) for a working setup.
|
|
79
|
+
|
|
80
|
+
## Limits
|
|
81
|
+
|
|
82
|
+
- Only `@kubb/plugin-ts` runs, and `arrayType` is its only option you can set. `kubb.config.ts` is not read.
|
|
83
|
+
- Properties of operation types (path parameters, inline response bodies) do not link to the spec, and renaming a type does not rename the key in the spec.
|
|
84
|
+
- A changed spec runs a full Kubb build: about 0.4 s and 155 MB for a 10 KB spec, about 2.6 s and 245 MB for a 1.4 MB spec. A repeated request for unchanged content reuses the last result.
|
|
85
|
+
|
|
86
|
+
## Supporting Kubb
|
|
87
|
+
|
|
88
|
+
Kubb is an open source project, and its development is funded entirely by sponsors. If you would like to become a sponsor, please consider:
|
|
89
|
+
|
|
90
|
+
- [Become a Sponsor on GitHub](https://github.com/sponsors/stijnvanhulle)
|
|
91
|
+
|
|
92
|
+
<p align="center">
|
|
93
|
+
<a href="https://github.com/sponsors/stijnvanhulle">
|
|
94
|
+
<img src="https://raw.githubusercontent.com/stijnvanhulle/sponsors/main/sponsors.svg" alt="My sponsors" />
|
|
95
|
+
</a>
|
|
96
|
+
</p>
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { adapterOas } from "@kubb/adapter-oas";
|
|
3
|
+
import { Diagnostics, createKubb, memoryStorage } from "@kubb/core";
|
|
4
|
+
import { parserTs } from "@kubb/parser-ts";
|
|
5
|
+
import { pluginTs } from "@kubb/plugin-ts";
|
|
6
|
+
import * as yaml from "yaml";
|
|
7
|
+
import { parseDocument } from "yaml";
|
|
8
|
+
import ts from "@typescript/typescript6";
|
|
9
|
+
//#region src/cache.ts
|
|
10
|
+
/**
|
|
11
|
+
* Wraps a transform so a repeated request for the same file, content and options returns the
|
|
12
|
+
* previous result. TypeScript asks again for specs it already transformed (another project, a
|
|
13
|
+
* reload), and a Kubb build of a large spec takes seconds. A failed transform is not kept.
|
|
14
|
+
*/
|
|
15
|
+
function cacheTransform(transform) {
|
|
16
|
+
const results = /* @__PURE__ */ new Map();
|
|
17
|
+
return (params, options = {}) => {
|
|
18
|
+
const cached = results.get(params.fileName);
|
|
19
|
+
if (cached && cached.content === params.content && cached.arrayType === options.arrayType) return cached.result;
|
|
20
|
+
const result = transform(params, options);
|
|
21
|
+
results.set(params.fileName, {
|
|
22
|
+
content: params.content,
|
|
23
|
+
arrayType: options.arrayType,
|
|
24
|
+
result
|
|
25
|
+
});
|
|
26
|
+
result.catch(() => results.delete(params.fileName));
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/options.ts
|
|
32
|
+
const arrayTypes = ["array", "generic"];
|
|
33
|
+
/**
|
|
34
|
+
* Validates the raw `options` value from `openProject`. Unknown keys and invalid values are
|
|
35
|
+
* dropped and reported, so a typo shows up in `tsconfig.json` instead of being silently ignored.
|
|
36
|
+
*/
|
|
37
|
+
function parseOptions(raw) {
|
|
38
|
+
const options = {};
|
|
39
|
+
const diagnostics = [];
|
|
40
|
+
if (raw === void 0 || raw === null) return {
|
|
41
|
+
options,
|
|
42
|
+
diagnostics
|
|
43
|
+
};
|
|
44
|
+
if (typeof raw !== "object" || Array.isArray(raw)) return {
|
|
45
|
+
options,
|
|
46
|
+
diagnostics: [{
|
|
47
|
+
path: [],
|
|
48
|
+
messageText: "Expected `options` to be an object."
|
|
49
|
+
}]
|
|
50
|
+
};
|
|
51
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
52
|
+
if (key !== "arrayType") {
|
|
53
|
+
diagnostics.push({
|
|
54
|
+
path: [key],
|
|
55
|
+
messageText: `Unknown option "${key}". Supported: arrayType.`
|
|
56
|
+
});
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (typeof value !== "string" || !arrayTypes.includes(value)) {
|
|
60
|
+
diagnostics.push({
|
|
61
|
+
path: [key],
|
|
62
|
+
messageText: `Expected "arrayType" to be one of ${arrayTypes.map((type) => `"${type}"`).join(", ")}.`
|
|
63
|
+
});
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
options.arrayType = value;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
options,
|
|
70
|
+
diagnostics
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/rpc.ts
|
|
75
|
+
const separator = "\r\n\r\n";
|
|
76
|
+
/**
|
|
77
|
+
* Frames a message with the LSP base protocol `Content-Length` header the host reads.
|
|
78
|
+
*/
|
|
79
|
+
function encode(message) {
|
|
80
|
+
const body = Buffer.from(JSON.stringify({
|
|
81
|
+
jsonrpc: "2.0",
|
|
82
|
+
...message
|
|
83
|
+
}));
|
|
84
|
+
return Buffer.concat([Buffer.from(`Content-Length: ${body.length}${separator}`), body]);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns a stream handler that collects `Content-Length` framed chunks and calls `onMessage`
|
|
88
|
+
* once per complete message, however the chunks split the frames.
|
|
89
|
+
*/
|
|
90
|
+
function createDecoder(onMessage) {
|
|
91
|
+
let buffer = Buffer.alloc(0);
|
|
92
|
+
return (chunk) => {
|
|
93
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
94
|
+
while (true) {
|
|
95
|
+
const headerEnd = buffer.indexOf(separator);
|
|
96
|
+
if (headerEnd === -1) return;
|
|
97
|
+
const header = buffer.subarray(0, headerEnd).toString();
|
|
98
|
+
const length = Number(/content-length:\s*(\d+)/i.exec(header)?.[1]);
|
|
99
|
+
if (!Number.isInteger(length)) throw new Error(`Missing Content-Length header in "${header}"`);
|
|
100
|
+
const start = headerEnd + 4;
|
|
101
|
+
if (buffer.length < start + length) return;
|
|
102
|
+
const body = buffer.subarray(start, start + length).toString();
|
|
103
|
+
buffer = buffer.subarray(start + length);
|
|
104
|
+
onMessage(JSON.parse(body));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/locate.ts
|
|
110
|
+
const toRange = ([start, end]) => ({
|
|
111
|
+
start,
|
|
112
|
+
end
|
|
113
|
+
});
|
|
114
|
+
const unescapeToken = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
115
|
+
/** Walks a JSON pointer through maps and sequences; the range is the last key or item it reached. */
|
|
116
|
+
function findPointer(document, pointer) {
|
|
117
|
+
return pointer.replace(/^#/, "").split("/").slice(1).map(unescapeToken).reduce((at, token) => {
|
|
118
|
+
if (yaml.isMap(at?.node)) {
|
|
119
|
+
const pair = at.node.items.find((item) => yaml.isScalar(item.key) && String(item.key.value) === token);
|
|
120
|
+
return pair && yaml.isScalar(pair.key) && pair.key.range ? {
|
|
121
|
+
node: pair.value,
|
|
122
|
+
range: toRange(pair.key.range)
|
|
123
|
+
} : void 0;
|
|
124
|
+
}
|
|
125
|
+
if (yaml.isSeq(at?.node)) {
|
|
126
|
+
const item = at.node.items[Number(token)];
|
|
127
|
+
return yaml.isNode(item) && item.range ? {
|
|
128
|
+
node: item,
|
|
129
|
+
range: toRange(item.range)
|
|
130
|
+
} : void 0;
|
|
131
|
+
}
|
|
132
|
+
}, {
|
|
133
|
+
node: document.contents,
|
|
134
|
+
range: void 0
|
|
135
|
+
})?.range;
|
|
136
|
+
}
|
|
137
|
+
/** The first `$ref` whose value is `ref`. */
|
|
138
|
+
function findRefUsage(document, ref) {
|
|
139
|
+
let found;
|
|
140
|
+
yaml.visit(document, { Pair(_, { key, value }) {
|
|
141
|
+
if (!yaml.isScalar(key) || key.value !== "$ref" || !yaml.isScalar(value) || value.value !== ref || !value.range) return;
|
|
142
|
+
found = toRange(value.range);
|
|
143
|
+
return yaml.visit.BREAK;
|
|
144
|
+
} });
|
|
145
|
+
return found;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Maps JSON pointers to ranges in an already parsed spec, the same way `@kubb/adapter-oas`'s
|
|
149
|
+
* `locate` does from the spec text. Reusing the document the build parsed saves a second parse of
|
|
150
|
+
* the spec on every transform. An unresolved `$ref` falls back to its first usage.
|
|
151
|
+
*/
|
|
152
|
+
function createLocator(document) {
|
|
153
|
+
return ({ pointer, ref }) => findPointer(document, pointer) ?? (ref ? findRefUsage(document, ref) : void 0);
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/mappings.ts
|
|
157
|
+
const kindAlias = 2;
|
|
158
|
+
const features = 249;
|
|
159
|
+
const escapeToken = (token) => token.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
160
|
+
/**
|
|
161
|
+
* Narrows an operation type to the part of the operation it was generated from, by the suffix
|
|
162
|
+
* `@kubb/plugin-ts` appends to the operation name.
|
|
163
|
+
*/
|
|
164
|
+
function operationPointer(base, suffix) {
|
|
165
|
+
const status = /^Status(\d{3}|Default)/.exec(suffix)?.[1];
|
|
166
|
+
if (status) return `${base}/responses/${status === "Default" ? "default" : status}`;
|
|
167
|
+
if (/^(Path|Query|Header)/.test(suffix)) return `${base}/parameters`;
|
|
168
|
+
if (/^(Body|Request|MutationRequest)/.test(suffix)) return `${base}/requestBody`;
|
|
169
|
+
return base;
|
|
170
|
+
}
|
|
171
|
+
const longestPrefix = (keys, name) => [...keys].filter((key) => name.startsWith(key)).sort((a, b) => b.length - a.length)[0];
|
|
172
|
+
/**
|
|
173
|
+
* Pointers to try for one declaration, most specific first. Enums extracted from a schema property
|
|
174
|
+
* (`OrderStatusEnumKey`, `orderStatusEnum`) point at that property, then at the schema.
|
|
175
|
+
*/
|
|
176
|
+
function declarationPointers(name, { schemas, operations }) {
|
|
177
|
+
const schema = schemas.get(name);
|
|
178
|
+
if (schema) return [`#/components/schemas/${escapeToken(schema)}`];
|
|
179
|
+
const schemaPrefix = longestPrefix(schemas.keys(), name);
|
|
180
|
+
const operationPrefix = longestPrefix(operations.keys(), name);
|
|
181
|
+
if (schemaPrefix !== void 0 && (operationPrefix === void 0 || schemaPrefix.length > operationPrefix.length)) {
|
|
182
|
+
const base = `#/components/schemas/${escapeToken(schemas.get(schemaPrefix))}`;
|
|
183
|
+
const property = name.slice(schemaPrefix.length).replace(/(Enum)?Key$|Enum$/, "");
|
|
184
|
+
return property ? [`${base}/properties/${escapeToken(property[0].toLowerCase() + property.slice(1))}`, base] : [base];
|
|
185
|
+
}
|
|
186
|
+
if (operationPrefix === void 0) return [];
|
|
187
|
+
const { path, method } = operations.get(operationPrefix);
|
|
188
|
+
return [operationPointer(`#/paths/${escapeToken(path)}/${method.toLowerCase()}`, name.slice(operationPrefix.length))];
|
|
189
|
+
}
|
|
190
|
+
/** The object literal a property type describes, looking through `T[]` and `Array<T>`. */
|
|
191
|
+
function objectLiteral(type) {
|
|
192
|
+
if (!type) return void 0;
|
|
193
|
+
if (ts.isTypeLiteralNode(type)) return {
|
|
194
|
+
node: type,
|
|
195
|
+
items: false
|
|
196
|
+
};
|
|
197
|
+
if (ts.isArrayTypeNode(type) && ts.isTypeLiteralNode(type.elementType)) return {
|
|
198
|
+
node: type.elementType,
|
|
199
|
+
items: true
|
|
200
|
+
};
|
|
201
|
+
if (ts.isTypeReferenceNode(type) && type.typeName.getText() === "Array" && type.typeArguments?.[0] && ts.isTypeLiteralNode(type.typeArguments[0])) return {
|
|
202
|
+
node: type.typeArguments[0],
|
|
203
|
+
items: true
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/** The members of an interface, or of a type alias for an object literal. */
|
|
207
|
+
function typeMembers(statement) {
|
|
208
|
+
if (ts.isInterfaceDeclaration(statement)) return statement.members;
|
|
209
|
+
return ts.isTypeLiteralNode(statement.type) ? statement.type.members : void 0;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Builds span map segments that link generated declaration and property names to the keys they
|
|
213
|
+
* came from in the spec, so go to definition, hover and find references cross between the two.
|
|
214
|
+
*
|
|
215
|
+
* Declarations of component schemas map to `components.schemas.<name>`, their properties to
|
|
216
|
+
* `properties.<name>` (nested object literals and arrays of them included), and operation types to
|
|
217
|
+
* the operation, its parameters, request body or response. A name `locate` cannot place is left
|
|
218
|
+
* synthesized.
|
|
219
|
+
*/
|
|
220
|
+
function createMappings(text, locate, targets) {
|
|
221
|
+
const sourceFile = ts.createSourceFile("index.ts", text, ts.ScriptTarget.Latest, true);
|
|
222
|
+
const segments = [];
|
|
223
|
+
const add = (name, ...pointers) => {
|
|
224
|
+
const range = pointers.map(locate).find(Boolean);
|
|
225
|
+
if (range) segments.push([
|
|
226
|
+
name.getStart(sourceFile),
|
|
227
|
+
name.getWidth(sourceFile),
|
|
228
|
+
range.start,
|
|
229
|
+
range.end - range.start,
|
|
230
|
+
kindAlias,
|
|
231
|
+
features
|
|
232
|
+
]);
|
|
233
|
+
};
|
|
234
|
+
const addMembers = (members, pointer) => {
|
|
235
|
+
for (const member of members) {
|
|
236
|
+
if (!ts.isPropertySignature(member) || !(ts.isIdentifier(member.name) || ts.isStringLiteral(member.name))) continue;
|
|
237
|
+
const propertyPointer = `${pointer}/properties/${escapeToken(member.name.text)}`;
|
|
238
|
+
add(member.name, propertyPointer);
|
|
239
|
+
const literal = objectLiteral(member.type);
|
|
240
|
+
if (literal) addMembers(literal.node.members, literal.items ? `${propertyPointer}/items` : propertyPointer);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
for (const statement of sourceFile.statements) {
|
|
244
|
+
if (ts.isVariableStatement(statement)) {
|
|
245
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
246
|
+
if (!ts.isIdentifier(declaration.name)) continue;
|
|
247
|
+
const name = declaration.name.text;
|
|
248
|
+
add(declaration.name, ...declarationPointers(name[0].toUpperCase() + name.slice(1), targets));
|
|
249
|
+
}
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (!ts.isTypeAliasDeclaration(statement) && !ts.isInterfaceDeclaration(statement)) continue;
|
|
253
|
+
const pointers = declarationPointers(statement.name.text, targets);
|
|
254
|
+
add(statement.name, ...pointers);
|
|
255
|
+
const pointer = pointers[0];
|
|
256
|
+
if (!pointer || !targets.schemas.has(statement.name.text)) continue;
|
|
257
|
+
const members = typeMembers(statement);
|
|
258
|
+
if (members) addMembers(members, pointer);
|
|
259
|
+
}
|
|
260
|
+
return segments;
|
|
261
|
+
}
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region src/transform.ts
|
|
264
|
+
/**
|
|
265
|
+
* Generates the `@kubb/plugin-ts` types for one OpenAPI document as a single module.
|
|
266
|
+
*
|
|
267
|
+
* The spec text comes from the request, not the disk, so unsaved editor changes are typed too.
|
|
268
|
+
* It is parsed once: Kubb builds from the parsed object, and the same document places diagnostics
|
|
269
|
+
* and mappings. Nothing is written: the build runs into a memory storage. A failed build returns
|
|
270
|
+
* an empty module with the error-level diagnostics placed on the spec key they point at.
|
|
271
|
+
*/
|
|
272
|
+
async function transform({ fileName, content }, { arrayType } = {}) {
|
|
273
|
+
const document = parseDocument(content);
|
|
274
|
+
if (document.errors.length) return {
|
|
275
|
+
text: "export {}",
|
|
276
|
+
extension: ".ts",
|
|
277
|
+
diagnostics: document.errors.map((error) => ({
|
|
278
|
+
messageText: error.message,
|
|
279
|
+
start: error.pos[0],
|
|
280
|
+
length: error.pos[1] - error.pos[0]
|
|
281
|
+
}))
|
|
282
|
+
};
|
|
283
|
+
const storage = memoryStorage();
|
|
284
|
+
const kubb = createKubb({
|
|
285
|
+
root: dirname(fileName),
|
|
286
|
+
input: document.toJS(),
|
|
287
|
+
output: {
|
|
288
|
+
path: ".kubb",
|
|
289
|
+
format: false,
|
|
290
|
+
lint: false
|
|
291
|
+
},
|
|
292
|
+
adapter: adapterOas(),
|
|
293
|
+
parsers: [parserTs()],
|
|
294
|
+
plugins: [pluginTs({
|
|
295
|
+
arrayType,
|
|
296
|
+
output: { path: "index.ts" }
|
|
297
|
+
})],
|
|
298
|
+
storage
|
|
299
|
+
});
|
|
300
|
+
const targets = {
|
|
301
|
+
schemas: /* @__PURE__ */ new Map(),
|
|
302
|
+
operations: /* @__PURE__ */ new Map()
|
|
303
|
+
};
|
|
304
|
+
kubb.hooks.hook("kubb:generate:schema", (node, { resolver }) => {
|
|
305
|
+
if (node.name) targets.schemas.set(resolver.name(node.name), node.name);
|
|
306
|
+
});
|
|
307
|
+
kubb.hooks.hook("kubb:generate:operation", (node, { resolver }) => {
|
|
308
|
+
if ("path" in node && node.path && node.method) targets.operations.set(resolver.name(node.operationId), {
|
|
309
|
+
path: node.path,
|
|
310
|
+
method: node.method
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
const { diagnostics } = await kubb.safeBuild();
|
|
314
|
+
const errors = diagnostics.filter(Diagnostics.isProblem).filter((diagnostic) => diagnostic.severity === "error");
|
|
315
|
+
const [key] = await storage.readKeys();
|
|
316
|
+
const text = key ? await storage.readItem(key) : null;
|
|
317
|
+
const locate = createLocator(document);
|
|
318
|
+
if (errors.length || !text) return {
|
|
319
|
+
text: "export {}",
|
|
320
|
+
extension: ".ts",
|
|
321
|
+
diagnostics: errors.map((error) => {
|
|
322
|
+
const range = error.location && "pointer" in error.location ? locate(error.location) : void 0;
|
|
323
|
+
return {
|
|
324
|
+
messageText: error.message,
|
|
325
|
+
start: range?.start ?? 0,
|
|
326
|
+
length: range ? range.end - range.start : 0
|
|
327
|
+
};
|
|
328
|
+
})
|
|
329
|
+
};
|
|
330
|
+
return {
|
|
331
|
+
text,
|
|
332
|
+
extension: ".ts",
|
|
333
|
+
mappings: createMappings(text, (pointer) => locate({ pointer }), targets)
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/server.ts
|
|
338
|
+
const writeProtocol = process.stdout.write.bind(process.stdout);
|
|
339
|
+
process.stdout.write = process.stderr.write.bind(process.stderr);
|
|
340
|
+
const projects = /* @__PURE__ */ new Map();
|
|
341
|
+
const cachedTransform = cacheTransform(transform);
|
|
342
|
+
const handlers = {
|
|
343
|
+
initialize: () => ({
|
|
344
|
+
protocolVersion: 1,
|
|
345
|
+
positionEncoding: "utf-16",
|
|
346
|
+
diagnosticSource: "kubb"
|
|
347
|
+
}),
|
|
348
|
+
openProject: ({ projectHandle, options }) => {
|
|
349
|
+
const parsed = parseOptions(options);
|
|
350
|
+
projects.set(projectHandle, parsed.options);
|
|
351
|
+
return parsed.diagnostics.length ? { optionDiagnostics: parsed.diagnostics } : {};
|
|
352
|
+
},
|
|
353
|
+
closeProject: ({ projectHandle }) => {
|
|
354
|
+
projects.delete(projectHandle);
|
|
355
|
+
return null;
|
|
356
|
+
},
|
|
357
|
+
transform: (params) => cachedTransform(params, projects.get(params.projectHandle))
|
|
358
|
+
};
|
|
359
|
+
async function handle({ id, method = "", params }) {
|
|
360
|
+
const handler = handlers[method];
|
|
361
|
+
if (id === void 0) return;
|
|
362
|
+
try {
|
|
363
|
+
if (!handler) {
|
|
364
|
+
writeProtocol(encode({
|
|
365
|
+
id,
|
|
366
|
+
error: {
|
|
367
|
+
code: -32601,
|
|
368
|
+
message: `Unknown method "${method}"`
|
|
369
|
+
}
|
|
370
|
+
}));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const result = await handler(params);
|
|
374
|
+
writeProtocol(encode({
|
|
375
|
+
id,
|
|
376
|
+
result: result ?? null
|
|
377
|
+
}));
|
|
378
|
+
} catch (error) {
|
|
379
|
+
writeProtocol(encode({
|
|
380
|
+
id,
|
|
381
|
+
error: {
|
|
382
|
+
code: -32603,
|
|
383
|
+
message: error instanceof Error ? error.stack ?? error.message : String(error)
|
|
384
|
+
}
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
process.stdin.on("data", createDecoder((message) => void handle(message)));
|
|
389
|
+
//#endregion
|
|
390
|
+
export {};
|
|
391
|
+
|
|
392
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":[],"sources":["../src/cache.ts","../src/options.ts","../src/rpc.ts","../src/locate.ts","../src/mappings.ts","../src/transform.ts","../src/server.ts"],"sourcesContent":["import type { Options } from './options.ts'\nimport type { TransformParams } from './transform.ts'\n\n/**\n * Wraps a transform so a repeated request for the same file, content and options returns the\n * previous result. TypeScript asks again for specs it already transformed (another project, a\n * reload), and a Kubb build of a large spec takes seconds. A failed transform is not kept.\n */\nexport function cacheTransform<TResult>(\n transform: (params: TransformParams, options?: Options) => Promise<TResult>,\n): (params: TransformParams, options?: Options) => Promise<TResult> {\n const results = new Map<string, { content: string; arrayType: Options['arrayType']; result: Promise<TResult> }>()\n\n return (params, options = {}) => {\n const cached = results.get(params.fileName)\n if (cached && cached.content === params.content && cached.arrayType === options.arrayType) return cached.result\n\n const result = transform(params, options)\n results.set(params.fileName, { content: params.content, arrayType: options.arrayType, result })\n result.catch(() => results.delete(params.fileName))\n return result\n }\n}\n","/**\n * Options read from the mapper's `contentMappers[].options` entry in `tsconfig.json`.\n */\nexport type Options = {\n /**\n * Passed to `@kubb/plugin-ts`: `'array'` prints `T[]`, `'generic'` prints `Array<T>`.\n * @default 'array'\n */\n arrayType?: 'array' | 'generic'\n}\n\n/**\n * An invalid option, reported by TypeScript on the `options` object in `tsconfig.json`.\n */\nexport type OptionDiagnostic = {\n path: Array<string>\n messageText: string\n}\n\nconst arrayTypes = ['array', 'generic']\n\n/**\n * Validates the raw `options` value from `openProject`. Unknown keys and invalid values are\n * dropped and reported, so a typo shows up in `tsconfig.json` instead of being silently ignored.\n */\nexport function parseOptions(raw: unknown): { options: Options; diagnostics: Array<OptionDiagnostic> } {\n const options: Options = {}\n const diagnostics: Array<OptionDiagnostic> = []\n\n if (raw === undefined || raw === null) return { options, diagnostics }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { options, diagnostics: [{ path: [], messageText: 'Expected `options` to be an object.' }] }\n }\n\n for (const [key, value] of Object.entries(raw)) {\n if (key !== 'arrayType') {\n diagnostics.push({ path: [key], messageText: `Unknown option \"${key}\". Supported: arrayType.` })\n continue\n }\n if (typeof value !== 'string' || !arrayTypes.includes(value)) {\n diagnostics.push({ path: [key], messageText: `Expected \"arrayType\" to be one of ${arrayTypes.map((type) => `\"${type}\"`).join(', ')}.` })\n continue\n }\n options.arrayType = value as Options['arrayType']\n }\n\n return { options, diagnostics }\n}\n","/**\n * A JSON-RPC 2.0 message as the TypeScript content mapper host sends and expects it.\n */\nexport type Message = {\n id?: number | string\n method?: string\n params?: unknown\n result?: unknown\n error?: { code: number; message: string }\n}\n\nconst separator = '\\r\\n\\r\\n'\n\n/**\n * Frames a message with the LSP base protocol `Content-Length` header the host reads.\n */\nexport function encode(message: Message): Buffer {\n const body = Buffer.from(JSON.stringify({ jsonrpc: '2.0', ...message }))\n\n return Buffer.concat([Buffer.from(`Content-Length: ${body.length}${separator}`), body])\n}\n\n/**\n * Returns a stream handler that collects `Content-Length` framed chunks and calls `onMessage`\n * once per complete message, however the chunks split the frames.\n */\nexport function createDecoder(onMessage: (message: Message) => void): (chunk: Buffer) => void {\n let buffer = Buffer.alloc(0)\n\n return (chunk) => {\n buffer = Buffer.concat([buffer, chunk])\n\n while (true) {\n const headerEnd = buffer.indexOf(separator)\n if (headerEnd === -1) return\n\n const header = buffer.subarray(0, headerEnd).toString()\n const length = Number(/content-length:\\s*(\\d+)/i.exec(header)?.[1])\n if (!Number.isInteger(length)) throw new Error(`Missing Content-Length header in \"${header}\"`)\n\n const start = headerEnd + separator.length\n if (buffer.length < start + length) return\n\n const body = buffer.subarray(start, start + length).toString()\n buffer = buffer.subarray(start + length)\n onMessage(JSON.parse(body) as Message)\n }\n }\n}\n","import * as yaml from 'yaml'\n\n/**\n * A range in the spec text, as `[start, end)` offsets.\n */\nexport type Range = { start: number; end: number }\n\nconst toRange = ([start, end]: yaml.Range): Range => ({ start, end })\n\nconst unescapeToken = (token: string) => token.replaceAll('~1', '/').replaceAll('~0', '~')\n\n/** Walks a JSON pointer through maps and sequences; the range is the last key or item it reached. */\nfunction findPointer(document: yaml.Document, pointer: string): Range | undefined {\n const tokens = pointer.replace(/^#/, '').split('/').slice(1).map(unescapeToken)\n return tokens.reduce<{ node: unknown; range: Range | undefined } | undefined>(\n (at, token) => {\n if (yaml.isMap(at?.node)) {\n const pair = at.node.items.find((item) => yaml.isScalar(item.key) && String(item.key.value) === token)\n return pair && yaml.isScalar(pair.key) && pair.key.range ? { node: pair.value, range: toRange(pair.key.range) } : undefined\n }\n if (yaml.isSeq(at?.node)) {\n const item = at.node.items[Number(token)]\n return yaml.isNode(item) && item.range ? { node: item, range: toRange(item.range) } : undefined\n }\n return undefined\n },\n { node: document.contents, range: undefined },\n )?.range\n}\n\n/** The first `$ref` whose value is `ref`. */\nfunction findRefUsage(document: yaml.Document, ref: string): Range | undefined {\n let found: Range | undefined\n yaml.visit(document, {\n Pair(_, { key, value }) {\n if (!yaml.isScalar(key) || key.value !== '$ref' || !yaml.isScalar(value) || value.value !== ref || !value.range) return\n found = toRange(value.range)\n return yaml.visit.BREAK\n },\n })\n return found\n}\n\n/**\n * Maps JSON pointers to ranges in an already parsed spec, the same way `@kubb/adapter-oas`'s\n * `locate` does from the spec text. Reusing the document the build parsed saves a second parse of\n * the spec on every transform. An unresolved `$ref` falls back to its first usage.\n */\nexport function createLocator(document: yaml.Document): (location: { pointer: string; ref?: string }) => Range | undefined {\n return ({ pointer, ref }) => findPointer(document, pointer) ?? (ref ? findRefUsage(document, ref) : undefined)\n}\n","import ts from '@typescript/typescript6'\n\n/**\n * A span map segment in the tuple form TypeScript reads:\n * `[virtualStart, virtualLength, originalStart, originalLength, kind, features]`.\n */\nexport type Segment = [number, number, number, number, number, number]\n\n/**\n * What the build saw, keyed by the names `@kubb/plugin-ts` emitted.\n */\nexport type Targets = {\n /**\n * Emitted type name to the `components.schemas` key it came from.\n */\n schemas: Map<string, string>\n /**\n * Emitted operation name prefix (such as `GetPetById`) to its path and method.\n */\n operations: Map<string, { path: string; method: string }>\n}\n\ntype Locate = (pointer: string) => { start: number; end: number } | undefined\n\nconst kindAlias = 2\n// Hover, Definition, TypeDefinition, Implementation, References, DocumentHighlights. Rename stays off\n// because only verbatim segments can write edits back to the spec.\nconst features = 1 | 8 | 16 | 32 | 64 | 128\n\nconst escapeToken = (token: string) => token.replaceAll('~', '~0').replaceAll('/', '~1')\n\n/**\n * Narrows an operation type to the part of the operation it was generated from, by the suffix\n * `@kubb/plugin-ts` appends to the operation name.\n */\nfunction operationPointer(base: string, suffix: string): string {\n const status = /^Status(\\d{3}|Default)/.exec(suffix)?.[1]\n if (status) return `${base}/responses/${status === 'Default' ? 'default' : status}`\n if (/^(Path|Query|Header)/.test(suffix)) return `${base}/parameters`\n if (/^(Body|Request|MutationRequest)/.test(suffix)) return `${base}/requestBody`\n return base\n}\n\nconst longestPrefix = (keys: Iterable<string>, name: string) => [...keys].filter((key) => name.startsWith(key)).sort((a, b) => b.length - a.length)[0]\n\n/**\n * Pointers to try for one declaration, most specific first. Enums extracted from a schema property\n * (`OrderStatusEnumKey`, `orderStatusEnum`) point at that property, then at the schema.\n */\nfunction declarationPointers(name: string, { schemas, operations }: Targets): Array<string> {\n const schema = schemas.get(name)\n if (schema) return [`#/components/schemas/${escapeToken(schema)}`]\n\n const schemaPrefix = longestPrefix(schemas.keys(), name)\n const operationPrefix = longestPrefix(operations.keys(), name)\n\n if (schemaPrefix !== undefined && (operationPrefix === undefined || schemaPrefix.length > operationPrefix.length)) {\n const base = `#/components/schemas/${escapeToken(schemas.get(schemaPrefix)!)}`\n const property = name.slice(schemaPrefix.length).replace(/(Enum)?Key$|Enum$/, '')\n return property ? [`${base}/properties/${escapeToken(property[0]!.toLowerCase() + property.slice(1))}`, base] : [base]\n }\n if (operationPrefix === undefined) return []\n\n const { path, method } = operations.get(operationPrefix)!\n return [operationPointer(`#/paths/${escapeToken(path)}/${method.toLowerCase()}`, name.slice(operationPrefix.length))]\n}\n\n/** The object literal a property type describes, looking through `T[]` and `Array<T>`. */\nfunction objectLiteral(type: ts.TypeNode | undefined): { node: ts.TypeLiteralNode; items: boolean } | undefined {\n if (!type) return undefined\n if (ts.isTypeLiteralNode(type)) return { node: type, items: false }\n if (ts.isArrayTypeNode(type) && ts.isTypeLiteralNode(type.elementType)) return { node: type.elementType, items: true }\n if (ts.isTypeReferenceNode(type) && type.typeName.getText() === 'Array' && type.typeArguments?.[0] && ts.isTypeLiteralNode(type.typeArguments[0])) {\n return { node: type.typeArguments[0], items: true }\n }\n return undefined\n}\n\n/** The members of an interface, or of a type alias for an object literal. */\nfunction typeMembers(statement: ts.TypeAliasDeclaration | ts.InterfaceDeclaration): ts.NodeArray<ts.TypeElement> | undefined {\n if (ts.isInterfaceDeclaration(statement)) return statement.members\n return ts.isTypeLiteralNode(statement.type) ? statement.type.members : undefined\n}\n\n/**\n * Builds span map segments that link generated declaration and property names to the keys they\n * came from in the spec, so go to definition, hover and find references cross between the two.\n *\n * Declarations of component schemas map to `components.schemas.<name>`, their properties to\n * `properties.<name>` (nested object literals and arrays of them included), and operation types to\n * the operation, its parameters, request body or response. A name `locate` cannot place is left\n * synthesized.\n */\nexport function createMappings(text: string, locate: Locate, targets: Targets): Array<Segment> {\n const sourceFile = ts.createSourceFile('index.ts', text, ts.ScriptTarget.Latest, true)\n const segments: Array<Segment> = []\n\n const add = (name: ts.Node, ...pointers: Array<string>) => {\n const range = pointers.map(locate).find(Boolean)\n if (range) segments.push([name.getStart(sourceFile), name.getWidth(sourceFile), range.start, range.end - range.start, kindAlias, features])\n }\n\n const addMembers = (members: ts.NodeArray<ts.TypeElement>, pointer: string) => {\n for (const member of members) {\n if (!ts.isPropertySignature(member) || !(ts.isIdentifier(member.name) || ts.isStringLiteral(member.name))) continue\n const propertyPointer = `${pointer}/properties/${escapeToken(member.name.text)}`\n add(member.name, propertyPointer)\n const literal = objectLiteral(member.type)\n if (literal) addMembers(literal.node.members, literal.items ? `${propertyPointer}/items` : propertyPointer)\n }\n }\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) {\n // Enum objects (`export const orderStatusEnum = { ... } as const`) match like their `Key` type.\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue\n const name = declaration.name.text\n add(declaration.name, ...declarationPointers(name[0]!.toUpperCase() + name.slice(1), targets))\n }\n continue\n }\n if (!ts.isTypeAliasDeclaration(statement) && !ts.isInterfaceDeclaration(statement)) continue\n const pointers = declarationPointers(statement.name.text, targets)\n add(statement.name, ...pointers)\n\n // Property names only resolve under a schema, not under operation parameters or responses.\n const pointer = pointers[0]\n if (!pointer || !targets.schemas.has(statement.name.text)) continue\n const members = typeMembers(statement)\n if (members) addMembers(members, pointer)\n }\n\n return segments\n}\n","import { dirname } from 'node:path'\nimport { adapterOas } from '@kubb/adapter-oas'\nimport { createKubb, Diagnostics, memoryStorage } from '@kubb/core'\nimport { parserTs } from '@kubb/parser-ts'\nimport { pluginTs } from '@kubb/plugin-ts'\nimport { parseDocument } from 'yaml'\nimport { createLocator } from './locate.ts'\nimport { createMappings, type Segment, type Targets } from './mappings.ts'\nimport type { Options } from './options.ts'\n\n/**\n * Parameters of the content mapper `transform` request.\n */\nexport type TransformParams = {\n fileName: string\n content: string\n}\n\n/**\n * Result of the content mapper `transform` request: the virtual TypeScript module TypeScript\n * checks in place of the spec file, and the segments linking its names back to the spec.\n */\nexport type TransformResult = {\n text: string\n extension: '.ts'\n mappings?: Array<Segment>\n diagnostics?: Array<{ messageText: string; start: number; length: number }>\n}\n\n/**\n * Generates the `@kubb/plugin-ts` types for one OpenAPI document as a single module.\n *\n * The spec text comes from the request, not the disk, so unsaved editor changes are typed too.\n * It is parsed once: Kubb builds from the parsed object, and the same document places diagnostics\n * and mappings. Nothing is written: the build runs into a memory storage. A failed build returns\n * an empty module with the error-level diagnostics placed on the spec key they point at.\n */\nexport async function transform({ fileName, content }: TransformParams, { arrayType }: Options = {}): Promise<TransformResult> {\n const document = parseDocument(content)\n if (document.errors.length) {\n return {\n text: 'export {}',\n extension: '.ts',\n diagnostics: document.errors.map((error) => ({ messageText: error.message, start: error.pos[0], length: error.pos[1] - error.pos[0] })),\n }\n }\n\n const storage = memoryStorage()\n const kubb = createKubb({\n root: dirname(fileName),\n input: document.toJS(),\n output: { path: '.kubb', format: false, lint: false },\n adapter: adapterOas(),\n parsers: [parserTs()],\n plugins: [pluginTs({ arrayType, output: { path: 'index.ts' } })],\n storage,\n })\n\n const targets: Targets = { schemas: new Map(), operations: new Map() }\n kubb.hooks.hook('kubb:generate:schema', (node, { resolver }) => {\n if (node.name) targets.schemas.set(resolver.name(node.name), node.name)\n })\n kubb.hooks.hook('kubb:generate:operation', (node, { resolver }) => {\n if ('path' in node && node.path && node.method) targets.operations.set(resolver.name(node.operationId), { path: node.path, method: node.method })\n })\n\n const { diagnostics } = await kubb.safeBuild()\n const errors = diagnostics.filter(Diagnostics.isProblem).filter((diagnostic) => diagnostic.severity === 'error')\n const [key] = await storage.readKeys()\n const text = key ? await storage.readItem(key) : null\n\n const locate = createLocator(document)\n\n if (errors.length || !text) {\n return {\n text: 'export {}',\n extension: '.ts',\n diagnostics: errors.map((error) => {\n const range = error.location && 'pointer' in error.location ? locate(error.location) : undefined\n return { messageText: error.message, start: range?.start ?? 0, length: range ? range.end - range.start : 0 }\n }),\n }\n }\n\n return { text, extension: '.ts', mappings: createMappings(text, (pointer) => locate({ pointer }), targets) }\n}\n","import { cacheTransform } from './cache.ts'\nimport { type Options, parseOptions } from './options.ts'\nimport { createDecoder, encode, type Message } from './rpc.ts'\nimport { transform, type TransformParams } from './transform.ts'\n\n// stdout carries the protocol, so every other stdout write (any console method, direct writes from\n// Kubb or its plugins) goes to stderr.\nconst writeProtocol = process.stdout.write.bind(process.stdout)\nprocess.stdout.write = process.stderr.write.bind(process.stderr) as typeof process.stdout.write\n\nconst projects = new Map<string, Options>()\n\nconst cachedTransform = cacheTransform(transform)\n\nconst handlers: Record<string, (params: never) => unknown> = {\n initialize: () => ({ protocolVersion: 1, positionEncoding: 'utf-16', diagnosticSource: 'kubb' }),\n openProject: ({ projectHandle, options }: { projectHandle: string; options?: unknown }) => {\n const parsed = parseOptions(options)\n projects.set(projectHandle, parsed.options)\n\n return parsed.diagnostics.length ? { optionDiagnostics: parsed.diagnostics } : {}\n },\n closeProject: ({ projectHandle }: { projectHandle: string }) => {\n projects.delete(projectHandle)\n return null\n },\n transform: (params: TransformParams & { projectHandle: string }) => cachedTransform(params, projects.get(params.projectHandle)),\n}\n\nasync function handle({ id, method = '', params }: Message): Promise<void> {\n const handler = handlers[method]\n if (id === undefined) return\n\n try {\n if (!handler) {\n writeProtocol(encode({ id, error: { code: -32601, message: `Unknown method \"${method}\"` } }))\n return\n }\n const result = await handler(params as never)\n writeProtocol(encode({ id, result: result ?? null }))\n } catch (error) {\n writeProtocol(encode({ id, error: { code: -32603, message: error instanceof Error ? (error.stack ?? error.message) : String(error) } }))\n }\n}\n\nprocess.stdin.on(\n 'data',\n createDecoder((message) => void handle(message)),\n)\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,100 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-import",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Import OpenAPI specs in TypeScript with types from Kubb, through TypeScript 7.1 content mappers. No generated files.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"code-generation",
|
|
7
|
+
"codegen",
|
|
8
|
+
"content-mapper",
|
|
9
|
+
"kubb",
|
|
10
|
+
"openapi",
|
|
11
|
+
"openapi-import",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/kubb-labs/openapi-import#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/kubb-labs/openapi-import/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "stijnvanhulle",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/kubb-labs/openapi-import.git"
|
|
23
|
+
},
|
|
24
|
+
"funding": [
|
|
25
|
+
{
|
|
26
|
+
"type": "github",
|
|
27
|
+
"url": "https://github.com/sponsors/stijnvanhulle"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"type": "opencollective",
|
|
31
|
+
"url": "https://opencollective.com/kubb"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"type": "custom",
|
|
35
|
+
"url": "https://kubb.dev/sponsors"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"!/**/**.test.**"
|
|
41
|
+
],
|
|
42
|
+
"type": "module",
|
|
43
|
+
"sideEffects": true,
|
|
44
|
+
"exports": {
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"registry": "https://registry.npmjs.org/"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsdown",
|
|
53
|
+
"changeset": "changeset",
|
|
54
|
+
"clean": "node -e \"require('node:fs').rmSync('./dist', {recursive:true,force:true})\"",
|
|
55
|
+
"format": "oxfmt -c oxfmt.config.ts .",
|
|
56
|
+
"format:check": "oxfmt -c oxfmt.config.ts --check .",
|
|
57
|
+
"lint": "oxlint -c oxlint.config.ts .",
|
|
58
|
+
"lint:fix": "oxlint -c oxlint.config.ts --fix .",
|
|
59
|
+
"start": "tsdown --watch",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"typecheck": "tsc",
|
|
62
|
+
"typecheck:example": "pnpm --filter openapi-import-pet-store typecheck"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@kubb/adapter-oas": "^5.12.5",
|
|
66
|
+
"@kubb/core": "^5.12.5",
|
|
67
|
+
"@kubb/parser-ts": "^5.12.5",
|
|
68
|
+
"@kubb/plugin-ts": "^5.0.14",
|
|
69
|
+
"@typescript/typescript6": "^6.0.2",
|
|
70
|
+
"yaml": "^2.9.1"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@changesets/changelog-github": "^1.0.1",
|
|
74
|
+
"@changesets/cli": "^3.0.3",
|
|
75
|
+
"@types/node": "22.20.2",
|
|
76
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
77
|
+
"kubb": "^5.12.5",
|
|
78
|
+
"oxfmt": "^0.72.0",
|
|
79
|
+
"oxlint": "^1.88.0",
|
|
80
|
+
"tsdown": "^0.23.1",
|
|
81
|
+
"typescript": "^7.0.2",
|
|
82
|
+
"vitest": "^5.0.5"
|
|
83
|
+
},
|
|
84
|
+
"peerDependencies": {
|
|
85
|
+
"kubb": "^5.12.5"
|
|
86
|
+
},
|
|
87
|
+
"typescript": {
|
|
88
|
+
"contentMapper": {
|
|
89
|
+
"exec": [
|
|
90
|
+
"node",
|
|
91
|
+
"dist/server.js"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">=22.12",
|
|
97
|
+
"pnpm": ">=11.0.0"
|
|
98
|
+
},
|
|
99
|
+
"packageManager": "pnpm@12.11.2"
|
|
100
|
+
}
|