From 24bdc55714ffe14def4676035d61535ee9e2ca09 Mon Sep 17 00:00:00 2001 From: Tom Pytleski Date: Fri, 26 Jul 2019 16:04:35 -0500 Subject: [PATCH 1/4] feat: add transform dereference result hook --- src/resolver.ts | 3 +++ src/runner.ts | 22 ++++++++++++++++- src/types.ts | 23 +++++++++++++++++- yarn.lock | 64 +++++++++++++------------------------------------ 4 files changed, 62 insertions(+), 50 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 2565778..15a67ef 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -20,6 +20,7 @@ export class Resolver { protected getRef?: (key: string, val: any) => string | void; protected transformRef?: (opts: Types.IRefTransformer, ctx: any) => uri.URI | any; protected parseResolveResult?: (opts: Types.IUriParser) => Promise; + protected transformDereferenceResult?: (opts: Types.ITransformerOptions) => Promise; constructor(opts: Types.IResolverOpts = {}) { this.uriCache = opts.uriCache || new Cache(); @@ -29,6 +30,7 @@ export class Resolver { this.dereferenceInline = typeof opts.dereferenceInline !== 'undefined' ? opts.dereferenceInline : true; this.dereferenceRemote = typeof opts.dereferenceRemote !== 'undefined' ? opts.dereferenceRemote : true; this.parseResolveResult = opts.parseResolveResult; + this.transformDereferenceResult = opts.transformDereferenceResult; this.ctx = opts.ctx; } @@ -41,6 +43,7 @@ export class Resolver { dereferenceInline: this.dereferenceInline, dereferenceRemote: this.dereferenceRemote, parseResolveResult: this.parseResolveResult, + transformDereferenceResult: this.transformDereferenceResult, ...opts, ctx: Object.assign({}, this.ctx || {}, opts.ctx || {}), }); diff --git a/src/runner.ts b/src/runner.ts index e8f7c15..d77a008 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -38,6 +38,7 @@ export class ResolveRunner implements Types.IResolveRunner { public readonly getRef: (key: string, val: any) => string | void; public readonly transformRef?: (opts: Types.IRefTransformer, ctx: any) => uri.URI | any; public readonly parseResolveResult?: (opts: Types.IUriParser) => Promise; + public readonly transformDereferenceResult?: (opts: Types.ITransformerOptions) => Promise; private _source: any; @@ -74,6 +75,7 @@ export class ResolveRunner implements Types.IResolveRunner { this.dereferenceRemote = typeof opts.dereferenceRemote !== 'undefined' ? opts.dereferenceRemote : true; this.parseResolveResult = opts.parseResolveResult; + this.transformDereferenceResult = opts.transformDereferenceResult; this.ctx = opts.ctx; this.lookupUri = memoize(this.lookupUri, { @@ -318,7 +320,8 @@ export class ResolveRunner implements Types.IResolveRunner { if (this.parseResolveResult) { try { const parsed = await this.parseResolveResult({ - uriResult: result, + // TODO: Is this correct? Result has type any, but uriResult should be type IUriResult. + // uriResult: result, result, targetAuthority: ref, parentAuthority: this.baseUri, @@ -340,6 +343,7 @@ export class ResolveRunner implements Types.IResolveRunner { resolvers: this.resolvers, transformRef: this.transformRef, parseResolveResult: this.parseResolveResult, + transformDereferenceResult: this.transformDereferenceResult, dereferenceRemote: this.dereferenceRemote, dereferenceInline: this.dereferenceInline, ctx: this.ctx, @@ -408,6 +412,22 @@ export class ResolveRunner implements Types.IResolveRunner { if (uriResolver) { lookupResult.resolved = await uriResolver.resolve(Utils.uriToJSONPointer(ref)); + // support custom transformers + if (this.transformDereferenceResult) { + const { result, error } = await this.transformDereferenceResult({ + source: uriResolver.source, + result: lookupResult.resolved.result, + targetAuthority: ref, + parentAuthority: this.baseUri, + parentPath, + fragment: ref.fragment(), + }); + if (error) { + throw new Error(`Could not transform dereferenced result for '${ref.toString()}' - ${String(error)}`); + } + + lookupResult.resolved.result = result; + } // if pointer resolution failed, revert to the original value (which will be a $ref most of the time) if (lookupResult.resolved.errors.length) { for (const error of lookupResult.resolved.errors) { diff --git a/src/types.ts b/src/types.ts index 4fae3b2..ae1c9cf 100644 --- a/src/types.ts +++ b/src/types.ts @@ -51,6 +51,13 @@ export interface IResolverOpts { */ parseResolveResult?: (opts: IUriParser) => Promise; + /** + * Hook to transform resolved object. + * + * For example, transform `OpenAPI` file to a `Hub Page`. + */ + transformDereferenceResult?: (opts: ITransformerOptions) => Promise; + /** Should we resolve local pointers? true by default. */ dereferenceInline?: boolean; @@ -115,7 +122,7 @@ export interface IResolver { export interface IUriParser { result: any; fragment: string; - uriResult: IUriResult; + // uriResult: IUriResult; targetAuthority: uri.URI; parentAuthority: uri.URI; parentPath: string[]; @@ -126,6 +133,20 @@ export interface IUriParserResult { error?: Error; } +export interface ITransformerOptions { + result: any; + source: any; + fragment: string; + targetAuthority: uri.URI; + parentAuthority: uri.URI; + parentPath: string[]; +} + +export interface ITransformerResult { + result?: any; + error?: Error; +} + export interface IUriResult { pointerStack: string[]; targetPath: string[]; diff --git a/yarn.lock b/yarn.lock index 577b930..7b0b7f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2200,7 +2200,7 @@ debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -3478,7 +3478,7 @@ import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -4618,7 +4618,7 @@ libnpm@^2.0.1: read-package-json "^2.0.13" stringify-package "^1.0.0" -libnpmaccess@*, libnpmaccess@^3.0.1: +libnpmaccess@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.1.tgz#5b3a9de621f293d425191aa2e779102f84167fa8" integrity sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA== @@ -4655,7 +4655,7 @@ libnpmhook@^5.0.2: get-stream "^4.0.0" npm-registry-fetch "^3.8.0" -libnpmorg@*, libnpmorg@^1.0.0: +libnpmorg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.0.tgz#979b868c48ba28c5820e3bb9d9e73c883c16a232" integrity sha512-o+4eVJBoDGMgRwh2lJY0a8pRV2c/tQM/SxlqXezjcAg26Qe9jigYVs+Xk0vvlYDWCDhP0g74J8UwWeAgsB7gGw== @@ -4680,7 +4680,7 @@ libnpmpublish@^1.1.0: semver "^5.5.1" ssri "^6.0.1" -libnpmsearch@*, libnpmsearch@^2.0.0: +libnpmsearch@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.1.tgz#eccc73a8fbf267d765d18082b85daa2512501f96" integrity sha512-K0yXyut9MHHCAH+DOiglQCpmBKPZXSUu76+BE2maSEfQN15OwNaA/Aiioe9lRFlVFOr7WcuJCY+VSl+gLi9NTA== @@ -4689,7 +4689,7 @@ libnpmsearch@*, libnpmsearch@^2.0.0: get-stream "^4.0.0" npm-registry-fetch "^3.8.0" -libnpmteam@*, libnpmteam@^1.0.1: +libnpmteam@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.1.tgz#ff704b1b6c06ea674b3b1101ac3e305f5114f213" integrity sha512-gDdrflKFCX7TNwOMX1snWojCoDE5LoRWcfOC0C/fqF7mBq8Uz9zWAX4B2RllYETNO7pBupBaSyBDkTAC15cAMg== @@ -4841,11 +4841,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -4854,33 +4849,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -4926,11 +4899,6 @@ lodash.map@^4.5.1: resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -5698,15 +5666,6 @@ npm-pick-manifest@^2.1.0, npm-pick-manifest@^2.2.3: npm-package-arg "^6.0.0" semver "^5.4.1" -npm-profile@*, npm-profile@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.1.tgz#d350f7a5e6b60691c7168fbb8392c3603583f5aa" - integrity sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA== - dependencies: - aproba "^1.1.2 || 2" - figgy-pudding "^3.4.1" - npm-registry-fetch "^3.8.0" - npm-profile@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-3.0.2.tgz#58d568f1b56ef769602fd0aed8c43fa0e0de0f57" @@ -5715,6 +5674,15 @@ npm-profile@^3.0.2: aproba "^1.1.2 || 2" make-fetch-happen "^2.5.0 || 3 || 4" +npm-profile@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.1.tgz#d350f7a5e6b60691c7168fbb8392c3603583f5aa" + integrity sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA== + dependencies: + aproba "^1.1.2 || 2" + figgy-pudding "^3.4.1" + npm-registry-fetch "^3.8.0" + npm-registry-client@^8.6.0: version "8.6.0" resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.6.0.tgz#7f1529f91450732e89f8518e0f21459deea3e4c4" @@ -6841,7 +6809,7 @@ readable-stream@~1.1.10: isarray "0.0.1" string_decoder "~0.10.x" -readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: +readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== From d20e1112fa0619756b2227e7be5434a7ec77d98b Mon Sep 17 00:00:00 2001 From: Tom Pytleski Date: Tue, 30 Jul 2019 12:43:29 -0500 Subject: [PATCH 2/4] chore: add tests --- src/__tests__/resolver.spec.ts | 177 +++++++++++++++++++++++++++++++++ src/runner.ts | 47 +++++---- src/types.ts | 9 +- 3 files changed, 213 insertions(+), 20 deletions(-) diff --git a/src/__tests__/resolver.spec.ts b/src/__tests__/resolver.spec.ts index 30adb48..17d085f 100644 --- a/src/__tests__/resolver.spec.ts +++ b/src/__tests__/resolver.spec.ts @@ -1670,6 +1670,183 @@ describe('resolver', () => { expect(result.errors[0].uri.toString()).toEqual(new URI('http://foo').toString()); }); + /** + * Allows the consumer to provide a custom ref transformer to transform a fully resolved object. + * + */ + test('should support `transformDereferenceResult` hook', async () => { + const data = { + markdown: '# hello', + bar: { + hello: `{ "hello": "world" }`, + }, + }; + + const source = { + definitions: { + foo: { + $ref: 'http://foo.com/foo.md#/markdown', + }, + bar: { + $ref: 'http://foo.com/bar.json#/hello', + }, + }, + }; + + const reader: Types.IResolver = { + async resolve(ref: uri.URI): Promise { + if (ref.path().split('.')[1] === 'md') { + return data; + } + + return data.bar; + }, + }; + + const resolver = new Resolver({ + resolvers: { + http: reader, + }, + transformDereferenceResult: async opts => { + if (opts.parentAuthority.path().split('.')[1] === 'md') { + opts.result = { + heading1: 'hello', + }; + } else if (opts.parentAuthority.toString() === 'http://foo.com/bar.json' && opts.fragment === '/hello') { + // Can transform the result however you want + opts.result = { + pooh: 'bear', + }; + } + + return opts; + }, + }); + + const result = await resolver.resolve(source); + + expect(result.result).toEqual({ + definitions: { + foo: { + heading1: 'hello', + }, + bar: { + pooh: 'bear', + }, + }, + }); + }); + + test('should pass `transformDereferenceResult` to child runners', async () => { + const data = { + foo: { + $ref: 'http://foo.com/hi', + }, + hi: { + $ref: 'http://foo.com/bye', + }, + bye: { + adios: true, + }, + bar: { + hello: 'world', + }, + }; + + const source = { + definitions: { + foo: { + $ref: 'http://foo.com/foo', + }, + bar: { + $ref: 'http://foo.com/bar', + }, + }, + }; + + const reader: Types.IResolver = { + async resolve(ref: uri.URI): Promise { + return data[ref.path().slice(1)]; + }, + }; + + let counter = 0; + const resolver = new Resolver({ + resolvers: { + http: reader, + }, + transformDereferenceResult: async opts => { + counter += 1; + return opts; + }, + }); + + const result = await resolver.resolve(source); + + expect(result.result).toEqual({ + definitions: { + foo: { + adios: true, + }, + bar: { + hello: 'world', + }, + }, + }); + + expect(counter).toEqual(5); + }); + + test('should support catching error in `transformDereferenceResult` hook', async () => { + const data = { + markdown: '# hello', + }; + + const source = { + definitions: { + foo: { + $ref: 'http://foo.com#/markdown', + }, + }, + }; + + const reader: Types.IResolver = { + async resolve(): Promise { + return data; + }, + }; + + const resolver = new Resolver({ + resolvers: { + http: reader, + }, + transformDereferenceResult: async opts => { + if (opts.parentAuthority.toString() === 'http://foo.com/') throw new Error('some transform error!'); + + return opts; + }, + }); + + const result = await resolver.resolve(source); + + expect(result.result).toEqual({ + definitions: { + foo: '# hello', + }, + }); + + expect({ ...result.errors[0], uri: undefined }).toEqual({ + code: 'TRANSFORM_DEREFERENCED', + message: + "Error: Could not transform dereferenced result for 'http://foo.com/#/markdown' - Error: some transform error!", + pointerStack: [], + uriStack: [], + path: ['markdown'], + uri: undefined, + }); + expect(result.errors[0].uri.toString()).toEqual(new URI('#/markdown').toString()); + }); + test('should pass context to transformRef and read', async () => { let t1; let t2; diff --git a/src/runner.ts b/src/runner.ts index d77a008..cdc0025 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -235,6 +235,34 @@ export class ResolveRunner implements Types.IResolveRunner { resolved.result = this._source; } + // support custom transformers + if (this.transformDereferenceResult) { + const ref = new URI(jsonPointer || ''); + try { + const { result } = await this.transformDereferenceResult({ + source: this.source, + result: resolved.result, + targetAuthority: ref, + parentAuthority: this.baseUri, + parentPath: targetPath, + fragment: ref.fragment(), + }); + + resolved.result = result; + } catch (e) { + resolved.errors.push({ + code: 'TRANSFORM_DEREFERENCED', + message: `Error: Could not transform dereferenced result for '${this.baseUri.toString()}${ + ref.fragment() !== '' ? `#${ref.fragment()}` : `` + }' - ${String(e)}`, + uri: ref, + uriStack: this.uriStack, + pointerStack: [], + path: targetPath, + }); + } + } + return resolved; } @@ -320,8 +348,7 @@ export class ResolveRunner implements Types.IResolveRunner { if (this.parseResolveResult) { try { const parsed = await this.parseResolveResult({ - // TODO: Is this correct? Result has type any, but uriResult should be type IUriResult. - // uriResult: result, + uriResult: result, result, targetAuthority: ref, parentAuthority: this.baseUri, @@ -412,22 +439,6 @@ export class ResolveRunner implements Types.IResolveRunner { if (uriResolver) { lookupResult.resolved = await uriResolver.resolve(Utils.uriToJSONPointer(ref)); - // support custom transformers - if (this.transformDereferenceResult) { - const { result, error } = await this.transformDereferenceResult({ - source: uriResolver.source, - result: lookupResult.resolved.result, - targetAuthority: ref, - parentAuthority: this.baseUri, - parentPath, - fragment: ref.fragment(), - }); - if (error) { - throw new Error(`Could not transform dereferenced result for '${ref.toString()}' - ${String(error)}`); - } - - lookupResult.resolved.result = result; - } // if pointer resolution failed, revert to the original value (which will be a $ref most of the time) if (lookupResult.resolved.errors.length) { for (const error of lookupResult.resolved.errors) { diff --git a/src/types.ts b/src/types.ts index ae1c9cf..257fb0e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -122,7 +122,7 @@ export interface IResolver { export interface IUriParser { result: any; fragment: string; - // uriResult: IUriResult; + uriResult: IUriResult; targetAuthority: uri.URI; parentAuthority: uri.URI; parentPath: string[]; @@ -168,7 +168,12 @@ export interface IRefTransformer extends IComputeRefOpts { uri: uri.URI; } -export type ResolverErrorCode = 'POINTER_MISSING' | 'RESOLVE_URI' | 'PARSE_URI' | 'RESOLVE_POINTER'; +export type ResolverErrorCode = + | 'POINTER_MISSING' + | 'RESOLVE_URI' + | 'PARSE_URI' + | 'RESOLVE_POINTER' + | 'TRANSFORM_DEREFERENCED'; export interface IResolveError { code: ResolverErrorCode; message: string; From f18cebe445717c602a5055f81c8ecf5dd2e703d1 Mon Sep 17 00:00:00 2001 From: Tom Pytleski Date: Tue, 30 Jul 2019 12:45:43 -0500 Subject: [PATCH 3/4] chore: update interface names --- src/resolver.ts | 2 +- src/runner.ts | 4 +++- src/types.ts | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 15a67ef..ed79e8d 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -20,7 +20,7 @@ export class Resolver { protected getRef?: (key: string, val: any) => string | void; protected transformRef?: (opts: Types.IRefTransformer, ctx: any) => uri.URI | any; protected parseResolveResult?: (opts: Types.IUriParser) => Promise; - protected transformDereferenceResult?: (opts: Types.ITransformerOptions) => Promise; + protected transformDereferenceResult?: (opts: Types.IDereferenceTransformer) => Promise; constructor(opts: Types.IResolverOpts = {}) { this.uriCache = opts.uriCache || new Cache(); diff --git a/src/runner.ts b/src/runner.ts index cdc0025..62fbb00 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -38,7 +38,9 @@ export class ResolveRunner implements Types.IResolveRunner { public readonly getRef: (key: string, val: any) => string | void; public readonly transformRef?: (opts: Types.IRefTransformer, ctx: any) => uri.URI | any; public readonly parseResolveResult?: (opts: Types.IUriParser) => Promise; - public readonly transformDereferenceResult?: (opts: Types.ITransformerOptions) => Promise; + public readonly transformDereferenceResult?: ( + opts: Types.IDereferenceTransformer, + ) => Promise; private _source: any; diff --git a/src/types.ts b/src/types.ts index 257fb0e..3470be5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -56,7 +56,7 @@ export interface IResolverOpts { * * For example, transform `OpenAPI` file to a `Hub Page`. */ - transformDereferenceResult?: (opts: ITransformerOptions) => Promise; + transformDereferenceResult?: (opts: IDereferenceTransformer) => Promise; /** Should we resolve local pointers? true by default. */ dereferenceInline?: boolean; @@ -133,7 +133,7 @@ export interface IUriParserResult { error?: Error; } -export interface ITransformerOptions { +export interface IDereferenceTransformer { result: any; source: any; fragment: string; From a8bfb7c0b7bd01256ff4036ea9e3ce2278a85c4b Mon Sep 17 00:00:00 2001 From: Tom Pytleski Date: Tue, 30 Jul 2019 12:53:43 -0500 Subject: [PATCH 4/4] chore: pr feedback --- src/runner.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runner.ts b/src/runner.ts index 62fbb00..dc83d2b 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -241,7 +241,7 @@ export class ResolveRunner implements Types.IResolveRunner { if (this.transformDereferenceResult) { const ref = new URI(jsonPointer || ''); try { - const { result } = await this.transformDereferenceResult({ + const { result, error } = await this.transformDereferenceResult({ source: this.source, result: resolved.result, targetAuthority: ref, @@ -251,6 +251,9 @@ export class ResolveRunner implements Types.IResolveRunner { }); resolved.result = result; + if (error) { + throw new Error(`Could not transform dereferenced result for '${ref.toString()}' - ${String(error)}`); + } } catch (e) { resolved.errors.push({ code: 'TRANSFORM_DEREFERENCED',