Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add uriresolver option #1862

Merged
merged 15 commits into from Feb 4, 2022
11 changes: 8 additions & 3 deletions lib/compile/index.ts
Expand Up @@ -257,9 +257,14 @@ export function resolveSchema(
root: SchemaEnv, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
ref: string // reference to resolve
): SchemaEnv | undefined {
const p = URI.parse(ref)
const refPath = _getFullPath(p)
let baseId = getFullPath(root.baseId)
let p: URI.URIComponents
if (this.opts.uriResolver) {
p = this.opts.uriResolver.parse(ref)
} else {
p = URI.parse(ref)
}
const refPath = _getFullPath(p, this.opts.uriResolver)
let baseId = getFullPath(root.baseId, undefined, this.opts.uriResolver)
// TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
if (Object.keys(root.schema).length > 0 && refPath === baseId) {
return getJsonPointer.call(this, p, root)
Expand Down
28 changes: 21 additions & 7 deletions lib/compile/resolve.ts
@@ -1,4 +1,4 @@
import type {AnySchema, AnySchemaObject} from "../types"
import type {AnySchema, AnySchemaObject, UriResolver} from "../types"
import type Ajv from "../ajv"
import {eachItem} from "./util"
import * as equal from "fast-deep-equal"
Expand Down Expand Up @@ -67,14 +67,25 @@ function countKeys(schema: AnySchemaObject): number {
return count
}

export function getFullPath(id = "", normalize?: boolean): string {
export function getFullPath(id = "", normalize?: boolean, resolver?: UriResolver): string {
if (normalize !== false) id = normalizeId(id)
const p = URI.parse(id)
return _getFullPath(p)
let p: URI.URIComponents
if (resolver !== undefined) {
p = resolver.parse(id)
} else {
p = URI.parse(id)
}
return _getFullPath(p, resolver)
}

export function _getFullPath(p: URI.URIComponents): string {
return URI.serialize(p).split("#")[0] + "#"
export function _getFullPath(p: URI.URIComponents, resolver?: UriResolver): string {
let serialized: string
if (resolver !== undefined) {
serialized = resolver.serialize(p)
} else {
serialized = URI.serialize(p)
}
return serialized.split("#")[0] + "#"
}

const TRAILING_SLASH_HASH = /#\/?$/
Expand Down Expand Up @@ -108,7 +119,10 @@ export function getSchemaRefs(this: Ajv, schema: AnySchema, baseId: string): Loc
baseIds[jsonPtr] = baseId

function addRef(this: Ajv, ref: string): string {
ref = normalizeId(baseId ? URI.resolve(baseId, ref) : ref)
const _resolve =
// eslint-disable-next-line @typescript-eslint/unbound-method
this.opts.uriResolver !== undefined ? this.opts.uriResolver?.resolve : URI.resolve
ref = normalizeId(baseId ? _resolve(baseId, ref) : ref)
if (schemaRefs.has(ref)) throw ambiguos(ref)
schemaRefs.add(ref)
let schOrRef = this.refs[ref]
Expand Down
3 changes: 2 additions & 1 deletion lib/core.ts
Expand Up @@ -49,6 +49,7 @@ import type {
Format,
AddedFormat,
RegExpEngine,
UriResolver,
} from "./types"
import type {JSONSchemaType} from "./types/json-schema"
import type {JTDSchemaType, SomeJTDSchemaType, JTDDataType} from "./types/jtd-schema"
Expand All @@ -60,7 +61,6 @@ import {Code, ValueScope} from "./compile/codegen"
import {normalizeId, getSchemaRefs} from "./compile/resolve"
import {getJSONTypes} from "./compile/validate/dataType"
import {eachItem} from "./compile/util"

import * as $dataRefSchema from "./refs/data.json"

const defaultRegExp: RegExpEngine = (str, flags) => new RegExp(str, flags)
Expand Down Expand Up @@ -136,6 +136,7 @@ export interface CurrentOptions {
int32range?: boolean // JTD only
messages?: boolean
code?: CodeOptions // NEW
uriResolver?: UriResolver
}

export interface CodeOptions {
Expand Down
7 changes: 7 additions & 0 deletions lib/types/index.ts
@@ -1,3 +1,4 @@
import * as URI from "uri-js"
import type {CodeGen, Code, Name, ScopeValueSets, ValueScopeName} from "../compile/codegen"
import type {SchemaEnv, SchemaCxt, SchemaObjCxt} from "../compile"
import type {JSONType} from "../compile/rules"
Expand Down Expand Up @@ -231,3 +232,9 @@ export interface RegExpEngine {
export interface RegExpLike {
test: (s: string) => boolean
}

export interface UriResolver {
parse(uri: string): URI.URIComponents
resolve(base: string, path: string): string
serialize(component: URI.URIComponents): string
}
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -83,6 +83,7 @@
"dayjs-plugin-utc": "^0.1.2",
"eslint": "^7.8.1",
"eslint-config-prettier": "^7.0.0",
"fast-uri": "^0.0.1",
"glob": "^7.0.0",
"husky": "^7.0.1",
"if-node-version": "^1.0.0",
Expand Down