@ir-kit/spec-convert 0.2.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.md +21 -0
- package/README.md +63 -0
- package/dist/converters/openapi3-to-json-schema.d.ts +2 -0
- package/dist/converters/openapi3-to-json-schema.d.ts.map +1 -0
- package/dist/converters/openapi3-to-json-schema.js +16 -0
- package/dist/converters/openapi3-to-json-schema.js.map +1 -0
- package/dist/converters/openapi3-to-postman.d.ts +2 -0
- package/dist/converters/openapi3-to-postman.d.ts.map +1 -0
- package/dist/converters/openapi3-to-postman.js +22 -0
- package/dist/converters/openapi3-to-postman.js.map +1 -0
- package/dist/converters/openapi3-to-typespec.d.ts +2 -0
- package/dist/converters/openapi3-to-typespec.d.ts.map +1 -0
- package/dist/converters/openapi3-to-typespec.js +11 -0
- package/dist/converters/openapi3-to-typespec.js.map +1 -0
- package/dist/converters/postman-to-openapi3.d.ts +2 -0
- package/dist/converters/postman-to-openapi3.d.ts.map +1 -0
- package/dist/converters/postman-to-openapi3.js +21 -0
- package/dist/converters/postman-to-openapi3.js.map +1 -0
- package/dist/converters/proto-to-openapi3.d.ts +2 -0
- package/dist/converters/proto-to-openapi3.d.ts.map +1 -0
- package/dist/converters/proto-to-openapi3.js +148 -0
- package/dist/converters/proto-to-openapi3.js.map +1 -0
- package/dist/converters/typespec-to-json-schema.d.ts +2 -0
- package/dist/converters/typespec-to-json-schema.d.ts.map +1 -0
- package/dist/converters/typespec-to-json-schema.js +20 -0
- package/dist/converters/typespec-to-json-schema.js.map +1 -0
- package/dist/converters/typespec-to-openapi3.d.ts +2 -0
- package/dist/converters/typespec-to-openapi3.d.ts.map +1 -0
- package/dist/converters/typespec-to-openapi3.js +20 -0
- package/dist/converters/typespec-to-openapi3.js.map +1 -0
- package/dist/converters/typespec-to-proto.d.ts +2 -0
- package/dist/converters/typespec-to-proto.d.ts.map +1 -0
- package/dist/converters/typespec-to-proto.js +20 -0
- package/dist/converters/typespec-to-proto.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +15 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +43 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +86 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ahmed Rowaihi
|
|
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
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# `@ir-kit/spec-convert`
|
|
2
|
+
|
|
3
|
+
Convert between API specification formats — OpenAPI 3, AsyncAPI 3, TypeSpec, Protobuf, Postman, JSON Schema. Graph-routed dispatcher: registered `(from → to)` converters compose automatically, so any new edge unlocks every other format combinatorially.
|
|
4
|
+
|
|
5
|
+
Part of [ir-kit](https://github.com/ir-kit/ir-kit).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @ir-kit/spec-convert
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { convertSpec } from "@ir-kit/spec-convert";
|
|
17
|
+
|
|
18
|
+
const result = await convertSpec({
|
|
19
|
+
input: "./petstore.yaml",
|
|
20
|
+
to: "postman",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (result.output.kind === "document") {
|
|
24
|
+
console.log(result.output.document);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`convertSpec` auto-detects the source format from the file extension and content (override with `from`). When no direct `(from → to)` converter is registered, the dispatcher BFS-routes through intermediate formats — e.g. `proto → openapi3 → postman` works out of the box.
|
|
29
|
+
|
|
30
|
+
## Registered converters
|
|
31
|
+
|
|
32
|
+
| From | → | To |
|
|
33
|
+
| -------- | --- | ------------------------------ |
|
|
34
|
+
| openapi3 | → | json-schema, postman, typespec |
|
|
35
|
+
| postman | → | openapi3 |
|
|
36
|
+
| proto | → | openapi3 |
|
|
37
|
+
| typespec | → | openapi3, json-schema, proto |
|
|
38
|
+
|
|
39
|
+
Any combination not in this table is resolved automatically by chaining edges through the graph — e.g. `postman → typespec` runs `postman → openapi3 → typespec`.
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
| Export | Description |
|
|
44
|
+
| -------------------------------------------------- | ------------------------------------------------------------- |
|
|
45
|
+
| `convertSpec(opts)` | Detect format, dispatch (or chain), return the converted spec |
|
|
46
|
+
| `listConverters()` | Inspect every registered direct edge |
|
|
47
|
+
| `SpecFormat`, `ConvertOutput`, `ConvertSpecResult` | Public types |
|
|
48
|
+
|
|
49
|
+
`ConvertOutput` is a discriminated union over `{ kind: "document" \| "source" \| "files" }` — a parsed JS object for OpenAPI-family targets, a source string for TypeSpec / Protobuf, or a `{ path → content }` map for emitters that produce multi-file output.
|
|
50
|
+
|
|
51
|
+
## CLI
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
ir spec convert ./input.yaml --to openapi3
|
|
55
|
+
ir spec convert ./api.proto --to postman
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
See [`@ir-kit/cli`](../../cli) for full flags.
|
|
59
|
+
|
|
60
|
+
## Limitations
|
|
61
|
+
|
|
62
|
+
- `openapi3 → proto` (and any `→ proto` chain through TypeSpec) is currently unsupported: the protobuf emitter requires `@field` numbers and `@TypeSpec.Protobuf.package` decorators that don't survive the OpenAPI → TypeSpec hop. Direct `proto → openapi3` works.
|
|
63
|
+
- AsyncAPI 3 outputs are not yet registered — `asyncapi3` works as a load target via `@ir-kit/spec-loader`, but not yet as a convert target.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-json-schema.d.ts","sourceRoot":"","sources":["../../src/converters/openapi3-to-json-schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { registerConverter } from "../registry.js";
|
|
2
|
+
registerConverter({
|
|
3
|
+
from: "openapi3",
|
|
4
|
+
to: "json-schema",
|
|
5
|
+
handler: async (document) => {
|
|
6
|
+
const components = (document.components ?? {});
|
|
7
|
+
return {
|
|
8
|
+
kind: "document",
|
|
9
|
+
document: {
|
|
10
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
11
|
+
$defs: components.schemas ?? {},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=openapi3-to-json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-json-schema.js","sourceRoot":"","sources":["../../src/converters/openapi3-to-json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,aAAa;IACjB,OAAO,EAAE,KAAK,EAAE,QAAsB,EAA0B,EAAE;QAChE,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAE5C,CAAC;QACF,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE;gBACR,OAAO,EAAE,8CAA8C;gBACvD,KAAK,EAAE,UAAU,CAAC,OAAO,IAAI,EAAE;aAChC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-postman.d.ts","sourceRoot":"","sources":["../../src/converters/openapi3-to-postman.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Converter from "openapi-to-postmanv2";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "openapi3",
|
|
5
|
+
to: "postman",
|
|
6
|
+
handler: async (document) => {
|
|
7
|
+
const json = JSON.stringify(document);
|
|
8
|
+
const result = await new Promise((resolve, reject) => {
|
|
9
|
+
Converter.convert({ type: "string", data: json }, { folderStrategy: "Tags" }, (err, res) => {
|
|
10
|
+
if (err)
|
|
11
|
+
reject(new Error(err.message));
|
|
12
|
+
else
|
|
13
|
+
resolve(res);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
if (!result.result || !result.output?.[0]?.data) {
|
|
17
|
+
throw new Error(`openapi3→postman failed: ${result.reason ?? "no output produced"}`);
|
|
18
|
+
}
|
|
19
|
+
return { kind: "document", document: result.output[0].data };
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=openapi3-to-postman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-postman.js","sourceRoot":"","sources":["../../src/converters/openapi3-to-postman.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AASnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,KAAK,EAAE,QAAsB,EAA0B,EAAE;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAClE,SAAS,CAAC,OAAO,CACf,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,EAC9B,EAAE,cAAc,EAAE,MAAM,EAAE,EAC1B,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;gBACX,IAAI,GAAG;oBAAE,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;;oBACnC,OAAO,CAAC,GAAoB,CAAC,CAAC;YACrC,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,4BAA4B,MAAM,CAAC,MAAM,IAAI,oBAAoB,EAAE,CACpE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-typespec.d.ts","sourceRoot":"","sources":["../../src/converters/openapi3-to-typespec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { convertOpenAPI3Document } from "@typespec/openapi3";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "openapi3",
|
|
5
|
+
to: "typespec",
|
|
6
|
+
handler: async (document) => {
|
|
7
|
+
const source = await convertOpenAPI3Document(document);
|
|
8
|
+
return { kind: "source", source, ext: "tsp" };
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=openapi3-to-typespec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi3-to-typespec.js","sourceRoot":"","sources":["../../src/converters/openapi3-to-typespec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,KAAK,EAAE,QAAsB,EAA0B,EAAE;QAChE,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,QAAoE,CACrE,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postman-to-openapi3.d.ts","sourceRoot":"","sources":["../../src/converters/postman-to-openapi3.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import postmanToOpenAPI from "@readme/postman-to-openapi";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "postman",
|
|
5
|
+
to: "openapi3",
|
|
6
|
+
handler: async (document) => {
|
|
7
|
+
const path = typeof document.__path === "string" ? document.__path : undefined;
|
|
8
|
+
if (!path) {
|
|
9
|
+
throw new Error("postman→openapi3 requires a file path; pass the collection path as input");
|
|
10
|
+
}
|
|
11
|
+
const json = await postmanToOpenAPI(path, undefined, {
|
|
12
|
+
defaultTag: "General",
|
|
13
|
+
outputFormat: "json",
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
kind: "document",
|
|
17
|
+
document: JSON.parse(json),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=postman-to-openapi3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postman-to-openapi3.js","sourceRoot":"","sources":["../../src/converters/postman-to-openapi3.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,SAAS;IACf,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,KAAK,EAAE,QAAsB,EAA0B,EAAE;QAChE,MAAM,IAAI,GACR,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE;YACnD,UAAU,EAAE,SAAS;YACrB,YAAY,EAAE,MAAM;SACrB,CAAC,CAAC;QACH,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB;SAC3C,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proto-to-openapi3.d.ts","sourceRoot":"","sources":["../../src/converters/proto-to-openapi3.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import protobuf from "protobufjs";
|
|
3
|
+
import { registerConverter } from "../registry.js";
|
|
4
|
+
registerConverter({
|
|
5
|
+
from: "proto",
|
|
6
|
+
to: "openapi3",
|
|
7
|
+
handler: async (document) => {
|
|
8
|
+
const path = typeof document.__path === "string" ? document.__path : undefined;
|
|
9
|
+
const source = typeof document.__source === "string" ? document.__source : undefined;
|
|
10
|
+
if (!path && !source) {
|
|
11
|
+
throw new Error("proto→openapi3 requires a `__path` or `__source` marker on the input document");
|
|
12
|
+
}
|
|
13
|
+
const text = source ?? (await readFile(path, "utf8"));
|
|
14
|
+
const root = new protobuf.Root();
|
|
15
|
+
const parsed = protobuf.parse(text, root, { keepCase: true });
|
|
16
|
+
const pkg = parsed.package ?? "default";
|
|
17
|
+
const schemas = {};
|
|
18
|
+
const paths = {};
|
|
19
|
+
walkNamespace(root, schemas, paths);
|
|
20
|
+
return {
|
|
21
|
+
kind: "document",
|
|
22
|
+
document: {
|
|
23
|
+
openapi: "3.1.0",
|
|
24
|
+
info: { title: pkg, version: "0.0.0" },
|
|
25
|
+
paths,
|
|
26
|
+
components: { schemas },
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
function walkNamespace(ns, schemas, paths) {
|
|
32
|
+
if (!ns.nested)
|
|
33
|
+
return;
|
|
34
|
+
for (const child of Object.values(ns.nested)) {
|
|
35
|
+
if (child instanceof protobuf.Type) {
|
|
36
|
+
schemas[child.fullName.replace(/^\./, "")] = messageToSchema(child);
|
|
37
|
+
walkNamespace(child, schemas, paths);
|
|
38
|
+
}
|
|
39
|
+
else if (child instanceof protobuf.Enum) {
|
|
40
|
+
schemas[child.fullName.replace(/^\./, "")] = enumToSchema(child);
|
|
41
|
+
}
|
|
42
|
+
else if (child instanceof protobuf.Service) {
|
|
43
|
+
addServicePaths(child, paths);
|
|
44
|
+
}
|
|
45
|
+
else if (child instanceof protobuf.Namespace) {
|
|
46
|
+
walkNamespace(child, schemas, paths);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function messageToSchema(type) {
|
|
51
|
+
const properties = {};
|
|
52
|
+
const required = [];
|
|
53
|
+
for (const field of type.fieldsArray) {
|
|
54
|
+
properties[field.name] = fieldToSchema(field);
|
|
55
|
+
if (field.required)
|
|
56
|
+
required.push(field.name);
|
|
57
|
+
}
|
|
58
|
+
const schema = {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties,
|
|
61
|
+
};
|
|
62
|
+
if (required.length > 0)
|
|
63
|
+
schema.required = required;
|
|
64
|
+
if (type.comment)
|
|
65
|
+
schema.description = type.comment;
|
|
66
|
+
return schema;
|
|
67
|
+
}
|
|
68
|
+
function enumToSchema(enm) {
|
|
69
|
+
const values = Object.keys(enm.values);
|
|
70
|
+
return {
|
|
71
|
+
type: "string",
|
|
72
|
+
enum: values,
|
|
73
|
+
...(enm.comment ? { description: enm.comment } : {}),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function fieldToSchema(field) {
|
|
77
|
+
const base = primitiveOrRef(field);
|
|
78
|
+
const schema = field.repeated
|
|
79
|
+
? { type: "array", items: base }
|
|
80
|
+
: base;
|
|
81
|
+
if (field.comment)
|
|
82
|
+
schema.description = field.comment;
|
|
83
|
+
return schema;
|
|
84
|
+
}
|
|
85
|
+
function primitiveOrRef(field) {
|
|
86
|
+
switch (field.type) {
|
|
87
|
+
case "double":
|
|
88
|
+
case "float":
|
|
89
|
+
return { type: "number", format: field.type };
|
|
90
|
+
case "int32":
|
|
91
|
+
case "uint32":
|
|
92
|
+
case "sint32":
|
|
93
|
+
case "fixed32":
|
|
94
|
+
case "sfixed32":
|
|
95
|
+
return { type: "integer", format: "int32" };
|
|
96
|
+
case "int64":
|
|
97
|
+
case "uint64":
|
|
98
|
+
case "sint64":
|
|
99
|
+
case "fixed64":
|
|
100
|
+
case "sfixed64":
|
|
101
|
+
return { type: "string", format: "int64" };
|
|
102
|
+
case "bool":
|
|
103
|
+
return { type: "boolean" };
|
|
104
|
+
case "string":
|
|
105
|
+
return { type: "string" };
|
|
106
|
+
case "bytes":
|
|
107
|
+
return { type: "string", format: "byte" };
|
|
108
|
+
default: {
|
|
109
|
+
const ref = field.resolvedType?.fullName ?? field.type;
|
|
110
|
+
return { $ref: `#/components/schemas/${ref.replace(/^\./, "")}` };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function addServicePaths(svc, paths) {
|
|
115
|
+
const serviceName = svc.fullName.replace(/^\./, "");
|
|
116
|
+
for (const method of svc.methodsArray) {
|
|
117
|
+
const url = `/${serviceName.replace(/\./g, "/")}/${method.name}`;
|
|
118
|
+
paths[url] = {
|
|
119
|
+
post: {
|
|
120
|
+
operationId: `${serviceName}_${method.name}`,
|
|
121
|
+
...(method.comment ? { description: method.comment } : {}),
|
|
122
|
+
requestBody: {
|
|
123
|
+
required: true,
|
|
124
|
+
content: {
|
|
125
|
+
"application/json": {
|
|
126
|
+
schema: {
|
|
127
|
+
$ref: `#/components/schemas/${method.resolvedRequestType?.fullName.replace(/^\./, "") ?? method.requestType}`,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
responses: {
|
|
133
|
+
"200": {
|
|
134
|
+
description: "OK",
|
|
135
|
+
content: {
|
|
136
|
+
"application/json": {
|
|
137
|
+
schema: {
|
|
138
|
+
$ref: `#/components/schemas/${method.resolvedResponseType?.fullName.replace(/^\./, "") ?? method.responseType}`,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=proto-to-openapi3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proto-to-openapi3.js","sourceRoot":"","sources":["../../src/converters/proto-to-openapi3.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-json-schema.d.ts","sourceRoot":"","sources":["../../src/converters/typespec-to-json-schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { compileTypespecCapture } from "@ir-kit/typespec-loader";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "typespec",
|
|
5
|
+
to: "json-schema",
|
|
6
|
+
handler: async (document, options) => {
|
|
7
|
+
const path = typeof document.__path === "string" ? document.__path : undefined;
|
|
8
|
+
const source = typeof document.__source === "string" ? document.__source : undefined;
|
|
9
|
+
if (!path && !source) {
|
|
10
|
+
throw new Error("typespec→json-schema requires a `__path` or `__source` marker on the input document");
|
|
11
|
+
}
|
|
12
|
+
const { files } = await compileTypespecCapture(path ? { path } : { source: source }, {
|
|
13
|
+
cwd: options.cwd,
|
|
14
|
+
emitter: "@typespec/json-schema",
|
|
15
|
+
emitterOptions: options.upstream,
|
|
16
|
+
});
|
|
17
|
+
return { kind: "files", files };
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=typespec-to-json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-json-schema.js","sourceRoot":"","sources":["../../src/converters/typespec-to-json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,aAAa;IACjB,OAAO,EAAE,KAAK,EAAE,QAAsB,EAAE,OAAO,EAA0B,EAAE;QACzE,MAAM,IAAI,GACR,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,MAAM,MAAM,GACV,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,CAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAgB,EAAE,EAC9C;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,uBAAuB;YAChC,cAAc,EAAE,OAAO,CAAC,QAAQ;SACjC,CACF,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-openapi3.d.ts","sourceRoot":"","sources":["../../src/converters/typespec-to-openapi3.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { compileTypespec } from "@ir-kit/typespec-loader";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "typespec",
|
|
5
|
+
to: "openapi3",
|
|
6
|
+
handler: async (document, options) => {
|
|
7
|
+
const path = typeof document.__path === "string" ? document.__path : undefined;
|
|
8
|
+
const source = typeof document.__source === "string" ? document.__source : undefined;
|
|
9
|
+
if (path) {
|
|
10
|
+
const { document: out } = await compileTypespec({ path }, { cwd: options.cwd, openapi: options.upstream });
|
|
11
|
+
return { kind: "document", document: out };
|
|
12
|
+
}
|
|
13
|
+
if (source) {
|
|
14
|
+
const { document: out } = await compileTypespec({ source }, { cwd: options.cwd, openapi: options.upstream });
|
|
15
|
+
return { kind: "document", document: out };
|
|
16
|
+
}
|
|
17
|
+
throw new Error("typespec→openapi3 requires a `__path` or `__source` marker on the input document");
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=typespec-to-openapi3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-openapi3.js","sourceRoot":"","sources":["../../src/converters/typespec-to-openapi3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,KAAK,EAAE,QAAsB,EAAE,OAAO,EAA0B,EAAE;QACzE,MAAM,IAAI,GACR,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,MAAM,MAAM,GACV,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,MAAM,eAAe,CAC7C,EAAE,IAAI,EAAE,EACR,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,CAChD,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAA8B,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,MAAM,eAAe,CAC7C,EAAE,MAAM,EAAE,EACV,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,CAChD,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAA8B,EAAE,CAAC;QACxE,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-proto.d.ts","sourceRoot":"","sources":["../../src/converters/typespec-to-proto.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { compileTypespecCapture } from "@ir-kit/typespec-loader";
|
|
2
|
+
import { registerConverter } from "../registry.js";
|
|
3
|
+
registerConverter({
|
|
4
|
+
from: "typespec",
|
|
5
|
+
to: "proto",
|
|
6
|
+
handler: async (document, options) => {
|
|
7
|
+
const path = typeof document.__path === "string" ? document.__path : undefined;
|
|
8
|
+
const source = typeof document.__source === "string" ? document.__source : undefined;
|
|
9
|
+
if (!path && !source) {
|
|
10
|
+
throw new Error("typespec→proto requires a `__path` or `__source` marker on the input document");
|
|
11
|
+
}
|
|
12
|
+
const { files } = await compileTypespecCapture(path ? { path } : { source: source }, {
|
|
13
|
+
cwd: options.cwd,
|
|
14
|
+
emitter: "@typespec/protobuf",
|
|
15
|
+
emitterOptions: options.upstream,
|
|
16
|
+
});
|
|
17
|
+
return { kind: "files", files };
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=typespec-to-proto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typespec-to-proto.js","sourceRoot":"","sources":["../../src/converters/typespec-to-proto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,iBAAiB,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,EAAE,EAAE,OAAO;IACX,OAAO,EAAE,KAAK,EAAE,QAAsB,EAAE,OAAO,EAA0B,EAAE;QACzE,MAAM,IAAI,GACR,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,MAAM,MAAM,GACV,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,CAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAgB,EAAE,EAC9C;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,oBAAoB;YAC7B,cAAc,EAAE,OAAO,CAAC,QAAQ;SACjC,CACF,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;CACF,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import "./converters/openapi3-to-json-schema.js";
|
|
2
|
+
import "./converters/openapi3-to-postman.js";
|
|
3
|
+
import "./converters/openapi3-to-typespec.js";
|
|
4
|
+
import "./converters/postman-to-openapi3.js";
|
|
5
|
+
import "./converters/proto-to-openapi3.js";
|
|
6
|
+
import "./converters/typespec-to-json-schema.js";
|
|
7
|
+
import "./converters/typespec-to-openapi3.js";
|
|
8
|
+
import "./converters/typespec-to-proto.js";
|
|
9
|
+
import { listConverters } from "./registry.js";
|
|
10
|
+
import type { ConvertHandlerOptions, ConvertOutput, SpecDocument, SpecFormat } from "./types.js";
|
|
11
|
+
export type { ConvertHandlerOptions, ConvertOutput, SpecDocument, SpecFormat };
|
|
12
|
+
export { listConverters };
|
|
13
|
+
export type ConvertSpecInput = string | SpecDocument;
|
|
14
|
+
export interface ConvertSpecOptions {
|
|
15
|
+
input: ConvertSpecInput;
|
|
16
|
+
to: SpecFormat;
|
|
17
|
+
from?: SpecFormat;
|
|
18
|
+
cwd?: string;
|
|
19
|
+
upstream?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export interface ConvertSpecResult {
|
|
22
|
+
from: SpecFormat;
|
|
23
|
+
to: SpecFormat;
|
|
24
|
+
output: ConvertOutput;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Convert between API spec formats. Detects the input format via
|
|
28
|
+
* `@ir-kit/spec-loader` (override with `from`). Uses a direct
|
|
29
|
+
* `(from → to)` converter when one is registered; otherwise BFS-routes
|
|
30
|
+
* through intermediate formats (chains like `proto → openapi3 → postman`
|
|
31
|
+
* are discovered automatically). Returns either a parsed document, a
|
|
32
|
+
* source string, or a multi-file map depending on the target.
|
|
33
|
+
*/
|
|
34
|
+
export declare function convertSpec(opts: ConvertSpecOptions): Promise<ConvertSpecResult>;
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,yCAAyC,CAAC;AACjD,OAAO,qCAAqC,CAAC;AAC7C,OAAO,sCAAsC,CAAC;AAC9C,OAAO,qCAAqC,CAAC;AAC7C,OAAO,mCAAmC,CAAC;AAC3C,OAAO,yCAAyC,CAAC;AACjD,OAAO,sCAAsC,CAAC;AAC9C,OAAO,mCAAmC,CAAC;AAE3C,OAAO,EAGL,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,gBAAgB,CAAC;IACxB,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,UAAU,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAoD5B"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, extname, join, resolve } from "node:path";
|
|
4
|
+
import { loadSpec } from "@ir-kit/spec-loader";
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
/** typespec-loader's package dir hosts the @typespec/* peer deps the
|
|
7
|
+
* TypeSpec compiler needs to resolve when chaining converters. */
|
|
8
|
+
const typespecLoaderDir = dirname(require.resolve("@ir-kit/typespec-loader/package.json"));
|
|
9
|
+
import "./converters/openapi3-to-json-schema.js";
|
|
10
|
+
import "./converters/openapi3-to-postman.js";
|
|
11
|
+
import "./converters/openapi3-to-typespec.js";
|
|
12
|
+
import "./converters/postman-to-openapi3.js";
|
|
13
|
+
import "./converters/proto-to-openapi3.js";
|
|
14
|
+
import "./converters/typespec-to-json-schema.js";
|
|
15
|
+
import "./converters/typespec-to-openapi3.js";
|
|
16
|
+
import "./converters/typespec-to-proto.js";
|
|
17
|
+
import { findConverter, findConverterPath, listConverters, } from "./registry.js";
|
|
18
|
+
export { listConverters };
|
|
19
|
+
/**
|
|
20
|
+
* Convert between API spec formats. Detects the input format via
|
|
21
|
+
* `@ir-kit/spec-loader` (override with `from`). Uses a direct
|
|
22
|
+
* `(from → to)` converter when one is registered; otherwise BFS-routes
|
|
23
|
+
* through intermediate formats (chains like `proto → openapi3 → postman`
|
|
24
|
+
* are discovered automatically). Returns either a parsed document, a
|
|
25
|
+
* source string, or a multi-file map depending on the target.
|
|
26
|
+
*/
|
|
27
|
+
export async function convertSpec(opts) {
|
|
28
|
+
const from = opts.from ?? (await detectFormat(opts.input, opts.cwd));
|
|
29
|
+
if (from === opts.to) {
|
|
30
|
+
const document = await readAsDocument(opts.input, opts.cwd);
|
|
31
|
+
return { from, to: opts.to, output: { kind: "document", document } };
|
|
32
|
+
}
|
|
33
|
+
const direct = findConverter(from, opts.to);
|
|
34
|
+
const path = direct ? [direct] : findConverterPath(from, opts.to);
|
|
35
|
+
if (!path || path.length === 0) {
|
|
36
|
+
throw new Error(`No converter path from ${from} to ${opts.to}. ` +
|
|
37
|
+
`Available edges: ${listConverters()
|
|
38
|
+
.map((p) => `${p.from}→${p.to}`)
|
|
39
|
+
.join(", ") || "<none>"}`);
|
|
40
|
+
}
|
|
41
|
+
let document = await materializeInput(opts.input, from, opts.cwd);
|
|
42
|
+
let output;
|
|
43
|
+
let tempDir;
|
|
44
|
+
try {
|
|
45
|
+
for (let i = 0; i < path.length; i++) {
|
|
46
|
+
const edge = path[i];
|
|
47
|
+
output = await edge.handler(document, {
|
|
48
|
+
cwd: opts.cwd,
|
|
49
|
+
upstream: opts.upstream,
|
|
50
|
+
});
|
|
51
|
+
if (i < path.length - 1) {
|
|
52
|
+
if (output.kind === "document") {
|
|
53
|
+
document = output.document;
|
|
54
|
+
}
|
|
55
|
+
else if (output.kind === "source") {
|
|
56
|
+
tempDir ??= await mkdtemp(join(typespecLoaderDir, ".ir-spec-convert-"));
|
|
57
|
+
const tempPath = join(tempDir, `intermediate-${i}.${output.ext}`);
|
|
58
|
+
await writeFile(tempPath, output.source);
|
|
59
|
+
document = { __path: tempPath };
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error(`Cannot chain through ${edge.to}: intermediate output is '${output.kind}', cannot bridge to next converter`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
if (tempDir)
|
|
69
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
return { from, to: opts.to, output: output };
|
|
72
|
+
}
|
|
73
|
+
async function detectFormat(input, cwd) {
|
|
74
|
+
if (typeof input === "object") {
|
|
75
|
+
if (input.asyncapi !== undefined)
|
|
76
|
+
return "asyncapi3";
|
|
77
|
+
if (isPostmanCollection(input))
|
|
78
|
+
return "postman";
|
|
79
|
+
return "openapi3";
|
|
80
|
+
}
|
|
81
|
+
const ext = extname(input).toLowerCase();
|
|
82
|
+
if (ext === ".tsp")
|
|
83
|
+
return "typespec";
|
|
84
|
+
if (ext === ".proto")
|
|
85
|
+
return "proto";
|
|
86
|
+
if (input.toLowerCase().endsWith(".postman_collection.json"))
|
|
87
|
+
return "postman";
|
|
88
|
+
const result = await loadSpec({ input, cwd });
|
|
89
|
+
if (result.kind === "asyncapi")
|
|
90
|
+
return "asyncapi3";
|
|
91
|
+
if (result.kind === "openapi" &&
|
|
92
|
+
isPostmanCollection(result.document)) {
|
|
93
|
+
return "postman";
|
|
94
|
+
}
|
|
95
|
+
return "openapi3";
|
|
96
|
+
}
|
|
97
|
+
function isPostmanCollection(doc) {
|
|
98
|
+
const info = doc.info;
|
|
99
|
+
return (typeof info?.schema === "string" &&
|
|
100
|
+
info.schema.includes("schema.getpostman.com"));
|
|
101
|
+
}
|
|
102
|
+
async function materializeInput(input, from, cwd) {
|
|
103
|
+
if (from === "typespec" || from === "proto" || from === "postman") {
|
|
104
|
+
if (typeof input !== "string") {
|
|
105
|
+
throw new Error(`${from} input must be a file path`);
|
|
106
|
+
}
|
|
107
|
+
return { __path: resolve(cwd ?? process.cwd(), input) };
|
|
108
|
+
}
|
|
109
|
+
return readAsDocument(input, cwd);
|
|
110
|
+
}
|
|
111
|
+
async function readAsDocument(input, cwd) {
|
|
112
|
+
if (typeof input === "object")
|
|
113
|
+
return input;
|
|
114
|
+
const loaded = await loadSpec({ input, cwd });
|
|
115
|
+
if (loaded.kind === "asyncapi") {
|
|
116
|
+
return loaded.document.json();
|
|
117
|
+
}
|
|
118
|
+
return loaded.document;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConverterPair, SpecFormat } from "./types.js";
|
|
2
|
+
export declare function registerConverter(pair: ConverterPair): void;
|
|
3
|
+
export declare function findConverter(from: SpecFormat, to: SpecFormat): ConverterPair | undefined;
|
|
4
|
+
export declare function listConverters(): ReadonlyArray<{
|
|
5
|
+
from: SpecFormat;
|
|
6
|
+
to: SpecFormat;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* Shortest converter path from `from` to `to`, including direct pairs.
|
|
10
|
+
* BFS over the registered converter graph; returns `undefined` if no
|
|
11
|
+
* path exists. Chains let any new (X → openapi3, openapi3 → X) pair
|
|
12
|
+
* unlock conversions to every other registered format automatically.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findConverterPath(from: SpecFormat, to: SpecFormat): ConverterPair[] | undefined;
|
|
15
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM5D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAE3D;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,UAAU,GACb,aAAa,GAAG,SAAS,CAE3B;AAED,wBAAgB,cAAc,IAAI,aAAa,CAAC;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,UAAU,CAAC;CAChB,CAAC,CAED;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,UAAU,GACb,aAAa,EAAE,GAAG,SAAS,CAyB7B"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
const key = (from, to) => `${from}->${to}`;
|
|
3
|
+
export function registerConverter(pair) {
|
|
4
|
+
registry.set(key(pair.from, pair.to), pair);
|
|
5
|
+
}
|
|
6
|
+
export function findConverter(from, to) {
|
|
7
|
+
return registry.get(key(from, to));
|
|
8
|
+
}
|
|
9
|
+
export function listConverters() {
|
|
10
|
+
return Array.from(registry.values()).map(({ from, to }) => ({ from, to }));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Shortest converter path from `from` to `to`, including direct pairs.
|
|
14
|
+
* BFS over the registered converter graph; returns `undefined` if no
|
|
15
|
+
* path exists. Chains let any new (X → openapi3, openapi3 → X) pair
|
|
16
|
+
* unlock conversions to every other registered format automatically.
|
|
17
|
+
*/
|
|
18
|
+
export function findConverterPath(from, to) {
|
|
19
|
+
if (from === to)
|
|
20
|
+
return [];
|
|
21
|
+
const adjacency = new Map();
|
|
22
|
+
for (const pair of registry.values()) {
|
|
23
|
+
const edges = adjacency.get(pair.from) ?? [];
|
|
24
|
+
edges.push(pair);
|
|
25
|
+
adjacency.set(pair.from, edges);
|
|
26
|
+
}
|
|
27
|
+
const queue = [{ node: from, path: [] }];
|
|
28
|
+
const visited = new Set([from]);
|
|
29
|
+
while (queue.length > 0) {
|
|
30
|
+
const { node, path } = queue.shift();
|
|
31
|
+
for (const edge of adjacency.get(node) ?? []) {
|
|
32
|
+
if (visited.has(edge.to))
|
|
33
|
+
continue;
|
|
34
|
+
const next = [...path, edge];
|
|
35
|
+
if (edge.to === to)
|
|
36
|
+
return next;
|
|
37
|
+
visited.add(edge.to);
|
|
38
|
+
queue.push({ node: edge.to, path: next });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAElD,MAAM,GAAG,GAAG,CAAC,IAAgB,EAAE,EAAc,EAAU,EAAE,CAAC,GAAG,IAAI,KAAK,EAAE,EAAE,CAAC;AAE3E,MAAM,UAAU,iBAAiB,CAAC,IAAmB;IACnD,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,IAAgB,EAChB,EAAc;IAEd,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc;IAI5B,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAgB,EAChB,EAAc;IAEd,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,SAAS,GAAG,IAAI,GAAG,EAA+B,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAGD,MAAM,KAAK,GAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAE5C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YACnC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE;gBAAE,OAAO,IAAI,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type SpecFormat = "openapi3" | "asyncapi3" | "typespec" | "proto" | "postman" | "json-schema";
|
|
2
|
+
export type SpecDocument = Record<string, unknown>;
|
|
3
|
+
export type ConvertOutput = {
|
|
4
|
+
kind: "document";
|
|
5
|
+
document: SpecDocument;
|
|
6
|
+
} | {
|
|
7
|
+
kind: "source";
|
|
8
|
+
source: string;
|
|
9
|
+
ext: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "files";
|
|
12
|
+
files: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
export type ConvertHandler = (document: SpecDocument, options: ConvertHandlerOptions) => Promise<ConvertOutput>;
|
|
15
|
+
export interface ConvertHandlerOptions {
|
|
16
|
+
cwd?: string;
|
|
17
|
+
upstream?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface ConverterPair {
|
|
20
|
+
from: SpecFormat;
|
|
21
|
+
to: SpecFormat;
|
|
22
|
+
handler: ConvertHandler;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,WAAW,GACX,UAAU,GACV,OAAO,GACP,SAAS,GACT,aAAa,CAAC;AAElB,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAErD,MAAM,MAAM,cAAc,GAAG,CAC3B,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;CACzB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ir-kit/spec-convert",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Convert between API specification formats — OpenAPI 3, AsyncAPI 3, TypeSpec, Protobuf, JSON Schema. Pair-handler registry; programmatic API; thin wrappers around upstream conversion tools where available.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openapi",
|
|
7
|
+
"asyncapi",
|
|
8
|
+
"typespec",
|
|
9
|
+
"protobuf",
|
|
10
|
+
"json-schema",
|
|
11
|
+
"convert",
|
|
12
|
+
"spec",
|
|
13
|
+
"ir-kit"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/ir-kit/ir-kit/tree/main/packages/shared/spec-convert",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/ir-kit/ir-kit/issues"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Ahmed Rowaihi",
|
|
22
|
+
"email": "ahmedrowaihi@gmail.com"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/ir-kit/ir-kit.git",
|
|
27
|
+
"directory": "packages/shared/spec-convert"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE.md"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@readme/postman-to-openapi": "^4.1.0",
|
|
51
|
+
"openapi-to-postmanv2": "^6.0.1",
|
|
52
|
+
"protobufjs": "^7.4.0",
|
|
53
|
+
"@ir-kit/spec-loader": "0.2.0",
|
|
54
|
+
"@ir-kit/typespec-loader": "0.2.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@typespec/json-schema": ">=1.0.0",
|
|
58
|
+
"@typespec/openapi3": ">=1.0.0",
|
|
59
|
+
"@typespec/protobuf": ">=0.80.0"
|
|
60
|
+
},
|
|
61
|
+
"peerDependenciesMeta": {
|
|
62
|
+
"@typespec/json-schema": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"@typespec/protobuf": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/node": "^22",
|
|
71
|
+
"@typespec/json-schema": "^1.12.0",
|
|
72
|
+
"@typespec/openapi3": "^1.12.0",
|
|
73
|
+
"@typespec/protobuf": "^0.82.0",
|
|
74
|
+
"vitest": "^4.0.0",
|
|
75
|
+
"@ir-kit/tsconfig": "0.0.0"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=20.19.0"
|
|
79
|
+
},
|
|
80
|
+
"scripts": {
|
|
81
|
+
"build": "tsc -p tsconfig.build.json",
|
|
82
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
83
|
+
"typecheck": "tsc --noEmit",
|
|
84
|
+
"test": "vitest run --passWithNoTests"
|
|
85
|
+
}
|
|
86
|
+
}
|