@ir-kit/openapi-loader 0.2.0 → 0.4.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Load an OpenAPI 3.x spec from a file path, URL, or pre-parsed object. Bundles `$ref`s via `@hey-api/json-schema-ref-parser` and runs optional hey-api-aware normalization.
4
4
 
5
- Part of [ir-kit](https://github.com/ir-kit/ir-kit). For multi-format input (OpenAPI + AsyncAPI + TypeSpec under one API), reach for [`@ir-kit/spec-loader`](../../shared/spec-loader) instead.
5
+ Part of [ir-kit](https://github.com/ahmedrowaihi/ir-kit). For multi-format input (OpenAPI + AsyncAPI + TypeSpec under one API), reach for [`@ir-kit/spec-loader`](../../shared/spec-loader) instead.
6
6
 
7
7
  ## Install
8
8
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type NormalizeOptions } from "@ir-kit/openapi";
2
+ import { type Type } from "js-yaml";
2
3
  export type OpenAPIInput = string | Record<string, unknown>;
3
4
  export interface LoadOpenAPIOptions {
4
5
  input: OpenAPIInput;
@@ -7,6 +8,19 @@ export interface LoadOpenAPIOptions {
7
8
  * the safe preset; pass an object for custom rules. */
8
9
  normalize?: boolean | NormalizeOptions;
9
10
  }
11
+ /** Parse a spec file, URL or object into its raw root document without resolving refs. */
12
+ export declare function readSpecDocument(input: OpenAPIInput, cwd?: string): Promise<Record<string, unknown>>;
10
13
  export declare function loadOpenAPI(opts: LoadOpenAPIOptions): Promise<Record<string, unknown>>;
14
+ declare module "js-yaml" {
15
+ const types: {
16
+ merge: Type;
17
+ };
18
+ }
19
+ /**
20
+ * `x-` extensions are opaque to OpenAPI, so an external `$ref` inside one
21
+ * (Spotify's `x-spotify-policy: { $ref: ../policies.yaml }`) is data, not a
22
+ * dependency of the spec. Rename it to `x-$ref` so bundling never fetches it.
23
+ */
24
+ export declare function detachExtensionRefs(node: unknown, inExtension?: boolean): void;
11
25
  export declare function resolveOpenAPIInput(input: OpenAPIInput, cwd?: string): OpenAPIInput;
12
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;4DACwD;IACxD,SAAS,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACxC;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAalC;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,GAAG,GAAE,MAAsB,GAC1B,YAAY,CASd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAqB,KAAK,IAAI,EAAS,MAAM,SAAS,CAAC;AAE9D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;4DACwD;IACxD,SAAS,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACxC;AAED,0FAA0F;AAC1F,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,YAAY,EACnB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAKlC;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0BlC;AAED,OAAO,QAAQ,SAAS,CAAC;IAEvB,MAAM,KAAK,EAAE;QAAE,KAAK,EAAE,IAAI,CAAA;KAAE,CAAC;CAC9B;AA4CD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,UAAQ,GAAG,IAAI,CAuB5E;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,GAAG,GAAE,MAAsB,GAC1B,YAAY,CASd"}
package/dist/index.js CHANGED
@@ -1,15 +1,105 @@
1
1
  import { isAbsolute, resolve } from "node:path";
2
- import { $RefParser } from "@hey-api/json-schema-ref-parser";
3
- import { normalizeSpec, SAFE_NORMALIZE, } from "@ir-kit/openapi";
2
+ import { $RefParser, ParserError, } from "@hey-api/json-schema-ref-parser";
3
+ import { hoistForeignSchemaRefs, normalizeSpec, SAFE_NORMALIZE, } from "@ir-kit/openapi";
4
+ import { CORE_SCHEMA, load, types } from "js-yaml";
5
+ /** Parse a spec file, URL or object into its raw root document without resolving refs. */
6
+ export async function readSpecDocument(input, cwd) {
7
+ const { schema } = await createParser().parse({
8
+ pathOrUrlOrSchema: resolveOpenAPIInput(input, cwd),
9
+ });
10
+ return schema;
11
+ }
4
12
  export async function loadOpenAPI(opts) {
5
- const bundled = (await new $RefParser().bundle({
6
- pathOrUrlOrSchema: resolveOpenAPIInput(opts.input, opts.cwd),
13
+ const parser = createParser();
14
+ const input = resolveOpenAPIInput(opts.input, opts.cwd);
15
+ const { schema } = await parser.parse({ pathOrUrlOrSchema: input });
16
+ const root = parser.$refs._root$Ref;
17
+ detachExtensionRefs(schema);
18
+ const bundled = (await parser.bundle({
19
+ pathOrUrlOrSchema: input,
20
+ resolvedInput: {
21
+ path: root.path ?? "",
22
+ schema,
23
+ type: typeof input === "string" ? root.pathType : "json",
24
+ },
7
25
  }));
26
+ hoistForeignSchemaRefs(bundled);
8
27
  if (opts.normalize) {
9
28
  normalizeSpec(bundled, opts.normalize === true ? SAFE_NORMALIZE : opts.normalize);
10
29
  }
11
30
  return bundled;
12
31
  }
32
+ // why: js-yaml's default YAML 1.1 schema turns unquoted dates such as
33
+ // Stripe's `api_version` enum (`- 2011-01-01`) into `Date` objects, which
34
+ // codegen then drops; the YAML 1.2 core schema keeps them as strings.
35
+ // `<<` merge keys stay supported, as specs use them to share fields.
36
+ const YAML_SCHEMA = CORE_SCHEMA.extend({ implicit: [types.merge] });
37
+ function createParser() {
38
+ const parser = new $RefParser();
39
+ parser.options.parse.yaml.handler = (file) => {
40
+ const data = Buffer.isBuffer(file.data) ? file.data.toString() : file.data;
41
+ if (typeof data !== "string")
42
+ return data;
43
+ try {
44
+ return load(data, { schema: YAML_SCHEMA });
45
+ }
46
+ catch (error) {
47
+ throw new ParserError(error.message, file.url);
48
+ }
49
+ };
50
+ return parser;
51
+ }
52
+ /** Keys whose children are user-named entries, never `x-` extensions. */
53
+ const NAMED_ENTRY_MAPS = new Set([
54
+ "$defs",
55
+ "callbacks",
56
+ "content",
57
+ "definitions",
58
+ "encoding",
59
+ "examples",
60
+ "headers",
61
+ "links",
62
+ "mapping",
63
+ "parameters",
64
+ "pathItems",
65
+ "patternProperties",
66
+ "properties",
67
+ "requestBodies",
68
+ "responses",
69
+ "schemas",
70
+ "securitySchemes",
71
+ "variables",
72
+ ]);
73
+ /**
74
+ * `x-` extensions are opaque to OpenAPI, so an external `$ref` inside one
75
+ * (Spotify's `x-spotify-policy: { $ref: ../policies.yaml }`) is data, not a
76
+ * dependency of the spec. Rename it to `x-$ref` so bundling never fetches it.
77
+ */
78
+ export function detachExtensionRefs(node, inExtension = false) {
79
+ if (!node || typeof node !== "object")
80
+ return;
81
+ if (Array.isArray(node)) {
82
+ for (const item of node)
83
+ detachExtensionRefs(item, inExtension);
84
+ return;
85
+ }
86
+ const obj = node;
87
+ if (inExtension &&
88
+ typeof obj.$ref === "string" &&
89
+ !obj.$ref.startsWith("#")) {
90
+ obj["x-$ref"] = obj.$ref;
91
+ delete obj.$ref;
92
+ }
93
+ for (const [key, value] of Object.entries(obj)) {
94
+ if (NAMED_ENTRY_MAPS.has(key) && value && typeof value === "object") {
95
+ for (const entry of Object.values(value))
96
+ detachExtensionRefs(entry, inExtension);
97
+ }
98
+ else {
99
+ detachExtensionRefs(value, inExtension || key.startsWith("x-"));
100
+ }
101
+ }
102
+ }
13
103
  export function resolveOpenAPIInput(input, cwd = process.cwd()) {
14
104
  if (typeof input !== "string")
15
105
  return input;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAEL,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AAYzB,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAwB;IAExB,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC,MAAM,CAAC;QAC7C,iBAAiB,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC;KAC7D,CAAC,CAA4B,CAAC;IAE/B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,aAAa,CACX,OAAO,EACP,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAC1D,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAmB,EACnB,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,OAAO,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ir-kit/openapi-loader",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Load an OpenAPI 3.x spec from a file path, URL, or pre-parsed object. Bundles `$ref`s via `@hey-api/json-schema-ref-parser` and runs optional hey-api-aware normalization.",
5
5
  "keywords": [
6
6
  "openapi",
@@ -9,9 +9,9 @@
9
9
  "spec",
10
10
  "ir-kit"
11
11
  ],
12
- "homepage": "https://github.com/ir-kit/ir-kit/tree/main/packages/openapi/loader",
12
+ "homepage": "https://github.com/ahmedrowaihi/ir-kit/tree/main/packages/openapi/loader",
13
13
  "bugs": {
14
- "url": "https://github.com/ir-kit/ir-kit/issues"
14
+ "url": "https://github.com/ahmedrowaihi/ir-kit/issues"
15
15
  },
16
16
  "license": "MIT",
17
17
  "author": {
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/ir-kit/ir-kit.git",
23
+ "url": "git+https://github.com/ahmedrowaihi/ir-kit.git",
24
24
  "directory": "packages/openapi/loader"
25
25
  },
26
26
  "type": "module",
@@ -44,10 +44,12 @@
44
44
  "provenance": true
45
45
  },
46
46
  "dependencies": {
47
- "@hey-api/json-schema-ref-parser": "^1.4.1",
48
- "@ir-kit/openapi": "0.3.0"
47
+ "@hey-api/json-schema-ref-parser": "^1.4.4",
48
+ "js-yaml": "^4.1.0",
49
+ "@ir-kit/openapi": "0.5.0"
49
50
  },
50
51
  "devDependencies": {
52
+ "@types/js-yaml": "^4.0.9",
51
53
  "@types/node": "^22",
52
54
  "vitest": "^4.0.0",
53
55
  "@ir-kit/tsconfig": "0.0.0"