From 4fa41ad012f389c1f4a183e48d940cf97eb4dd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Fri, 12 Feb 2021 00:58:53 +0200 Subject: [PATCH] feat: lazyInlineResolver util --- src/__tests__/lazyInlineRefResolver.spec.ts | 25 ++++++++++++++ src/index.ts | 1 + src/lazyInlineRefResolver.ts | 38 +++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/__tests__/lazyInlineRefResolver.spec.ts create mode 100644 src/lazyInlineRefResolver.ts diff --git a/src/__tests__/lazyInlineRefResolver.spec.ts b/src/__tests__/lazyInlineRefResolver.spec.ts new file mode 100644 index 0000000..1fc6c4c --- /dev/null +++ b/src/__tests__/lazyInlineRefResolver.spec.ts @@ -0,0 +1,25 @@ +import { lazyInlineRefResolver } from '../lazyInlineRefResolver'; + +describe('lazyInlineResolver', () => { + test('should work', () => { + const doc = { + a: { + $ref: '#/b/foo', + }, + b: { + foo: { + $ref: '#/c', + }, + bar: { + $ref: '#/e', + }, + }, + c: { + $ref: '#/b/bar', + }, + e: 'woo!', + }; + + expect((lazyInlineRefResolver(doc) as any).b.foo).toBe('woo!'); + }); +}); diff --git a/src/index.ts b/src/index.ts index 59283e0..66d9165 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ export * from './getLastPathSegment'; export * from './getLocationForJsonPath'; export * from './hasRef'; export * from './isLocalRef'; +export * from './lazyInlineRefResolver'; export * from './parseWithPointers'; export * from './pathToPointer'; export * from './pointerToPath'; diff --git a/src/lazyInlineRefResolver.ts b/src/lazyInlineRefResolver.ts new file mode 100644 index 0000000..04a3768 --- /dev/null +++ b/src/lazyInlineRefResolver.ts @@ -0,0 +1,38 @@ +import { resolveInlineRef } from './resolveInlineRef'; + +const ROOT_MAP = new WeakMap(); + +type Root = Record; + +// todo: handle circular? might be not needed, as simply pass the responsibility onto consumer +const traps: ProxyHandler = { + get(target, key, recv) { + const value = Reflect.get(target, key, recv); + + if (typeof value === 'object' && value !== null) { + const root = ROOT_MAP.get(target); + + if (!('$ref' in value)) { + return _lazyInlineRefResolver(value, root); + } + + const resolved = resolveInlineRef(root, value.$ref); + if (typeof resolved === 'object' && resolved !== null) { + return _lazyInlineRefResolver(resolved, root); + } + + return resolved; + } + + return value; + }, +}; + +function _lazyInlineRefResolver(obj: object, root: Root) { + ROOT_MAP.set(obj, root); + return new Proxy(obj, traps); +} + +export function lazyInlineRefResolver(root: Root) { + return _lazyInlineRefResolver(root, root); +}