34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
/* eslint-disable implicit-arrow-linebreak, @typescript-eslint/explicit-function-return-type, newline-before-return */
|
|
/**
|
|
* This code is inspired by and adapted from:
|
|
* https://github.com/bitauth/libauth
|
|
*/
|
|
import { lossyNormalize } from '@bitauth/libauth';
|
|
import xoTemplateValidator from './validate-xo-template.js';
|
|
import type { AjvValidator, XOAjvError } from './ajv-types.js';
|
|
|
|
const avjErrorsToDescription = (errors: XOAjvError[]): string =>
|
|
// TODO: translate instancePath
|
|
errors.map((error) => `${error.instancePath}: ${error.message}`).join(',');
|
|
|
|
/**
|
|
* Given an untrusted JSON string or object and an AJV validator, verify that
|
|
* the untrusted value is of the expected shape. Note, this method first
|
|
* normalizes all characters in the input using `Normalization Form KC`
|
|
* (Compatibility Decomposition, followed by Canonical Composition).
|
|
*/
|
|
export const ajvStandaloneJsonParse = <T>(untrustedJsonOrObject: unknown, validator: AjvValidator<T>) => {
|
|
try {
|
|
const stringified = typeof untrustedJsonOrObject === 'string' ? untrustedJsonOrObject : JSON.stringify(untrustedJsonOrObject);
|
|
const normalized = lossyNormalize(stringified);
|
|
const parsed = JSON.parse(normalized) as unknown;
|
|
if (validator(parsed)) {
|
|
return parsed;
|
|
}
|
|
// @ts-ignore
|
|
return avjErrorsToDescription(xoTemplateValidator.errors!);
|
|
} catch (e) {
|
|
return `Invalid JSON. ${String(e)}`;
|
|
}
|
|
};
|