openapi-import 0.0.0 → 0.0.1
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/README.md +43 -39
- package/dist/server.js +119 -103
- package/dist/server.js.map +1 -1
- package/package.json +21 -22
package/README.md
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
# openapi-import
|
|
2
2
|
|
|
3
|
-
Import an OpenAPI spec
|
|
3
|
+
Import an OpenAPI spec in TypeScript and get the code the plugins in your `kubb.config.ts` generate, without generated files.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import type
|
|
7
|
-
|
|
8
|
-
const pet: Pet = { name: 'Rex', photoUrls: [] }
|
|
6
|
+
import { type Pet, petSchema } from './petStore.openapi.yaml'
|
|
9
7
|
```
|
|
10
8
|
|
|
11
|
-
It is a [TypeScript content mapper](https://github.com/microsoft/typescript-go/pull/4712)
|
|
9
|
+
It is a [TypeScript content mapper](https://github.com/microsoft/typescript-go/pull/4712): TypeScript 7.1 type-checks the output of every plugin in your config in place of the spec.
|
|
12
10
|
|
|
13
11
|
> [!WARNING]
|
|
14
|
-
> Experimental.
|
|
12
|
+
> Experimental. It needs TypeScript 7.1.0-beta or later with `--runExternalCode`. TypeScript does not emit the spec to JavaScript, so values such as `petSchema` only exist at run time when a bundler loads the spec with [`unplugin-kubb`](https://github.com/kubb-labs/kubb/tree/main/packages/unplugin-kubb).
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- Import a `.openapi.yaml` spec straight into TypeScript, with no generated files.
|
|
17
|
+
- Works without a config: you get the types from `@kubb/plugin-ts`.
|
|
18
|
+
- Add a `kubb.config.ts` to get Zod schemas, clients and the output of any other Kubb plugin from the same import.
|
|
19
|
+
- Autocomplete and type errors come from the spec.
|
|
20
|
+
- Go to definition, find references and hover jump between the types and the spec.
|
|
21
|
+
- Rename a schema type in TypeScript and the key in the spec is renamed too.
|
|
22
|
+
- Spec errors, such as an unresolved `$ref`, show on the key they point at.
|
|
23
|
+
- `tsc --runExternalCode` reports the same errors in CI.
|
|
24
|
+
- At run time, `unplugin-kubb` loads the same module in Vite, webpack, Rollup and other bundlers.
|
|
15
25
|
|
|
16
26
|
## Setup
|
|
17
27
|
|
|
18
28
|
```bash
|
|
19
|
-
pnpm add -D kubb openapi-import typescript@
|
|
29
|
+
pnpm add -D kubb openapi-import typescript@beta @kubb/plugin-ts
|
|
20
30
|
```
|
|
21
31
|
|
|
22
|
-
npm
|
|
32
|
+
With npm, `tsc` runs TypeScript 6, because `@typescript/typescript6` links its `tsc` over the one from `typescript`. Run `node node_modules/typescript/bin/tsc` instead.
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
Register the `.openapi.yaml` extension in `tsconfig.json`. A plain `.yaml` would also send files such as `docker-compose.yaml` to the mapper, and `.json` can't be mapped.
|
|
25
35
|
|
|
26
36
|
```json
|
|
27
37
|
{
|
|
@@ -29,19 +39,34 @@ Name your specs with an `.openapi.yaml` extension, such as `petStore.openapi.yam
|
|
|
29
39
|
}
|
|
30
40
|
```
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
Add the plugins you want to `kubb.config.ts`, and install them, such as `@kubb/plugin-zod` and `zod`:
|
|
33
43
|
|
|
34
|
-
|
|
44
|
+
```ts
|
|
45
|
+
import { pluginTs } from '@kubb/plugin-ts'
|
|
46
|
+
import { pluginZod } from '@kubb/plugin-zod'
|
|
47
|
+
import { defineConfig } from 'kubb/config'
|
|
48
|
+
|
|
49
|
+
export default defineConfig({
|
|
50
|
+
output: { path: './src/gen' },
|
|
51
|
+
plugins: [pluginTs(), pluginZod()],
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The mapper finds the config like the Kubb CLI does and reloads it when it changes. With several configs, a spec uses the one whose `input` matches it. Without a config, only `@kubb/plugin-ts` runs.
|
|
56
|
+
|
|
57
|
+
For values at run time, add `kubb()` from `kubb/vite` or another bundler entry, without a `config` option, so it reads the same `kubb.config.ts` as `tsc`. A config with an `input` also writes the generated files at build time, so leave it out to import specs only.
|
|
58
|
+
|
|
59
|
+
Run the type check:
|
|
35
60
|
|
|
36
61
|
```bash
|
|
37
62
|
tsc --noEmit --runExternalCode
|
|
38
63
|
```
|
|
39
64
|
|
|
40
|
-
VS Code passes `--runExternalCode`
|
|
65
|
+
VS Code only passes `--runExternalCode` in trusted workspaces.
|
|
41
66
|
|
|
42
67
|
## Editor support
|
|
43
68
|
|
|
44
|
-
|
|
69
|
+
Go to definition, find references and hover link generated names to their keys in the spec. Renaming a schema type named like its key, such as `Pet`, renames the key too. Update the `$ref`s to it yourself.
|
|
45
70
|
|
|
46
71
|
| Generated name | Jumps to |
|
|
47
72
|
| ------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
@@ -53,35 +78,14 @@ Generated names link back to the keys they came from in the spec. Go to definiti
|
|
|
53
78
|
| `GetPetByIdStatus404` | `responses.404` |
|
|
54
79
|
| `AddPetBody` | the operation's `requestBody` |
|
|
55
80
|
|
|
56
|
-
Spec errors, such as an unresolved `$ref`, show on the key
|
|
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.
|
|
81
|
+
Spec errors, such as an unresolved `$ref`, show on the key they point at. See [`examples/pet-store`](./examples/pet-store) for a working setup.
|
|
79
82
|
|
|
80
83
|
## Limits
|
|
81
84
|
|
|
82
|
-
-
|
|
83
|
-
- Properties of operation types
|
|
84
|
-
-
|
|
85
|
+
- Code a plugin writes to a separate file, such as a bundled client runtime, is not included. Point imports like the client's `importPath` at a package.
|
|
86
|
+
- Properties of operation types don't link to the spec, and renaming a property doesn't rename its key.
|
|
87
|
+
- Files that `kubb.config.ts` imports are not watched. Restart the TypeScript server after you change them.
|
|
88
|
+
- A changed spec runs a full Kubb build: about 0.4 s for a 10 KB spec and 2.6 s for a 1.4 MB spec.
|
|
85
89
|
|
|
86
90
|
## Supporting Kubb
|
|
87
91
|
|
package/dist/server.js
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import { dirname } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { configFileCandidates, findConfigFile, generateModule, loadConfigFile, selectConfig } from "unplugin-kubb";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { Hookable } from "kubb/kit";
|
|
5
6
|
import { pluginTs } from "@kubb/plugin-ts";
|
|
6
7
|
import * as yaml from "yaml";
|
|
7
8
|
import { parseDocument } from "yaml";
|
|
8
9
|
import ts from "@typescript/typescript6";
|
|
9
10
|
//#region src/cache.ts
|
|
10
11
|
/**
|
|
11
|
-
* Wraps a transform so a repeated request for the same file, content and
|
|
12
|
+
* Wraps a transform so a repeated request for the same file, content and config returns the
|
|
12
13
|
* previous result. TypeScript asks again for specs it already transformed (another project, a
|
|
13
14
|
* reload), and a Kubb build of a large spec takes seconds. A failed transform is not kept.
|
|
14
15
|
*/
|
|
15
16
|
function cacheTransform(transform) {
|
|
16
17
|
const results = /* @__PURE__ */ new Map();
|
|
17
|
-
return (params,
|
|
18
|
+
return (params, config) => {
|
|
18
19
|
const cached = results.get(params.fileName);
|
|
19
|
-
if (cached && cached.content === params.content && cached.
|
|
20
|
-
const result = transform(params,
|
|
20
|
+
if (cached && cached.content === params.content && cached.config === config) return cached.result;
|
|
21
|
+
const result = transform(params, config);
|
|
21
22
|
results.set(params.fileName, {
|
|
22
23
|
content: params.content,
|
|
23
|
-
|
|
24
|
+
config,
|
|
24
25
|
result
|
|
25
26
|
});
|
|
26
27
|
result.catch(() => results.delete(params.fileName));
|
|
@@ -28,47 +29,38 @@ function cacheTransform(transform) {
|
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
//#endregion
|
|
31
|
-
//#region src/
|
|
32
|
-
const arrayTypes = ["array", "generic"];
|
|
32
|
+
//#region src/config.ts
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* Finds the Kubb config the way the Kubb CLI does, from `dir` up, and loads it. A config that
|
|
35
|
+
* exports a function is called with no CLI options.
|
|
36
36
|
*/
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
async function loadProjectConfig(dir) {
|
|
38
|
+
dir = resolve(dir);
|
|
39
|
+
const file = findConfigFile(dir);
|
|
40
|
+
const watchedFiles = [.../* @__PURE__ */ new Set([...file ? [file] : [], ...configFileCandidates(dir)])];
|
|
41
|
+
if (!file) return {
|
|
42
|
+
dir,
|
|
43
|
+
configs: [],
|
|
44
|
+
watchedFiles,
|
|
45
|
+
identity: "none"
|
|
43
46
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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;
|
|
47
|
+
const identity = createHash("sha256").update(readFileSync(file)).digest("hex");
|
|
48
|
+
try {
|
|
49
|
+
return {
|
|
50
|
+
dir,
|
|
51
|
+
configs: await loadConfigFile(file, {}),
|
|
52
|
+
watchedFiles,
|
|
53
|
+
identity
|
|
54
|
+
};
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
dir,
|
|
58
|
+
configs: [],
|
|
59
|
+
watchedFiles,
|
|
60
|
+
identity,
|
|
61
|
+
error: `${file} failed to load: ${error instanceof Error ? error.message : String(error)}`
|
|
62
|
+
};
|
|
67
63
|
}
|
|
68
|
-
return {
|
|
69
|
-
options,
|
|
70
|
-
diagnostics
|
|
71
|
-
};
|
|
72
64
|
}
|
|
73
65
|
//#endregion
|
|
74
66
|
//#region src/rpc.ts
|
|
@@ -112,7 +104,9 @@ const toRange = ([start, end]) => ({
|
|
|
112
104
|
end
|
|
113
105
|
});
|
|
114
106
|
const unescapeToken = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
115
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* Walks a JSON pointer through maps and sequences; the range is the last key or item it reached.
|
|
109
|
+
*/
|
|
116
110
|
function findPointer(document, pointer) {
|
|
117
111
|
return pointer.replace(/^#/, "").split("/").slice(1).map(unescapeToken).reduce((at, token) => {
|
|
118
112
|
if (yaml.isMap(at?.node)) {
|
|
@@ -134,7 +128,9 @@ function findPointer(document, pointer) {
|
|
|
134
128
|
range: void 0
|
|
135
129
|
})?.range;
|
|
136
130
|
}
|
|
137
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* The first `$ref` whose value is `ref`.
|
|
133
|
+
*/
|
|
138
134
|
function findRefUsage(document, ref) {
|
|
139
135
|
let found;
|
|
140
136
|
yaml.visit(document, { Pair(_, { key, value }) {
|
|
@@ -154,6 +150,7 @@ function createLocator(document) {
|
|
|
154
150
|
}
|
|
155
151
|
//#endregion
|
|
156
152
|
//#region src/mappings.ts
|
|
153
|
+
const kindVerbatim = 0;
|
|
157
154
|
const kindAlias = 2;
|
|
158
155
|
const features = 249;
|
|
159
156
|
const escapeToken = (token) => token.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
@@ -187,7 +184,9 @@ function declarationPointers(name, { schemas, operations }) {
|
|
|
187
184
|
const { path, method } = operations.get(operationPrefix);
|
|
188
185
|
return [operationPointer(`#/paths/${escapeToken(path)}/${method.toLowerCase()}`, name.slice(operationPrefix.length))];
|
|
189
186
|
}
|
|
190
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* The object literal a property type describes, looking through `T[]` and `Array<T>`.
|
|
189
|
+
*/
|
|
191
190
|
function objectLiteral(type) {
|
|
192
191
|
if (!type) return void 0;
|
|
193
192
|
if (ts.isTypeLiteralNode(type)) return {
|
|
@@ -203,39 +202,39 @@ function objectLiteral(type) {
|
|
|
203
202
|
items: true
|
|
204
203
|
};
|
|
205
204
|
}
|
|
206
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* The members of an interface, or of a type alias for an object literal.
|
|
207
|
+
*/
|
|
207
208
|
function typeMembers(statement) {
|
|
208
209
|
if (ts.isInterfaceDeclaration(statement)) return statement.members;
|
|
209
210
|
return ts.isTypeLiteralNode(statement.type) ? statement.type.members : void 0;
|
|
210
211
|
}
|
|
211
212
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
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.
|
|
213
|
+
* Links generated names to the spec keys they came from: schemas and their (nested) properties,
|
|
214
|
+
* and operation types to the operation, parameters, request body or response. A schema type named
|
|
215
|
+
* exactly like its key is verbatim, so a rename in TypeScript renames the key.
|
|
219
216
|
*/
|
|
220
|
-
function createMappings(text, locate, targets) {
|
|
217
|
+
function createMappings(text, content, locate, targets) {
|
|
221
218
|
const sourceFile = ts.createSourceFile("index.ts", text, ts.ScriptTarget.Latest, true);
|
|
222
219
|
const segments = [];
|
|
223
|
-
const add = (name, ...pointers) => {
|
|
220
|
+
const add = (name, rename, ...pointers) => {
|
|
224
221
|
const range = pointers.map(locate).find(Boolean);
|
|
225
|
-
if (range)
|
|
222
|
+
if (!range) return;
|
|
223
|
+
const verbatim = rename && content.slice(range.start, range.end) === name.getText(sourceFile);
|
|
224
|
+
segments.push([
|
|
226
225
|
name.getStart(sourceFile),
|
|
227
226
|
name.getWidth(sourceFile),
|
|
228
227
|
range.start,
|
|
229
228
|
range.end - range.start,
|
|
230
|
-
kindAlias,
|
|
231
|
-
features
|
|
229
|
+
verbatim ? kindVerbatim : kindAlias,
|
|
230
|
+
verbatim ? 505 : features
|
|
232
231
|
]);
|
|
233
232
|
};
|
|
234
233
|
const addMembers = (members, pointer) => {
|
|
235
234
|
for (const member of members) {
|
|
236
235
|
if (!ts.isPropertySignature(member) || !(ts.isIdentifier(member.name) || ts.isStringLiteral(member.name))) continue;
|
|
237
236
|
const propertyPointer = `${pointer}/properties/${escapeToken(member.name.text)}`;
|
|
238
|
-
add(member.name, propertyPointer);
|
|
237
|
+
add(member.name, false, propertyPointer);
|
|
239
238
|
const literal = objectLiteral(member.type);
|
|
240
239
|
if (literal) addMembers(literal.node.members, literal.items ? `${propertyPointer}/items` : propertyPointer);
|
|
241
240
|
}
|
|
@@ -245,15 +244,16 @@ function createMappings(text, locate, targets) {
|
|
|
245
244
|
for (const declaration of statement.declarationList.declarations) {
|
|
246
245
|
if (!ts.isIdentifier(declaration.name)) continue;
|
|
247
246
|
const name = declaration.name.text;
|
|
248
|
-
add(declaration.name, ...declarationPointers(name[0].toUpperCase() + name.slice(1), targets));
|
|
247
|
+
add(declaration.name, false, ...declarationPointers(name, targets), ...declarationPointers(name[0].toUpperCase() + name.slice(1), targets));
|
|
249
248
|
}
|
|
250
249
|
continue;
|
|
251
250
|
}
|
|
252
251
|
if (!ts.isTypeAliasDeclaration(statement) && !ts.isInterfaceDeclaration(statement)) continue;
|
|
253
252
|
const pointers = declarationPointers(statement.name.text, targets);
|
|
254
|
-
|
|
253
|
+
const isSchema = targets.schemas.has(statement.name.text);
|
|
254
|
+
add(statement.name, isSchema, ...pointers);
|
|
255
255
|
const pointer = pointers[0];
|
|
256
|
-
if (!pointer || !
|
|
256
|
+
if (!pointer || !isSchema) continue;
|
|
257
257
|
const members = typeMembers(statement);
|
|
258
258
|
if (members) addMembers(members, pointer);
|
|
259
259
|
}
|
|
@@ -262,14 +262,12 @@ function createMappings(text, locate, targets) {
|
|
|
262
262
|
//#endregion
|
|
263
263
|
//#region src/transform.ts
|
|
264
264
|
/**
|
|
265
|
-
* Generates the
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
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.
|
|
265
|
+
* Generates the module for one spec with `generateModule` from `unplugin-kubb`, the same one a
|
|
266
|
+
* bundler loads. Without a config, only `@kubb/plugin-ts` runs. The spec text comes from the
|
|
267
|
+
* request, so unsaved edits are checked too. It is parsed once and shared by the build, the
|
|
268
|
+
* diagnostics and the mappings.
|
|
271
269
|
*/
|
|
272
|
-
async function transform({ fileName, content },
|
|
270
|
+
async function transform({ fileName, content }, config) {
|
|
273
271
|
const document = parseDocument(content);
|
|
274
272
|
if (document.errors.length) return {
|
|
275
273
|
text: "export {}",
|
|
@@ -280,42 +278,31 @@ async function transform({ fileName, content }, { arrayType } = {}) {
|
|
|
280
278
|
length: error.pos[1] - error.pos[0]
|
|
281
279
|
}))
|
|
282
280
|
};
|
|
283
|
-
const
|
|
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
|
-
});
|
|
281
|
+
const hooks = new Hookable();
|
|
300
282
|
const targets = {
|
|
301
283
|
schemas: /* @__PURE__ */ new Map(),
|
|
302
284
|
operations: /* @__PURE__ */ new Map()
|
|
303
285
|
};
|
|
304
|
-
|
|
286
|
+
hooks.hook("kubb:generate:schema", (node, { resolver }) => {
|
|
305
287
|
if (node.name) targets.schemas.set(resolver.name(node.name), node.name);
|
|
306
288
|
});
|
|
307
|
-
|
|
289
|
+
hooks.hook("kubb:generate:operation", (node, { resolver }) => {
|
|
308
290
|
if ("path" in node && node.path && node.method) targets.operations.set(resolver.name(node.operationId), {
|
|
309
291
|
path: node.path,
|
|
310
292
|
method: node.method
|
|
311
293
|
});
|
|
312
294
|
});
|
|
313
|
-
const {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
295
|
+
const { text, errors } = await generateModule({
|
|
296
|
+
root: dirname(fileName),
|
|
297
|
+
input: document.toJS(),
|
|
298
|
+
config: config ?? {
|
|
299
|
+
output: { path: "." },
|
|
300
|
+
plugins: [pluginTs()]
|
|
301
|
+
},
|
|
302
|
+
hooks
|
|
303
|
+
});
|
|
317
304
|
const locate = createLocator(document);
|
|
318
|
-
if (errors.length
|
|
305
|
+
if (errors.length) return {
|
|
319
306
|
text: "export {}",
|
|
320
307
|
extension: ".ts",
|
|
321
308
|
diagnostics: errors.map((error) => {
|
|
@@ -327,10 +314,19 @@ async function transform({ fileName, content }, { arrayType } = {}) {
|
|
|
327
314
|
};
|
|
328
315
|
})
|
|
329
316
|
};
|
|
317
|
+
if (config && !text) return {
|
|
318
|
+
text: "export {}",
|
|
319
|
+
extension: ".ts",
|
|
320
|
+
diagnostics: [{
|
|
321
|
+
messageText: "kubb.config.ts generated no code for this spec. Add a plugin such as pluginTs().",
|
|
322
|
+
start: 0,
|
|
323
|
+
length: 0
|
|
324
|
+
}]
|
|
325
|
+
};
|
|
330
326
|
return {
|
|
331
327
|
text,
|
|
332
328
|
extension: ".ts",
|
|
333
|
-
mappings: createMappings(text, (pointer) => locate({ pointer }), targets)
|
|
329
|
+
mappings: createMappings(text, content, (pointer) => locate({ pointer }), targets)
|
|
334
330
|
};
|
|
335
331
|
}
|
|
336
332
|
//#endregion
|
|
@@ -345,16 +341,36 @@ const handlers = {
|
|
|
345
341
|
positionEncoding: "utf-16",
|
|
346
342
|
diagnosticSource: "kubb"
|
|
347
343
|
}),
|
|
348
|
-
openProject: ({ projectHandle, options }) => {
|
|
349
|
-
const
|
|
350
|
-
projects.set(projectHandle,
|
|
351
|
-
|
|
344
|
+
openProject: async ({ projectHandle, configFileName, options }) => {
|
|
345
|
+
const loading = loadProjectConfig(configFileName ? dirname(configFileName) : process.cwd());
|
|
346
|
+
projects.set(projectHandle, loading);
|
|
347
|
+
const project = await loading;
|
|
348
|
+
return {
|
|
349
|
+
configIdentity: project.identity,
|
|
350
|
+
watchedFiles: project.watchedFiles,
|
|
351
|
+
...options != null && { optionDiagnostics: [{
|
|
352
|
+
path: [],
|
|
353
|
+
messageText: "openapi-import has no options. Set plugin options in kubb.config.ts."
|
|
354
|
+
}] }
|
|
355
|
+
};
|
|
352
356
|
},
|
|
353
357
|
closeProject: ({ projectHandle }) => {
|
|
354
358
|
projects.delete(projectHandle);
|
|
355
359
|
return null;
|
|
356
360
|
},
|
|
357
|
-
transform: (params) =>
|
|
361
|
+
transform: async (params) => {
|
|
362
|
+
const project = await projects.get(params.projectHandle);
|
|
363
|
+
if (project?.error) return {
|
|
364
|
+
text: "export {}",
|
|
365
|
+
extension: ".ts",
|
|
366
|
+
diagnostics: [{
|
|
367
|
+
messageText: project.error,
|
|
368
|
+
start: 0,
|
|
369
|
+
length: 0
|
|
370
|
+
}]
|
|
371
|
+
};
|
|
372
|
+
return cachedTransform(params, project && selectConfig(project.configs, params.fileName, project.dir));
|
|
373
|
+
}
|
|
358
374
|
};
|
|
359
375
|
async function handle({ id, method = "", params }) {
|
|
360
376
|
const handler = handlers[method];
|
package/dist/server.js.map
CHANGED
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"server.js","names":[],"sources":["../src/cache.ts","../src/config.ts","../src/rpc.ts","../src/locate.ts","../src/mappings.ts","../src/transform.ts","../src/server.ts"],"sourcesContent":["import type { UserConfig } from 'kubb'\nimport type { TransformParams } from './transform.ts'\n\n/**\n * Wraps a transform so a repeated request for the same file, content and config 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, config?: UserConfig) => Promise<TResult>,\n): (params: TransformParams, config?: UserConfig) => Promise<TResult> {\n const results = new Map<string, { content: string; config?: UserConfig; result: Promise<TResult> }>()\n\n return (params, config) => {\n const cached = results.get(params.fileName)\n // A reloaded config is a new object, so comparing by reference catches every config change.\n if (cached && cached.content === params.content && cached.config === config) return cached.result\n\n const result = transform(params, config)\n results.set(params.fileName, { content: params.content, config, result })\n result.catch(() => results.delete(params.fileName))\n return result\n }\n}\n","import { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { UserConfig } from 'kubb'\nimport { configFileCandidates, findConfigFile, loadConfigFile } from 'unplugin-kubb'\n\n/**\n * A Kubb config found for a TypeScript project, with what TypeScript needs to reload it.\n */\nexport type ProjectConfig = {\n /**\n * The project folder. Kubb resolves a config's `root` and `input` from here.\n */\n dir: string\n /**\n * The configs the file exports, empty when there is no config file.\n */\n configs: Array<UserConfig>\n /**\n * The config file, plus every file the CLI would pick up in `dir`, so adding one reloads too.\n */\n watchedFiles: Array<string>\n /**\n * Changes when the config file changes, so TypeScript transforms its specs again.\n */\n identity: string\n /**\n * Why the config file failed to load. Each transform reports it on the spec.\n */\n error?: string\n}\n\n/**\n * Finds the Kubb config the way the Kubb CLI does, from `dir` up, and loads it. A config that\n * exports a function is called with no CLI options.\n */\nexport async function loadProjectConfig(dir: string): Promise<ProjectConfig> {\n dir = resolve(dir)\n const file = findConfigFile(dir)\n const watchedFiles = [...new Set([...(file ? [file] : []), ...configFileCandidates(dir)])]\n if (!file) return { dir, configs: [], watchedFiles, identity: 'none' }\n\n const identity = createHash('sha256').update(readFileSync(file)).digest('hex')\n try {\n return { dir, configs: await loadConfigFile<UserConfig>(file, {}), watchedFiles, identity }\n } catch (error) {\n return { dir, configs: [], watchedFiles, identity, error: `${file} failed to load: ${error instanceof Error ? error.message : String(error)}` }\n }\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/**\n * Walks a JSON pointer through maps and sequences; the range is the last key or item it reached.\n */\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/**\n * The first `$ref` whose value is `ref`.\n */\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 kindVerbatim = 0\nconst kindAlias = 2\n// Hover, Definition, TypeDefinition, Implementation, References, DocumentHighlights.\nconst features = 1 | 8 | 16 | 32 | 64 | 128\n// Only schema names rename into the spec. A stale `$ref` shows as an error, but a stale `required` entry fails silently.\nconst renameFeature = 256\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/**\n * The object literal a property type describes, looking through `T[]` and `Array<T>`.\n */\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/**\n * The members of an interface, or of a type alias for an object literal.\n */\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 * Links generated names to the spec keys they came from: schemas and their (nested) properties,\n * and operation types to the operation, parameters, request body or response. A schema type named\n * exactly like its key is verbatim, so a rename in TypeScript renames the key.\n */\nexport function createMappings(text: string, content: 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, rename: boolean, ...pointers: Array<string>) => {\n const range = pointers.map(locate).find(Boolean)\n if (!range) return\n const verbatim = rename && content.slice(range.start, range.end) === name.getText(sourceFile)\n segments.push([\n name.getStart(sourceFile),\n name.getWidth(sourceFile),\n range.start,\n range.end - range.start,\n verbatim ? kindVerbatim : kindAlias,\n verbatim ? features | renameFeature : features,\n ])\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, false, 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, false, ...declarationPointers(name, targets), ...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 const isSchema = targets.schemas.has(statement.name.text)\n add(statement.name, isSchema, ...pointers)\n\n // Property names only resolve under a schema, not under operation parameters or responses.\n const pointer = pointers[0]\n if (!pointer || !isSchema) 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 type { UserConfig } from 'kubb'\nimport { Hookable, type KubbHooks } from 'kubb/kit'\nimport { pluginTs } from '@kubb/plugin-ts'\nimport { generateModule } from 'unplugin-kubb'\nimport { parseDocument } from 'yaml'\nimport { createLocator } from './locate.ts'\nimport { createMappings, type Segment, type Targets } from './mappings.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 * The module TypeScript checks in place of the spec, and the segments linking it 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 module for one spec with `generateModule` from `unplugin-kubb`, the same one a\n * bundler loads. Without a config, only `@kubb/plugin-ts` runs. The spec text comes from the\n * request, so unsaved edits are checked too. It is parsed once and shared by the build, the\n * diagnostics and the mappings.\n */\nexport async function transform({ fileName, content }: TransformParams, config?: UserConfig): 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 hooks = new Hookable<KubbHooks>()\n const targets: Targets = { schemas: new Map(), operations: new Map() }\n hooks.hook('kubb:generate:schema', (node, { resolver }) => {\n if (node.name) targets.schemas.set(resolver.name(node.name), node.name)\n })\n 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 { text, errors } = await generateModule({\n root: dirname(fileName),\n input: document.toJS(),\n config: config ?? { output: { path: '.' }, plugins: [pluginTs()] },\n hooks,\n })\n\n const locate = createLocator(document)\n\n if (errors.length) {\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 if (config && !text) {\n return {\n text: 'export {}',\n extension: '.ts',\n diagnostics: [{ messageText: 'kubb.config.ts generated no code for this spec. Add a plugin such as pluginTs().', start: 0, length: 0 }],\n }\n }\n\n return { text, extension: '.ts', mappings: createMappings(text, content, (pointer) => locate({ pointer }), targets) }\n}\n","import { dirname } from 'node:path'\nimport { selectConfig } from 'unplugin-kubb'\nimport { cacheTransform } from './cache.ts'\nimport { loadProjectConfig, type ProjectConfig } from './config.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\n// The load promise is stored right away, so a transform sent before the load finishes waits for it.\nconst projects = new Map<string, Promise<ProjectConfig>>()\n\nconst cachedTransform = cacheTransform(transform)\n\nconst handlers: Record<string, (params: never) => unknown> = {\n initialize: () => ({ protocolVersion: 1, positionEncoding: 'utf-16', diagnosticSource: 'kubb' }),\n // `dynamicConfig` in package.json: TypeScript watches `watchedFiles` and opens the project again\n // when one changes, then transforms its specs again when `configIdentity` differs.\n openProject: async ({ projectHandle, configFileName, options }: { projectHandle: string; configFileName?: string; options?: unknown }) => {\n const loading = loadProjectConfig(configFileName ? dirname(configFileName) : process.cwd())\n projects.set(projectHandle, loading)\n const project = await loading\n\n return {\n configIdentity: project.identity,\n watchedFiles: project.watchedFiles,\n ...(options != null && { optionDiagnostics: [{ path: [], messageText: 'openapi-import has no options. Set plugin options in kubb.config.ts.' }] }),\n }\n },\n closeProject: ({ projectHandle }: { projectHandle: string }) => {\n projects.delete(projectHandle)\n return null\n },\n transform: async (params: TransformParams & { projectHandle: string }) => {\n const project = await projects.get(params.projectHandle)\n if (project?.error) return { text: 'export {}', extension: '.ts', diagnostics: [{ messageText: project.error, start: 0, length: 0 }] }\n\n return cachedTransform(params, project && selectConfig(project.configs, params.fileName, project.dir))\n },\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,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-import",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"description": "Import OpenAPI specs in TypeScript with types from Kubb, through TypeScript 7.1 content mappers. No generated files.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"code-generation",
|
|
@@ -48,44 +48,31 @@
|
|
|
48
48
|
"access": "public",
|
|
49
49
|
"registry": "https://registry.npmjs.org/"
|
|
50
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
51
|
"dependencies": {
|
|
65
|
-
"@kubb/adapter-oas": "^5.12.5",
|
|
66
|
-
"@kubb/core": "^5.12.5",
|
|
67
|
-
"@kubb/parser-ts": "^5.12.5",
|
|
68
52
|
"@kubb/plugin-ts": "^5.0.14",
|
|
69
53
|
"@typescript/typescript6": "^6.0.2",
|
|
54
|
+
"unplugin-kubb": "^5.12.6",
|
|
70
55
|
"yaml": "^2.9.1"
|
|
71
56
|
},
|
|
72
57
|
"devDependencies": {
|
|
73
58
|
"@changesets/changelog-github": "^1.0.1",
|
|
74
59
|
"@changesets/cli": "^3.0.3",
|
|
60
|
+
"@kubb/plugin-zod": "^5.4.12",
|
|
75
61
|
"@types/node": "22.20.2",
|
|
76
62
|
"@vitest/coverage-v8": "^5.0.5",
|
|
77
|
-
"kubb": "^5.12.
|
|
63
|
+
"kubb": "^5.12.6",
|
|
78
64
|
"oxfmt": "^0.72.0",
|
|
79
65
|
"oxlint": "^1.88.0",
|
|
80
66
|
"tsdown": "^0.23.1",
|
|
81
|
-
"typescript": "
|
|
67
|
+
"typescript": "7.1.0-beta",
|
|
82
68
|
"vitest": "^5.0.5"
|
|
83
69
|
},
|
|
84
70
|
"peerDependencies": {
|
|
85
|
-
"kubb": "^5.12.
|
|
71
|
+
"kubb": "^5.12.6"
|
|
86
72
|
},
|
|
87
73
|
"typescript": {
|
|
88
74
|
"contentMapper": {
|
|
75
|
+
"dynamicConfig": true,
|
|
89
76
|
"exec": [
|
|
90
77
|
"node",
|
|
91
78
|
"dist/server.js"
|
|
@@ -96,5 +83,17 @@
|
|
|
96
83
|
"node": ">=22.12",
|
|
97
84
|
"pnpm": ">=11.0.0"
|
|
98
85
|
},
|
|
99
|
-
"
|
|
100
|
-
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "tsdown",
|
|
88
|
+
"changeset": "changeset",
|
|
89
|
+
"clean": "node -e \"require('node:fs').rmSync('./dist', {recursive:true,force:true})\"",
|
|
90
|
+
"format": "oxfmt -c oxfmt.config.ts .",
|
|
91
|
+
"format:check": "oxfmt -c oxfmt.config.ts --check .",
|
|
92
|
+
"lint": "oxlint -c oxlint.config.ts .",
|
|
93
|
+
"lint:fix": "oxlint -c oxlint.config.ts --fix .",
|
|
94
|
+
"start": "tsdown --watch",
|
|
95
|
+
"test": "vitest run",
|
|
96
|
+
"typecheck": "tsc",
|
|
97
|
+
"typecheck:example": "pnpm --filter openapi-import-pet-store typecheck"
|
|
98
|
+
}
|
|
99
|
+
}
|