Skip to content

Commit 31f3c74

Browse files
committed
feat: implement JSON Schema 2020-12 namespace
Refs #1820
1 parent f0057bb commit 31f3c74

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+6089
-4
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ You can install ApiDOM packages using [npm CLI](https://docs.npmjs.com/cli):
7676
$ npm install @swagger-api/apidom-ns-api-design-systems
7777
$ npm install @swagger-api/apidom-ns-asyncapi-2
7878
$ npm install @swagger-api/apidom-ns-json-schema-2019-09
79+
$ npm install @swagger-api/apidom-ns-json-schema-2020-12
7980
$ npm install @swagger-api/apidom-ns-json-schema-draft-4
8081
$ npm install @swagger-api/apidom-ns-json-schema-draft-6
8182
$ npm install @swagger-api/apidom-ns-json-schema-draft-7

package-lock.json

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/apidom-ns-json-schema-2019-09/src/index.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ export type {
4646
SpecPath,
4747
} from '@swagger-api/apidom-ns-json-schema-draft-7';
4848

49-
export type {
50-
default as JSONSchemaVisitor,
51-
JSONSchemaVisitorOptions,
52-
} from './refractor/visitors/json-schema/index.ts';
49+
export { default as JSONSchemaVisitor } from './refractor/visitors/json-schema/index.ts';
50+
export type { JSONSchemaVisitorOptions } from './refractor/visitors/json-schema/index.ts';
5351
export type {
5452
default as LinkDescriptionVisitor,
5553
LinkDescriptionVisitorOptions,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**/*.js
2+
/**/*.mjs
3+
/**/*.cjs
4+
/dist
5+
/config
6+
/types
7+
/.eslintrc.js
8+
/.nyc_output
9+
/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-ns-json-schema-2020-12*.tgz
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"recursive": true,
3+
"spec": "test/**/*.mjs",
4+
"file": ["test/mocha-bootstrap.mjs"]
5+
}
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,186 @@
1+
# @swagger-api/apidom-ns-json-schema-2020-12
2+
3+
`@swagger-api/apidom-ns-json-schema-2020-12` contains ApiDOM namespace specific to [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01) specification.
4+
5+
## Installation
6+
7+
You can install this package via [npm CLI](https://docs.npmjs.com/cli) by running the following command:
8+
9+
```sh
10+
$ npm install @swagger-api/apidom-ns-json-schema-2020-12
11+
```
12+
13+
## JSON Schema 2020-12 namespace
14+
15+
JSON Schema 2020-12 namespace consists of [number of elements](https://github.com/swagger-api/apidom/tree/main/packages/apidom-ns-json-schema-2020-12/src/elements) implemented on top
16+
of [primitive ones](https://github.com/refractproject/minim/tree/master/lib/primitives).
17+
18+
```js
19+
import { createNamespace } from '@swagger-api/apidom-core';
20+
import jsonShema202012Namespace from '@swagger-api/apidom-ns-json-schema-2020-12';
21+
22+
const namespace = createNamespace(jsonShema202012Namespace);
23+
24+
const objectElement = new namespace.elements.Object();
25+
const jsonSchemaElement = new namespace.elements.JSONSchema202012();
26+
```
27+
28+
When namespace instance is created in this way, it will extend the base namespace
29+
with the namespace provided as an argument.
30+
31+
Elements from the namespace can also be used directly by importing them.
32+
33+
```js
34+
import { JSONSchemaElement, LinkDescriptionElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
35+
36+
const jsonSchemaElement = new JSONSchemaElement();
37+
const linkDescriptionElement = new LinkDescriptionElement();
38+
```
39+
40+
## Predicates
41+
42+
This package exposes [predicates](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ns-json-schema-2020-12/src/predicates.ts)
43+
for all higher order elements that are part of this namespace.
44+
45+
```js
46+
import { isJSONSchemaElement, JSONSchemaElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
47+
48+
const jsonSchemaElement = new JSONSchemaElement();
49+
50+
isJSONSchemaElement(jsonSchemaElement); // => true
51+
```
52+
53+
## Traversal
54+
55+
Traversing ApiDOM in this namespace is possible by using `visit` function from `apidom` package.
56+
This package comes with its own [keyMap](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ns-json-schema-2020-12/src/traversal/visitor.ts#L11) and [nodeTypeGetter](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ns-json-schema-2020-12/src/traversal/visitor.ts#L4).
57+
To learn more about these `visit` configuration options please refer to [@swagger-api/apidom-ast documentation](https://github.com/swagger-api/apidom/blob/main/packages/apidom-ast/README.md#visit).
58+
59+
```js
60+
import { visit } from '@swagger-api/apidom-core';
61+
import { JSONSchemaElement, keyMap, getNodeType } from '@swagger-api/apidom-ns-json-schema-2020-12';
62+
63+
const element = new JSONSchemaElement();
64+
65+
const visitor = {
66+
JSONSchema202012Element(jsonSchemaElement) {
67+
console.dir(jsonSchemaElement);
68+
},
69+
};
70+
71+
visit(element, visitor, { keyMap, nodeTypeGetter: getNodeType });
72+
```
73+
74+
## Refractors
75+
76+
Refractor is a special layer inside the namespace that can transform either JavaScript structures
77+
or generic ApiDOM structures into structures built from elements of this namespace.
78+
79+
**Refracting JavaScript structures**:
80+
81+
```js
82+
import { LinkDescriptionElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
83+
84+
const object = {
85+
anchor: 'nodes/{thisNodeId}',
86+
anchorPointer: '#/relative/json/pointer',
87+
};
88+
89+
LinkDescriptionElement.refract(object); // => LinkDescriptionElement({ anchor, anchorPointer })
90+
```
91+
92+
**Refracting generic ApiDOM structures**:
93+
94+
```js
95+
import { ObjectElement } from '@swagger-api/apidom-core';
96+
import { LinkDescriptionElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
97+
98+
const objectElement = new ObjectElement({
99+
anchor: 'nodes/{thisNodeId}',
100+
anchorPointer: '#/relative/json/pointer',
101+
});
102+
103+
LinkDescriptionElement.refract(objectElement); // => LinkDescriptionElement({ anchor = 'nodes/{thisNodeId}', anchorPointer = '#/relative/json/pointer' })
104+
```
105+
106+
### Refractor plugins
107+
108+
Refractors can accept plugins as a second argument of refract static method.
109+
110+
```js
111+
import { ObjectElement } from '@swagger-api/apidom-core';
112+
import { LinkDescriptionElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
113+
114+
const objectElement = new ObjectElement({
115+
anchor: 'nodes/{thisNodeId}',
116+
anchorPointer: '#/relative/json/pointer',
117+
});
118+
119+
const plugin = ({ predicates, namespace }) => ({
120+
name: 'plugin',
121+
pre() {
122+
console.dir('runs before traversal');
123+
},
124+
visitor: {
125+
LinkDescriptionElement(linkDescriptionElement) {
126+
linkDescriptionElement.anchorPointer = '#/relative/json/pointer/x';
127+
},
128+
},
129+
post() {
130+
console.dir('runs after traversal');
131+
},
132+
});
133+
134+
LinkDescriptionElement.refract(objectElement, { plugins: [plugin] }); // => LinkDescriptionElement({ anchor = 'nodes/{thisNodeId}', anchorPointer = '#/relative/json/pointer/x' })
135+
```
136+
137+
You can define as many plugins as needed to enhance the resulting namespaced ApiDOM structure.
138+
If multiple plugins with the same visitor method are defined, they run in parallel (just like in Babel).
139+
140+
#### Replace Empty Element plugin
141+
142+
This plugin is specific to YAML 1.2 format, which allows defining key-value pairs with empty key,
143+
empty value, or both. If the value is not provided in YAML format, this plugin compensates for
144+
this missing value with the most appropriate semantic element type.
145+
146+
```js
147+
import { parse } from '@swagger-api/apidom-parser-adapter-yaml-1-2';
148+
import { refractorPluginReplaceEmptyElement, JSONSchemaElement } from '@swagger-api/apidom-ns-json-schema-2020-12';
149+
150+
const yamlDefinition = `
151+
$schema: 'https://json-schema.org/draft/2020-12/schema'
152+
if:
153+
`;
154+
const apiDOM = await parse(yamlDefinition);
155+
const jsonSchemaElement = JSONSchemaElement.refract(apiDOM.result, {
156+
plugins: [refractorPluginReplaceEmptyElement()],
157+
});
158+
159+
// =>
160+
// (JSONSchema202012Element
161+
// (MemberElement
162+
// (StringElement)
163+
// (StringElement))
164+
// (MemberElement
165+
// (StringElement)
166+
// (JSONSchema202012Element)))
167+
168+
// => without the plugin the result would be as follows:
169+
// (JSONSchema202012Element
170+
// (MemberElement
171+
// (StringElement)
172+
// (StringElement))
173+
// (MemberElement
174+
// (StringElement)
175+
// (StringElement)))
176+
```
177+
178+
## Implementation progress
179+
180+
Only fully implemented specification objects should be checked here.
181+
182+
- [x] [JSON Schema Object](https://json-schema.org/draft/2020-12/json-schema-core)
183+
- [x] [Link Description Object](https://json-schema.org/draft/2019-09/draft-handrews-json-schema-hyperschema-02#rfc.section.6)
184+
185+
186+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "../../../../api-extractor.json"
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import path from 'node:path';
2+
import { nonMinimizeTrait, minimizeTrait } from './traits.config.js';
3+
4+
const browser = {
5+
mode: 'production',
6+
entry: ['./src/index.ts'],
7+
target: 'web',
8+
performance: {
9+
maxEntrypointSize: 1400000,
10+
maxAssetSize: 1400000,
11+
},
12+
output: {
13+
path: path.resolve('./dist'),
14+
filename: 'apidom-ns-json-schema-2020-12.browser.js',
15+
libraryTarget: 'umd',
16+
library: 'apidomNsJSONSchema202012',
17+
},
18+
resolve: {
19+
extensions: ['.ts', '.mjs', '.js', '.json'],
20+
},
21+
module: {
22+
rules: [
23+
{
24+
test: /\.(ts|js)?$/,
25+
exclude: /node_modules/,
26+
use: {
27+
loader: 'babel-loader',
28+
options: {
29+
babelrc: true,
30+
rootMode: 'upward',
31+
},
32+
},
33+
},
34+
],
35+
},
36+
...nonMinimizeTrait,
37+
};
38+
39+
const browserMin = {
40+
mode: 'production',
41+
entry: ['./src/index.ts'],
42+
target: 'web',
43+
output: {
44+
path: path.resolve('./dist'),
45+
filename: 'apidom-ns-json-schema-2020-12.browser.js',
46+
libraryTarget: 'umd',
47+
library: 'apidomNsJSONSchema202012',
48+
},
49+
resolve: {
50+
extensions: ['.ts', '.mjs', '.js', '.json'],
51+
},
52+
module: {
53+
rules: [
54+
{
55+
test: /\.(ts|js)?$/,
56+
exclude: /node_modules/,
57+
use: {
58+
loader: 'babel-loader',
59+
options: {
60+
babelrc: true,
61+
rootMode: 'upward',
62+
},
63+
},
64+
},
65+
],
66+
},
67+
...minimizeTrait,
68+
};
69+
70+
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+
};

0 commit comments

Comments
 (0)