@webda/content-mapper 0.0.0-stage → 4.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +166 -0
- package/lib/coercions.d.ts +22 -0
- package/lib/coercions.d.ts.map +1 -0
- package/lib/coercions.js +10 -0
- package/lib/coercions.js.map +1 -0
- package/lib/context.d.ts +56 -0
- package/lib/context.d.ts.map +1 -0
- package/lib/context.js +111 -0
- package/lib/context.js.map +1 -0
- package/lib/defaults.d.ts +31 -0
- package/lib/defaults.d.ts.map +1 -0
- package/lib/defaults.js +33 -0
- package/lib/defaults.js.map +1 -0
- package/lib/generators/accessors.d.ts +15 -0
- package/lib/generators/accessors.d.ts.map +1 -0
- package/lib/generators/accessors.js +567 -0
- package/lib/generators/accessors.js.map +1 -0
- package/lib/generators/behaviors.d.ts +21 -0
- package/lib/generators/behaviors.d.ts.map +1 -0
- package/lib/generators/behaviors.js +292 -0
- package/lib/generators/behaviors.js.map +1 -0
- package/lib/generators/imports.d.ts +86 -0
- package/lib/generators/imports.d.ts.map +1 -0
- package/lib/generators/imports.js +205 -0
- package/lib/generators/imports.js.map +1 -0
- package/lib/generators/loadparameters.d.ts +7 -0
- package/lib/generators/loadparameters.d.ts.map +1 -0
- package/lib/generators/loadparameters.js +175 -0
- package/lib/generators/loadparameters.js.map +1 -0
- package/lib/generators/qlvalidator.d.ts +53 -0
- package/lib/generators/qlvalidator.d.ts.map +1 -0
- package/lib/generators/qlvalidator.js +238 -0
- package/lib/generators/qlvalidator.js.map +1 -0
- package/lib/index.d.ts +53 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +36 -0
- package/lib/index.js.map +1 -0
- package/lib/module-discovery.d.ts +211 -0
- package/lib/module-discovery.d.ts.map +1 -0
- package/lib/module-discovery.js +662 -0
- package/lib/module-discovery.js.map +1 -0
- package/lib/module.d.ts +213 -0
- package/lib/module.d.ts.map +1 -0
- package/lib/module.js +1243 -0
- package/lib/module.js.map +1 -0
- package/lib/plan.d.ts +101 -0
- package/lib/plan.d.ts.map +1 -0
- package/lib/plan.js +61 -0
- package/lib/plan.js.map +1 -0
- package/lib/property-order.d.ts +37 -0
- package/lib/property-order.d.ts.map +1 -0
- package/lib/property-order.js +141 -0
- package/lib/property-order.js.map +1 -0
- package/lib/schema/action.d.ts +46 -0
- package/lib/schema/action.d.ts.map +1 -0
- package/lib/schema/action.js +190 -0
- package/lib/schema/action.js.map +1 -0
- package/lib/schema/annotations.d.ts +63 -0
- package/lib/schema/annotations.d.ts.map +1 -0
- package/lib/schema/annotations.js +116 -0
- package/lib/schema/annotations.js.map +1 -0
- package/lib/schema/converter.d.ts +363 -0
- package/lib/schema/converter.d.ts.map +1 -0
- package/lib/schema/converter.js +1377 -0
- package/lib/schema/converter.js.map +1 -0
- package/lib/schema/jsdoc.d.ts +34 -0
- package/lib/schema/jsdoc.d.ts.map +1 -0
- package/lib/schema/jsdoc.js +206 -0
- package/lib/schema/jsdoc.js.map +1 -0
- package/lib/schema/model.d.ts +27 -0
- package/lib/schema/model.d.ts.map +1 -0
- package/lib/schema/model.js +86 -0
- package/lib/schema/model.js.map +1 -0
- package/lib/schema/project.d.ts +34 -0
- package/lib/schema/project.d.ts.map +1 -0
- package/lib/schema/project.js +305 -0
- package/lib/schema/project.js.map +1 -0
- package/lib/schema/service.d.ts +62 -0
- package/lib/schema/service.d.ts.map +1 -0
- package/lib/schema/service.js +130 -0
- package/lib/schema/service.js.map +1 -0
- package/lib/schema/types.d.ts +61 -0
- package/lib/schema/types.d.ts.map +1 -0
- package/lib/schema/types.js +36 -0
- package/lib/schema/types.js.map +1 -0
- package/lib/schema/worker-cli.d.ts +3 -0
- package/lib/schema/worker-cli.d.ts.map +1 -0
- package/lib/schema/worker-cli.js +7 -0
- package/lib/schema/worker-cli.js.map +1 -0
- package/lib/schema/worker.d.ts +81 -0
- package/lib/schema/worker.d.ts.map +1 -0
- package/lib/schema/worker.js +186 -0
- package/lib/schema/worker.js.map +1 -0
- package/lib/server.d.ts +2 -0
- package/lib/server.d.ts.map +1 -0
- package/lib/server.js +133 -0
- package/lib/server.js.map +1 -0
- package/lib/session.d.ts +84 -0
- package/lib/session.d.ts.map +1 -0
- package/lib/session.js +141 -0
- package/lib/session.js.map +1 -0
- package/lib/spans.d.ts +46 -0
- package/lib/spans.d.ts.map +1 -0
- package/lib/spans.js +64 -0
- package/lib/spans.js.map +1 -0
- package/lib/twopass.d.ts +45 -0
- package/lib/twopass.d.ts.map +1 -0
- package/lib/twopass.js +87 -0
- package/lib/twopass.js.map +1 -0
- package/lib/vite.d.ts +20 -0
- package/lib/vite.d.ts.map +1 -0
- package/lib/vite.js +41 -0
- package/lib/vite.js.map +1 -0
- package/package.json +93 -3
- package/README.md +0 -3
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action schemas — the `<Class>.<method>.input` and `.output` entries in the
|
|
3
|
+
* top-level `schemas` map.
|
|
4
|
+
*
|
|
5
|
+
* An `@Action` or `@Operation` method gets two schemas describing its call:
|
|
6
|
+
* one for the arguments, one for what it resolves to. They are built very
|
|
7
|
+
* differently, and the asymmetry is visible in the committed artefact:
|
|
8
|
+
*
|
|
9
|
+
* - `.input` is a **hand-built** object whose properties are one generated
|
|
10
|
+
* document per parameter, each stripped of its `$schema`. The root never
|
|
11
|
+
* passed through the converter, so it has no `$schema`, no
|
|
12
|
+
* `additionalProperties`, and its keys stay in declaration order.
|
|
13
|
+
* - `.output` **is** a generated document, `$schema` and all, taken from the
|
|
14
|
+
* resolved return type.
|
|
15
|
+
*
|
|
16
|
+
* Both are then flattened by {@link normalizeDefinitions}.
|
|
17
|
+
*/
|
|
18
|
+
import { SignatureKind, SymbolFlags } from "typescript/unstable/sync";
|
|
19
|
+
import * as is from "typescript/unstable/ast/is";
|
|
20
|
+
import { SchemaConverter } from "./converter.js";
|
|
21
|
+
/**
|
|
22
|
+
* Schema for an action's arguments.
|
|
23
|
+
*
|
|
24
|
+
* Every parameter is included — there is no filter for `context` / `ctx`, so
|
|
25
|
+
* an `OperationContext` argument is expanded in full. That is odd for
|
|
26
|
+
* something called an operation *input*, and it is what the committed
|
|
27
|
+
* artefact contains, so it is reproduced rather than improved here.
|
|
28
|
+
* @param method - the decorated method
|
|
29
|
+
* @param options - project and checker
|
|
30
|
+
* @returns the arguments schema
|
|
31
|
+
*/
|
|
32
|
+
export function generateActionInput(method, options) {
|
|
33
|
+
const { checker, project } = options;
|
|
34
|
+
const signature = callSignatureOf(method, options);
|
|
35
|
+
// Hand-built, not converted: this root is why `.input` carries no
|
|
36
|
+
// `$schema` and keeps its keys in declaration order.
|
|
37
|
+
const schema = { type: "object", properties: {} };
|
|
38
|
+
const required = [];
|
|
39
|
+
for (const parameter of signature?.getParameters() ?? []) {
|
|
40
|
+
const converter = new SchemaConverter({ project, checker, mode: "input" });
|
|
41
|
+
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, method.parent);
|
|
42
|
+
const parameterSchema = converter.fromType(parameterType, method.parent);
|
|
43
|
+
delete parameterSchema.$schema;
|
|
44
|
+
schema.properties[parameter.name] = parameterSchema;
|
|
45
|
+
if (!isOptionalParameter(parameter, project))
|
|
46
|
+
required.push(parameter.name);
|
|
47
|
+
}
|
|
48
|
+
// Omitted entirely when empty, and in declaration order rather than sorted
|
|
49
|
+
// — unlike every `required` the converter itself produces.
|
|
50
|
+
if (required.length > 0)
|
|
51
|
+
schema.required = required;
|
|
52
|
+
return normalizeDefinitions(schema);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Schema for what an action resolves to.
|
|
56
|
+
* @param method - the decorated method
|
|
57
|
+
* @param options - project and checker
|
|
58
|
+
* @returns the return schema, or undefined when it cannot be resolved
|
|
59
|
+
*/
|
|
60
|
+
export function generateActionOutput(method, options) {
|
|
61
|
+
const { checker, project } = options;
|
|
62
|
+
const signature = callSignatureOf(method, options, true);
|
|
63
|
+
if (!signature)
|
|
64
|
+
return undefined;
|
|
65
|
+
const returned = checker.getReturnTypeOfSignature(signature);
|
|
66
|
+
const resolved = unwrapPromise(returned, checker);
|
|
67
|
+
if (!resolved)
|
|
68
|
+
return undefined;
|
|
69
|
+
const converter = new SchemaConverter({ project, checker, mode: "output" });
|
|
70
|
+
return normalizeDefinitions(converter.fromType(resolved, method.parent));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The first call signature of a method.
|
|
74
|
+
* @param method - the method declaration
|
|
75
|
+
* @param options - project and checker
|
|
76
|
+
* @param apparent - resolve through the apparent type, as the output path does
|
|
77
|
+
* @returns the signature, when the method has one
|
|
78
|
+
*/
|
|
79
|
+
function callSignatureOf(method, options, apparent = false) {
|
|
80
|
+
const { checker } = options;
|
|
81
|
+
const methodType = checker.getTypeAtLocation(method);
|
|
82
|
+
const source = apparent ? checker.getApparentType(methodType) : methodType;
|
|
83
|
+
return checker.getSignaturesOfType(source, SignatureKind.Call)[0];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Unwrap one level of `Promise<T>`.
|
|
87
|
+
*
|
|
88
|
+
* Matched by symbol name, as `@webda/compiler` does — which means a class of
|
|
89
|
+
* your own called `Promise` is unwrapped too.
|
|
90
|
+
* @param type - the declared return type
|
|
91
|
+
* @param checker - the resident checker
|
|
92
|
+
* @returns the awaited type, or the original
|
|
93
|
+
*/
|
|
94
|
+
function unwrapPromise(type, checker) {
|
|
95
|
+
if (type.getSymbol()?.name !== "Promise" || !type.isTypeReference())
|
|
96
|
+
return type;
|
|
97
|
+
const args = checker.getTypeArguments(type);
|
|
98
|
+
return args.length > 0 ? args[0] : type;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Whether a parameter may be omitted at the call site.
|
|
102
|
+
* @param parameter - the parameter symbol
|
|
103
|
+
* @param project - project used to resolve declaration handles
|
|
104
|
+
* @returns true when optional or defaulted
|
|
105
|
+
*/
|
|
106
|
+
function isOptionalParameter(parameter, project) {
|
|
107
|
+
if ((parameter.flags & SymbolFlags.Optional) !== 0)
|
|
108
|
+
return true;
|
|
109
|
+
return parameter.declarations.some(handle => {
|
|
110
|
+
const declaration = handle.resolve(project);
|
|
111
|
+
if (!declaration || !is.isParameterDeclaration(declaration))
|
|
112
|
+
return false;
|
|
113
|
+
return declaration.questionToken !== undefined || declaration.initializer !== undefined;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Hoist every nested `definitions` block to the root and drop dangling refs.
|
|
118
|
+
*
|
|
119
|
+
* Applied to action schemas only. Two real failures motivate it, both of
|
|
120
|
+
* which crash AJV rather than merely looking untidy: a bound generic keeps
|
|
121
|
+
* its `definitions` on a sub-schema where a root-relative `$ref` cannot see
|
|
122
|
+
* it, and an unbound generic produces a definition whose key does not match
|
|
123
|
+
* the `$ref` pointing at it. Hoisting fixes the first; pruning the `$ref` —
|
|
124
|
+
* leaving an unconstrained `{}` — contains the second.
|
|
125
|
+
* Accepts any JSON value: the guard against non-objects is deliberate, so
|
|
126
|
+
* callers never have to check before flattening.
|
|
127
|
+
* @param schema - the schema to flatten, mutated in place
|
|
128
|
+
* @returns the same value
|
|
129
|
+
* @typeParam T - the value type, preserved
|
|
130
|
+
*/
|
|
131
|
+
export function normalizeDefinitions(schema) {
|
|
132
|
+
if (!schema || typeof schema !== "object")
|
|
133
|
+
return schema;
|
|
134
|
+
const target = schema;
|
|
135
|
+
const collected = {};
|
|
136
|
+
const collect = (node) => {
|
|
137
|
+
if (!node || typeof node !== "object")
|
|
138
|
+
return;
|
|
139
|
+
if (Array.isArray(node)) {
|
|
140
|
+
node.forEach(collect);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const record = node;
|
|
144
|
+
if (record.definitions && typeof record.definitions === "object") {
|
|
145
|
+
for (const [key, value] of Object.entries(record.definitions)) {
|
|
146
|
+
// First writer wins: sibling definitions sharing a key describe the
|
|
147
|
+
// same type, because the key is the type's own name.
|
|
148
|
+
collected[key] ??= value;
|
|
149
|
+
}
|
|
150
|
+
delete record.definitions;
|
|
151
|
+
}
|
|
152
|
+
for (const key of Object.keys(record)) {
|
|
153
|
+
if (key === "$ref")
|
|
154
|
+
continue;
|
|
155
|
+
collect(record[key]);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
collect(target);
|
|
159
|
+
if (Object.keys(collected).length > 0)
|
|
160
|
+
target.definitions = { ...target.definitions, ...collected };
|
|
161
|
+
const resolvable = (ref) => {
|
|
162
|
+
if (!ref.startsWith("#/definitions/"))
|
|
163
|
+
return true;
|
|
164
|
+
const raw = ref.slice("#/definitions/".length);
|
|
165
|
+
let decoded = raw;
|
|
166
|
+
try {
|
|
167
|
+
decoded = decodeURIComponent(raw);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
decoded = raw;
|
|
171
|
+
}
|
|
172
|
+
return raw in collected || decoded in collected;
|
|
173
|
+
};
|
|
174
|
+
const prune = (node) => {
|
|
175
|
+
if (!node || typeof node !== "object")
|
|
176
|
+
return;
|
|
177
|
+
if (Array.isArray(node)) {
|
|
178
|
+
node.forEach(prune);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const record = node;
|
|
182
|
+
if (typeof record.$ref === "string" && !resolvable(record.$ref))
|
|
183
|
+
delete record.$ref;
|
|
184
|
+
for (const key of Object.keys(record))
|
|
185
|
+
prune(record[key]);
|
|
186
|
+
};
|
|
187
|
+
prune(target);
|
|
188
|
+
return schema;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../../src/schema/action.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSDoc-to-JSON-Schema annotation mapping.
|
|
3
|
+
*
|
|
4
|
+
* Webda lets a JSDoc tag set a schema keyword directly — `@minimum 0`,
|
|
5
|
+
* `@format email`, `@deprecated` — and the committed `webda.module.json`
|
|
6
|
+
* contains the results, so the classification below is not a design choice but
|
|
7
|
+
* a compatibility surface. It reproduces `@webda/schema`'s `Annotations` table
|
|
8
|
+
* and `processJsDoc` exactly, including the behaviours that look like bugs:
|
|
9
|
+
*
|
|
10
|
+
* - an unclassified tag becomes a keyword of its own name, so `@see` and
|
|
11
|
+
* `@returns` end up in the schema, and `@type number | string` **overwrites**
|
|
12
|
+
* the structural `type`
|
|
13
|
+
* - a repeated tag collects into an array
|
|
14
|
+
* - a tag with no text becomes `true`
|
|
15
|
+
*
|
|
16
|
+
* Those are all present in the committed output. Diverging from them is a
|
|
17
|
+
* schema change, not a fix, so it does not belong in this port.
|
|
18
|
+
*/
|
|
19
|
+
import type { Checker, Project, Symbol as TsSymbol } from "typescript/unstable/sync";
|
|
20
|
+
import type { JSONSchema7 } from "./types.ts";
|
|
21
|
+
/** How a JSDoc tag name maps onto a JSON Schema keyword. */
|
|
22
|
+
export declare const Annotations: {
|
|
23
|
+
/** Emitted with a `$` prefix — `@id x` becomes `$id: "x"`. */
|
|
24
|
+
readonly dollarPrefixed: readonly ["id", "comment", "ref"];
|
|
25
|
+
/** Presence alone sets the keyword to `true`; any text is discarded. */
|
|
26
|
+
readonly boolean: readonly ["deprecated", "readOnly", "writeOnly", "exclusiveMinimum", "exclusiveMaximum"];
|
|
27
|
+
/** Tag text is copied verbatim as a string. */
|
|
28
|
+
readonly string: readonly ["title", "description", "id", "format", "pattern", "ref", "comment", "contentMediaType", "contentEncoding", "discriminator", "markdownDescription", "deprecationMessage"];
|
|
29
|
+
};
|
|
30
|
+
/** A JSDoc comment and its tags, already rendered to text. */
|
|
31
|
+
export interface SymbolDocs {
|
|
32
|
+
/** The free-text comment, empty when absent. */
|
|
33
|
+
comment: string;
|
|
34
|
+
/** Tags in declaration order. */
|
|
35
|
+
tags: {
|
|
36
|
+
name: string;
|
|
37
|
+
text: string;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read a symbol's JSDoc comment and tags.
|
|
42
|
+
*
|
|
43
|
+
* Tags come straight from the checker; the comment is resolved by
|
|
44
|
+
* {@link documentationOf}, which reproduces behaviour the 7.1 API dropped —
|
|
45
|
+
* see `jsdoc.ts`.
|
|
46
|
+
* @param symbol - the symbol to document
|
|
47
|
+
* @param checker - the checker resolving the documentation
|
|
48
|
+
* @param project - project used to resolve declaration handles
|
|
49
|
+
* @returns comment text and tags
|
|
50
|
+
*/
|
|
51
|
+
export declare function readDocs(symbol: TsSymbol, checker: Checker, project: Project): SymbolDocs;
|
|
52
|
+
/**
|
|
53
|
+
* Merge a symbol's JSDoc into a schema, in place.
|
|
54
|
+
*
|
|
55
|
+
* Applied in three passes so that the precedence matches `@webda/schema`:
|
|
56
|
+
* string tags, then boolean tags, then everything else.
|
|
57
|
+
* @param definition - the schema to enrich
|
|
58
|
+
* @param symbol - the symbol whose JSDoc to read; a no-op when undefined
|
|
59
|
+
* @param checker - the checker resolving the documentation
|
|
60
|
+
* @param project - project used to resolve declaration handles
|
|
61
|
+
*/
|
|
62
|
+
export declare function applyDocs(definition: JSONSchema7, symbol: TsSymbol | undefined, checker: Checker, project: Project): void;
|
|
63
|
+
//# sourceMappingURL=annotations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/schema/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAErF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,4DAA4D;AAC5D,eAAO,MAAM,WAAW;IACtB,8DAA8D;aAC9D,cAAc,YAAG,IAAI,EAAE,SAAS,EAAE,KAAK;IACvC,wEAAwE;aACxE,OAAO,YAAG,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,kBAAkB;IACvF,+CAA+C;aAC/C,MAAM,YACJ,OAAO,EACP,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,KAAK,EAEL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EAEjB,eAAe,EACf,qBAAqB,EACrB,oBAAoB;CAEd,CAAC;AAuBX,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,CAOzF;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,WAAW,EACvB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACf,IAAI,CAoCN"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { documentationOf } from "./jsdoc.js";
|
|
2
|
+
/** How a JSDoc tag name maps onto a JSON Schema keyword. */
|
|
3
|
+
export const Annotations = {
|
|
4
|
+
/** Emitted with a `$` prefix — `@id x` becomes `$id: "x"`. */
|
|
5
|
+
dollarPrefixed: ["id", "comment", "ref"],
|
|
6
|
+
/** Presence alone sets the keyword to `true`; any text is discarded. */
|
|
7
|
+
boolean: ["deprecated", "readOnly", "writeOnly", "exclusiveMinimum", "exclusiveMaximum"],
|
|
8
|
+
/** Tag text is copied verbatim as a string. */
|
|
9
|
+
string: [
|
|
10
|
+
"title",
|
|
11
|
+
"description",
|
|
12
|
+
"id",
|
|
13
|
+
"format",
|
|
14
|
+
"pattern",
|
|
15
|
+
"ref",
|
|
16
|
+
// Draft-07 additions.
|
|
17
|
+
"comment",
|
|
18
|
+
"contentMediaType",
|
|
19
|
+
"contentEncoding",
|
|
20
|
+
// Webda extensions.
|
|
21
|
+
"discriminator",
|
|
22
|
+
"markdownDescription",
|
|
23
|
+
"deprecationMessage"
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Tags whose payload TypeScript consumes as a type expression, braces or not.
|
|
28
|
+
*
|
|
29
|
+
* `parseEnumTag` and `parseThisTag` call `parseJSDocTypeExpression` with
|
|
30
|
+
* `mayOmitBraces: true`, so `@enum ["draft", "published"]` parses the array
|
|
31
|
+
* as a *type* and leaves the comment empty. The 6.x services layer reported
|
|
32
|
+
* that empty text; 7.1 hands back the raw payload instead.
|
|
33
|
+
*
|
|
34
|
+
* Reproducing 6.x here is deliberate. Webda's annotation layer turns an
|
|
35
|
+
* unrecognised tag into a keyword of its own name, so the raw payload would
|
|
36
|
+
* start populating `enum` — which is arguably what the author meant, and is
|
|
37
|
+
* also a behaviour change that produces nonsense where the union already
|
|
38
|
+
* supplied an `enum` (the two get concatenated). It belongs in its own
|
|
39
|
+
* commit, not in a port whose contract is byte-identical output.
|
|
40
|
+
*
|
|
41
|
+
* `@type` is deliberately absent: `parseTypeTag` requires braces, so
|
|
42
|
+
* `@type number | string` keeps its text in both versions — and the
|
|
43
|
+
* committed schemas contain it.
|
|
44
|
+
*/
|
|
45
|
+
const TYPE_EXPRESSION_TAGS = ["enum", "this"];
|
|
46
|
+
/**
|
|
47
|
+
* Read a symbol's JSDoc comment and tags.
|
|
48
|
+
*
|
|
49
|
+
* Tags come straight from the checker; the comment is resolved by
|
|
50
|
+
* {@link documentationOf}, which reproduces behaviour the 7.1 API dropped —
|
|
51
|
+
* see `jsdoc.ts`.
|
|
52
|
+
* @param symbol - the symbol to document
|
|
53
|
+
* @param checker - the checker resolving the documentation
|
|
54
|
+
* @param project - project used to resolve declaration handles
|
|
55
|
+
* @returns comment text and tags
|
|
56
|
+
*/
|
|
57
|
+
export function readDocs(symbol, checker, project) {
|
|
58
|
+
return {
|
|
59
|
+
comment: documentationOf(symbol, checker, project),
|
|
60
|
+
tags: symbol
|
|
61
|
+
.getJsDocTags(checker)
|
|
62
|
+
.map(tag => ({ name: tag.name, text: TYPE_EXPRESSION_TAGS.includes(tag.name) ? "" : (tag.text ?? "") }))
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Merge a symbol's JSDoc into a schema, in place.
|
|
67
|
+
*
|
|
68
|
+
* Applied in three passes so that the precedence matches `@webda/schema`:
|
|
69
|
+
* string tags, then boolean tags, then everything else.
|
|
70
|
+
* @param definition - the schema to enrich
|
|
71
|
+
* @param symbol - the symbol whose JSDoc to read; a no-op when undefined
|
|
72
|
+
* @param checker - the checker resolving the documentation
|
|
73
|
+
* @param project - project used to resolve declaration handles
|
|
74
|
+
*/
|
|
75
|
+
export function applyDocs(definition, symbol, checker, project) {
|
|
76
|
+
if (!symbol)
|
|
77
|
+
return;
|
|
78
|
+
const docs = readDocs(symbol, checker, project);
|
|
79
|
+
const target = definition;
|
|
80
|
+
if (docs.comment)
|
|
81
|
+
target.description = docs.comment;
|
|
82
|
+
for (const tag of docs.tags) {
|
|
83
|
+
if (!Annotations.string.includes(tag.name))
|
|
84
|
+
continue;
|
|
85
|
+
target[Annotations.dollarPrefixed.includes(tag.name) ? `$${tag.name}` : tag.name] = tag.text;
|
|
86
|
+
}
|
|
87
|
+
for (const tag of docs.tags) {
|
|
88
|
+
if (Annotations.boolean.includes(tag.name))
|
|
89
|
+
target[tag.name] = true;
|
|
90
|
+
}
|
|
91
|
+
for (const tag of docs.tags) {
|
|
92
|
+
if (Annotations.boolean.includes(tag.name) || Annotations.string.includes(tag.name))
|
|
93
|
+
continue;
|
|
94
|
+
let value;
|
|
95
|
+
try {
|
|
96
|
+
value = JSON.parse(tag.text);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
value = tag.text === "" ? true : tag.text;
|
|
100
|
+
}
|
|
101
|
+
// Truthiness, not `!== undefined`: a falsy existing value is overwritten
|
|
102
|
+
// rather than collected. `@webda/schema` does the same, and the committed
|
|
103
|
+
// schemas were generated that way.
|
|
104
|
+
const existing = target[tag.name];
|
|
105
|
+
if (Array.isArray(existing)) {
|
|
106
|
+
existing.push(value);
|
|
107
|
+
}
|
|
108
|
+
else if (existing) {
|
|
109
|
+
target[tag.name] = [existing, value];
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
target[tag.name] = value;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=annotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/schema/annotations.ts"],"names":[],"mappings":"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"}
|