Skip to content

Commit 1749bda

Browse files
committed
feat: implement JSON parser adapter for JSON Schema 2020-12
Refs #1867
1 parent 603c9b3 commit 1749bda

23 files changed

+977
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ You can install ApiDOM packages using [npm CLI](https://docs.npmjs.com/cli):
9090
$ npm install @swagger-api/apidom-parser-adapter-asyncapi-json-2
9191
$ npm install @swagger-api/apidom-parser-adapter-asyncapi-yaml-2
9292
$ npm install @swagger-api/apidom-parser-adapter-json
93+
$ npm install @swagger-api/apidom-parser-adapter-json-schema-json-2020-12
9394
$ npm install @swagger-api/apidom-parser-adapter-openapi-json-2
9495
$ npm install @swagger-api/apidom-parser-adapter-openapi-json-3-0
9596
$ npm install @swagger-api/apidom-parser-adapter-openapi-json-3-1

package-lock.json

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**/*.js
2+
/**/*.mjs
3+
/**/*.cjs
4+
/dist
5+
/types
6+
/config
7+
/.nyc_output
8+
/node_modules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/src/**/*.mjs
2+
/src/**/*.cjs
3+
/test/**/*.mjs
4+
/dist
5+
/types
6+
/NOTICE
7+
/swagger-api-apidom-parser-adapter-json-schema-yaml-2020-12-*.tgz
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"recursive": true,
3+
"spec": "test/**/*.mjs",
4+
"file": ["test/mocha-bootstrap.mjs"],
5+
"ignore": ["test/perf/**/*.mjs"]
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
save-prefix="="
2+
save=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# @swagger-api/apidom-parser-adapter-json-schema-json-2020-12
2+
3+
`@swagger-api/apidom-parser-adapter-json-schema-json-2020-12` is a parser adapter for the [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01) in [JSON format](https://www.json.org/json-en.html).
4+
Under the hood this adapter uses [apidom-parser-adapter-json](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser-adapter-json)
5+
to parse a source string into generic ApiDOM in [base ApiDOM namespace](https://github.com/swagger-api/apidom/tree/main/packages/apidom#base-namespace)
6+
which is then refracted with [JSON Schema 2020-12 Refractors](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-json-schema-2020-12#refractors).
7+
8+
## Installation
9+
10+
After [prerequisites](https://github.com/swagger-api/apidom/blob/main/README.md#prerequisites) for installing this package are satisfied, you can install it
11+
via [npm CLI](https://docs.npmjs.com/cli) by running the following command:
12+
13+
```sh
14+
$ npm install @swagger-api/apidom-parser-adapter-json-schema-json-2020-12
15+
```
16+
17+
## Parser adapter API
18+
19+
This parser adapter is fully compatible with parser adapter interface required by [@swagger-api/apidom-parser](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser#mounting-parser-adapters)
20+
and implements all required properties.
21+
22+
### mediaTypes
23+
24+
Defines list of media types that this parser adapter recognizes.
25+
26+
```js
27+
[
28+
'application/schema;version=2020-12',
29+
'application/schema+json;version=2020-12',
30+
]
31+
```
32+
33+
### detect
34+
35+
[Detection](https://github.com/swagger-api/apidom/blob/main/packages/apidom-parser-adapter-json-schema-json-2020-12/src/adapter.ts#L13) is based on a regular expression matching required JSON Schema 2020-12 symbols in JSON format.
36+
37+
### namespace
38+
39+
This adapter exposes an instance of [JSON Schema 2020-12 ApiDOM namespace](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-json-schema-2020-12#json-schema-2020-12-namespace).
40+
41+
### parse
42+
43+
`parse` function consumes various options as a second argument. Here is a list of these options:
44+
45+
Option | Type | Default | Description
46+
--- | --- | --- | ---
47+
<a name="specObj"></a>`specObj` | `Object` | [Specification Object](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ns-json-schema-2020-12/src/refractor/specification.ts) | This specification object drives the JSON AST transformation to JSON Schema 2020-12 ApiDOM namespace.
48+
<a name="sourceMap"></a>`sourceMap` | `Boolean` | `false` | Indicate whether to generate source maps.
49+
<a name="refractorOpts"></a>`refractorOpts` | `Object` | `{}` | Refractor options are [passed to refractors](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-json-schema-2020-12#refractor-plugins) during refracting phase.
50+
51+
All unrecognized arbitrary options will be ignored.
52+
53+
## Usage
54+
55+
This parser adapter can be used directly or indirectly via [@swagger-api/apidom-parser](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser).
56+
57+
### Direct usage
58+
59+
During direct usage you don't need to provide `mediaType` as the `parse` function is already pre-bound
60+
with [supported media types](#mediatypes).
61+
62+
```js
63+
import { parse, detect } from '@swagger-api/apidom-parser-adapter-json-schema-json-2020-12';
64+
65+
// detecting
66+
await detect('{"$schema": "https://json-schema.org/draft/2020-12/schema"}'); // => true
67+
await detect('test'); // => false
68+
69+
// parsing
70+
const parseResult = await parse('{"$schema": "https://json-schema.org/draft/2020-12/schema"}', {
71+
sourceMap: true,
72+
});
73+
```
74+
75+
### Indirect usage
76+
77+
You can omit the `mediaType` option here, but please read [Word on detect vs mediaTypes](https://github.com/swagger-api/apidom/tree/main/packages/apidom-parser#word-on-detect-vs-mediatypes) before you do so.
78+
79+
```js
80+
import ApiDOMParser from '@swagger-api/apidom-parser';
81+
import * as jsonSchemaJsonAdapter from '@swagger-api/apidom-parser-adapter-json-schema-json-2020-12';
82+
83+
const parser = new ApiDOMParser();
84+
85+
parser.use(jsonSchemaJsonAdapter);
86+
87+
const parseResult = await parser.parse(
88+
'{"$schema": "https://json-schema.org/draft/2020-12/schema"}',
89+
{ mediaType: jsonSchemaJsonAdapter.mediaTypes.latest('json') },
90+
);
91+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "../../../../api-extractor.json",
4+
"mainEntryPointFilePath": "../../types/adapter.d.ts"
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import path from 'node:path';
2+
import { nonMinimizeTrait, minimizeTrait } from './traits.config.js';
3+
4+
const browser = {
5+
mode: 'production',
6+
entry: ['./src/adapter.ts'],
7+
target: 'web',
8+
performance: {
9+
maxEntrypointSize: 1800000,
10+
maxAssetSize: 1800000,
11+
},
12+
output: {
13+
path: path.resolve('./dist'),
14+
filename: 'apidom-parser-adapter-json-schema-json-2020-12.browser.js',
15+
libraryTarget: 'umd',
16+
library: 'apidomParserAdapterJSONSchemaJSON202012',
17+
},
18+
resolve: {
19+
extensions: ['.ts', '.mjs', '.js', '.json'],
20+
fallback: {
21+
fs: false,
22+
path: false,
23+
},
24+
},
25+
module: {
26+
rules: [
27+
{
28+
test: /\.wasm$/,
29+
loader: 'file-loader',
30+
type: 'javascript/auto',
31+
},
32+
{
33+
test: /\.(ts|js)?$/,
34+
exclude: /node_modules/,
35+
use: {
36+
loader: 'babel-loader',
37+
options: {
38+
babelrc: true,
39+
rootMode: 'upward',
40+
},
41+
},
42+
},
43+
],
44+
},
45+
...nonMinimizeTrait,
46+
};
47+
48+
const browserMin = {
49+
mode: 'production',
50+
entry: ['./src/adapter.ts'],
51+
target: 'web',
52+
performance: {
53+
maxEntrypointSize: 280000,
54+
maxAssetSize: 280000,
55+
},
56+
output: {
57+
path: path.resolve('./dist'),
58+
filename: 'apidom-parser-adapter-json-schema-json-2020-12.browser.min.js',
59+
libraryTarget: 'umd',
60+
library: 'apidomParserAdapterJSONSchemaJSON202012',
61+
},
62+
resolve: {
63+
extensions: ['.ts', '.mjs', '.js', '.json'],
64+
fallback: {
65+
fs: false,
66+
path: false,
67+
},
68+
},
69+
module: {
70+
rules: [
71+
{
72+
test: /\.wasm$/,
73+
loader: 'file-loader',
74+
type: 'javascript/auto',
75+
},
76+
{
77+
test: /\.(ts|js)?$/,
78+
exclude: /node_modules/,
79+
use: {
80+
loader: 'babel-loader',
81+
options: {
82+
babelrc: true,
83+
rootMode: 'upward',
84+
},
85+
},
86+
},
87+
],
88+
},
89+
...minimizeTrait,
90+
};
91+
92+
export default [browser, browserMin];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import webpack from 'webpack';
2+
import TerserPlugin from 'terser-webpack-plugin';
3+
4+
export const nonMinimizeTrait = {
5+
optimization: {
6+
minimize: false,
7+
usedExports: false,
8+
concatenateModules: false,
9+
},
10+
};
11+
12+
export const minimizeTrait = {
13+
plugins: [
14+
new webpack.LoaderOptionsPlugin({
15+
minimize: true,
16+
}),
17+
],
18+
optimization: {
19+
minimizer: [
20+
new TerserPlugin({
21+
terserOptions: {
22+
compress: {
23+
warnings: false,
24+
},
25+
output: {
26+
comments: false,
27+
},
28+
},
29+
}),
30+
],
31+
},
32+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"name": "@swagger-api/apidom-parser-adapter-json-schema-json-2020-12",
3+
"version": "1.0.0-beta.7",
4+
"description": "Parser adapter for parsing JSON documents into JSON Schema 2020-12 namespace.",
5+
"publishConfig": {
6+
"access": "public",
7+
"registry": "https://registry.npmjs.org"
8+
},
9+
"type": "module",
10+
"sideEffects": false,
11+
"unpkg": "./dist/apidom-parser-apdater-json-schema-json-2020-12.browser.min.js",
12+
"main": "./src/adapter.cjs",
13+
"exports": {
14+
"types": "./types/apidom-parser-adapter-json-schema-json-2020-12.d.ts",
15+
"import": "./src/adapter.mjs",
16+
"require": "./src/adapter.cjs"
17+
},
18+
"types": "./types/apidom-parser-adapter-json-schema-json-2020-12.d.ts",
19+
"scripts": {
20+
"build": "npm run clean && run-p --max-parallel ${CPU_CORES:-2} typescript:declaration build:es build:cjs build:umd:browser",
21+
"build:es": "cross-env BABEL_ENV=es babel src --out-dir src --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward'",
22+
"build:cjs": "cross-env BABEL_ENV=cjs babel src --out-dir src --extensions '.ts' --out-file-extension '.cjs' --root-mode 'upward'",
23+
"build:umd:browser": "cross-env BABEL_ENV=browser webpack --config config/webpack/browser.config.js --progress",
24+
"lint": "eslint ./",
25+
"lint:fix": "eslint ./ --fix",
26+
"clean": "rimraf --glob 'src/**/*.mjs' 'src/**/*.cjs' 'test/**/*.mjs' ./dist ./types",
27+
"typescript:check-types": "tsc --noEmit && tsc -p ./test/tsconfig.json --noEmit",
28+
"typescript:declaration": "tsc -p tsconfig.declaration.json && api-extractor run -l -c ./config/api-extractor/api-extractor.json",
29+
"test": "npm run build:es && cross-env BABEL_ENV=es babel test --out-dir test --extensions '.ts' --out-file-extension '.mjs' --root-mode 'upward' && cross-env NODE_ENV=test mocha",
30+
"prepack": "copyfiles -u 3 ../../LICENSES/* LICENSES && copyfiles -u 2 ../../NOTICE .",
31+
"postpack": "rimraf NOTICE LICENSES"
32+
},
33+
"repository": {
34+
"type": "git",
35+
"url": "git+https://github.com/swagger-api/apidom.git"
36+
},
37+
"author": "Vladimir Gorej",
38+
"license": "Apache-2.0",
39+
"dependencies": {
40+
"@babel/runtime-corejs3": "^7.20.7",
41+
"@swagger-api/apidom-core": "^1.0.0-beta.7",
42+
"@swagger-api/apidom-ns-json-schema-2020-12": "^1.0.0-beta.7",
43+
"@swagger-api/apidom-parser-adapter-json": "^1.0.0-beta.7",
44+
"@types/ramda": "~0.30.0",
45+
"ramda": "~0.30.0",
46+
"ramda-adjunct": "^5.0.0"
47+
},
48+
"files": [
49+
"src/**/*.mjs",
50+
"src/**/*.cjs",
51+
"dist/",
52+
"types/apidom-parser-adapter-json-schema-json-2020-12.d.ts",
53+
"LICENSES",
54+
"NOTICE",
55+
"README.md",
56+
"CHANGELOG.md"
57+
]
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { propOr, omit } from 'ramda';
2+
import { isNotUndefined } from 'ramda-adjunct';
3+
import { ParseResultElement, createNamespace } from '@swagger-api/apidom-core';
4+
import { parse as parseJSON, detect as detectJSON } from '@swagger-api/apidom-parser-adapter-json';
5+
import jsonSchemaNamespace, { JSONSchemaElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
6+
7+
export { default as mediaTypes } from './media-types.ts';
8+
9+
/**
10+
* @public
11+
*/
12+
export const detectionRegExp =
13+
/"\$schema"\s*:\s*"https:\/\/json-schema\.org\/draft\/(?<version_json>2020-12)\/schema"/;
14+
15+
/**
16+
* @public
17+
*/
18+
export const detect = async (source: string): Promise<boolean> =>
19+
detectionRegExp.test(source) && (await detectJSON(source));
20+
21+
/**
22+
* @public
23+
*/
24+
export const parse = async (
25+
source: string,
26+
options: Record<string, unknown> = {},
27+
): Promise<ParseResultElement> => {
28+
const refractorOpts: Record<string, unknown> = propOr({}, 'refractorOpts', options);
29+
const parserOpts = omit(['refractorOpts'], options);
30+
const parseResultElement = await parseJSON(source, parserOpts);
31+
const { result } = parseResultElement;
32+
33+
if (isNotUndefined(result)) {
34+
const jsonSchemaElement = JSONSchemaElement.refract(result, refractorOpts);
35+
jsonSchemaElement.classes.push('result');
36+
parseResultElement.replaceResult(jsonSchemaElement);
37+
}
38+
39+
return parseResultElement;
40+
};
41+
42+
/**
43+
* @public
44+
*/
45+
export const namespace = createNamespace(jsonSchemaNamespace);

0 commit comments

Comments
 (0)