@obsidiane/meridiane 1.0.1 → 2.0.1
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/README.md +8 -5
- package/cli.js +7 -11
- package/package.json +1 -1
- package/templates/_lib_template/README.md +194 -0
- package/templates/_lib_template/ng-package.json +3 -0
- package/tools/build.js +6 -5
- package/tools/core/generate.js +40 -24
- package/tools/core/paths.js +0 -7
- package/tools/dev.js +6 -5
- package/tools/generator/models/oas-contract.js +159 -0
- package/tools/generator/models/oas-schema-name.js +71 -0
- package/tools/generator/models/openapi-to-models.js +171 -378
- package/tools/generator/models/schema-utils.js +3 -100
- package/tools/generator/models/templates/model.hbs +3 -1
- package/tools/generator/models/type-resolver.js +6 -3
- package/tools/generator/models/naming.js +0 -26
|
@@ -13,10 +13,11 @@ export function isObject(v) {
|
|
|
13
13
|
/**
|
|
14
14
|
* Extrait le nom du schéma depuis une référence $ref
|
|
15
15
|
* @param {string} $ref
|
|
16
|
+
* @returns {string|undefined}
|
|
16
17
|
*/
|
|
17
18
|
export function schemaNameFromRef($ref) {
|
|
18
19
|
const m = $ref.match(/#\/components\/schemas\/(.+)$/);
|
|
19
|
-
return m ? m[1] :
|
|
20
|
+
return m ? m[1] : undefined;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -31,7 +32,7 @@ export function mergeAllOf(schemas) {
|
|
|
31
32
|
for (const s of schemas) {
|
|
32
33
|
if (s.$ref) {
|
|
33
34
|
const ref = schemaNameFromRef(s.$ref);
|
|
34
|
-
if (HYDRA_BASE_RE.test(ref)) {
|
|
35
|
+
if (ref && HYDRA_BASE_RE.test(ref)) {
|
|
35
36
|
continue;
|
|
36
37
|
}
|
|
37
38
|
return null;
|
|
@@ -46,101 +47,3 @@ export function mergeAllOf(schemas) {
|
|
|
46
47
|
out.required = [...new Set(out.required)];
|
|
47
48
|
return out;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Liste les noms de schémas dans `components.schemas`.
|
|
52
|
-
* La sélection/filtres est gérée par `applySchemaNameFilters`.
|
|
53
|
-
* @param {Record<string, any>} schemas
|
|
54
|
-
* @returns {string[]}
|
|
55
|
-
*/
|
|
56
|
-
export function filterSchemaNames(schemas, cfg) {
|
|
57
|
-
return Object.keys(schemas).sort((a, b) => a.localeCompare(b));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @param {unknown} rule
|
|
62
|
-
* @returns {rule is ((name: string) => boolean)}
|
|
63
|
-
*/
|
|
64
|
-
function isRuleFn(rule) {
|
|
65
|
-
return typeof rule === 'function';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @param {string} name
|
|
70
|
-
* @param {RegExp|string|((name: string) => boolean)} rule
|
|
71
|
-
*/
|
|
72
|
-
function matchesRule(name, rule) {
|
|
73
|
-
if (rule instanceof RegExp) return rule.test(name);
|
|
74
|
-
if (isRuleFn(rule)) return !!rule(name);
|
|
75
|
-
if (typeof rule === 'string' && rule.length) return name.includes(rule);
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Applique un preset de génération et/ou des règles include/exclude.
|
|
81
|
-
*
|
|
82
|
-
* - `preset: "all"`: ne filtre rien (comportement par défaut)
|
|
83
|
-
* - `preset: "native"`: retire les schémas "techniques" (Hydra*, jsonMergePatch…)
|
|
84
|
-
*
|
|
85
|
-
* Les règles `includeSchemaNames` / `excludeSchemaNames` s'appliquent sur les noms
|
|
86
|
-
* de schémas OpenAPI (ex: "User-user.read", "Conversation.jsonMergePatch", …).
|
|
87
|
-
*
|
|
88
|
-
* @param {string[]} schemaNames
|
|
89
|
-
* @param {{
|
|
90
|
-
* preset?: 'all'|'native',
|
|
91
|
-
* includeSchemaNames?: Array<RegExp|string|((name: string) => boolean)>,
|
|
92
|
-
* excludeSchemaNames?: Array<RegExp|string|((name: string) => boolean)>,
|
|
93
|
-
* }} [cfg]
|
|
94
|
-
*/
|
|
95
|
-
export function applySchemaNameFilters(schemaNames, cfg) {
|
|
96
|
-
const preset = cfg?.preset ?? 'all';
|
|
97
|
-
|
|
98
|
-
/** @type {Array<RegExp|string|((name: string) => boolean)>} */
|
|
99
|
-
const include = Array.isArray(cfg?.includeSchemaNames) ? cfg.includeSchemaNames : [];
|
|
100
|
-
/** @type {Array<RegExp|string|((name: string) => boolean)>} */
|
|
101
|
-
const exclude = Array.isArray(cfg?.excludeSchemaNames) ? [...cfg.excludeSchemaNames] : [];
|
|
102
|
-
|
|
103
|
-
// 1) include/exclude user filters (always applied first)
|
|
104
|
-
const hasInclude = include.length > 0;
|
|
105
|
-
let out = schemaNames.filter((name) => {
|
|
106
|
-
if (hasInclude && !include.some((r) => matchesRule(name, r))) return false;
|
|
107
|
-
if (exclude.some((r) => matchesRule(name, r))) return false;
|
|
108
|
-
return true;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// 2) preset filters
|
|
112
|
-
if (preset === 'native') {
|
|
113
|
-
out = out
|
|
114
|
-
.filter((n) => !/^Hydra/i.test(n))
|
|
115
|
-
// API Platform adds a technical "Multipart" schema for multipart/form-data request bodies (file uploads).
|
|
116
|
-
// It's not a resource model and tends to pollute the generated "native" model list.
|
|
117
|
-
.filter((n) => !/^Multipart(?:$|[.-])/i.test(n))
|
|
118
|
-
.filter((n) => !/jsonMergePatch/i.test(n))
|
|
119
|
-
.filter((n) => !/\.jsonld\b/i.test(n))
|
|
120
|
-
.filter((n) => !/\.jsonapi\b/i.test(n));
|
|
121
|
-
|
|
122
|
-
// 3) collapse group variants: keep one schema per base (before `-`)
|
|
123
|
-
const score = (name) => {
|
|
124
|
-
if (!name.includes('-')) return 100;
|
|
125
|
-
const group = name.split('-').slice(1).join('-');
|
|
126
|
-
if (/(^|[.\-])read($|[.\-])/i.test(group)) return 50;
|
|
127
|
-
return 0;
|
|
128
|
-
};
|
|
129
|
-
const byBase = new Map();
|
|
130
|
-
for (const name of out) {
|
|
131
|
-
const base = name.split('-')[0];
|
|
132
|
-
const prev = byBase.get(base);
|
|
133
|
-
if (!prev) {
|
|
134
|
-
byBase.set(base, name);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const a = prev, b = name;
|
|
138
|
-
const sa = score(a), sb = score(b);
|
|
139
|
-
if (sb > sa) byBase.set(base, b);
|
|
140
|
-
else if (sb === sa && b.localeCompare(a) < 0) byBase.set(base, b);
|
|
141
|
-
}
|
|
142
|
-
out = [...byBase.values()].sort((a, b) => a.localeCompare(b));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return out;
|
|
146
|
-
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
{{#if extendsItem}}
|
|
1
2
|
import type { Item } from '../lib/ports/resource-repository.port';
|
|
3
|
+
{{/if}}
|
|
2
4
|
{{#each imports}}
|
|
3
5
|
import type { {{this}} } from './{{this}}';
|
|
4
6
|
{{/each}}
|
|
5
7
|
|
|
6
|
-
export interface {{name}} extends Item{{#each extendsTypes}}, {{this}}{{/each}} {
|
|
8
|
+
export interface {{name}}{{#if extendsItem}} extends Item{{#each extendsTypes}}, {{this}}{{/each}}{{else}}{{#each extendsTypes}}{{#if @first}} extends {{this}}{{else}}, {{this}}{{/if}}{{/each}}{{/if}} {
|
|
7
9
|
{{#each props}}
|
|
8
10
|
{{{tsKey}}}{{#if optional}}?{{/if}}: {{type}};
|
|
9
11
|
{{/each}}
|
|
@@ -16,16 +16,19 @@ export function withNullable(ts, schema) {
|
|
|
16
16
|
* @param {any} schema
|
|
17
17
|
* @param {Set<string>} deps
|
|
18
18
|
* @param {Map<string,string>} nameMap
|
|
19
|
-
* @param {{ requiredMode?: 'all
|
|
19
|
+
* @param {{ requiredMode?: 'all'|'spec' }} [cfg]
|
|
20
20
|
* @returns {string}
|
|
21
21
|
*/
|
|
22
22
|
export function tsTypeOf(schema, deps, nameMap, cfg) {
|
|
23
23
|
if (!schema) return 'any';
|
|
24
|
-
const requiredMode = cfg?.requiredMode ?? 'all
|
|
25
|
-
const forceNullable =
|
|
24
|
+
const requiredMode = cfg?.requiredMode ?? 'all';
|
|
25
|
+
const forceNullable = requiredMode !== 'spec';
|
|
26
26
|
|
|
27
27
|
if (schema.$ref) {
|
|
28
28
|
const orig = schemaNameFromRef(schema.$ref);
|
|
29
|
+
if (!orig) return 'any';
|
|
30
|
+
if (/jsonMergePatch/i.test(orig)) return 'any';
|
|
31
|
+
if (/^Hydra/i.test(orig)) return 'any';
|
|
29
32
|
const name = nameMap.get(orig) || orig;
|
|
30
33
|
deps.add(name);
|
|
31
34
|
return name;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Construit un label "tokenisé" (sans `.` ni `-`) à partir d'un nom de schéma OpenAPI.
|
|
3
|
-
* Le label est ensuite passé à `sanitizeTypeName()` pour produire un identifiant TS stable.
|
|
4
|
-
*
|
|
5
|
-
* @param {string} original
|
|
6
|
-
* @param {{ preset: 'all'|'native' }} cfg
|
|
7
|
-
*/
|
|
8
|
-
export function schemaLabel(original, cfg) {
|
|
9
|
-
const preset = cfg?.preset ?? 'all';
|
|
10
|
-
if (preset === 'native') {
|
|
11
|
-
// En native, on vise un nom "entity-like" : on ignore le groupe (après `-`) si présent.
|
|
12
|
-
// Les variantes .jsonld/.jsonapi/jsonMergePatch sont censées être filtrées par le preset.
|
|
13
|
-
return String(original).split('-')[0];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// En all, on encode tout : `.` et `-` deviennent des séparateurs de tokens.
|
|
17
|
-
const rawTokens = String(original).split(/[.-]/g).filter(Boolean);
|
|
18
|
-
const tokens = rawTokens.map((t) => {
|
|
19
|
-
const lower = t.toLowerCase();
|
|
20
|
-
if (lower === 'jsonld') return 'Jsonld';
|
|
21
|
-
if (lower === 'jsonapi') return 'Jsonapi';
|
|
22
|
-
if (lower === 'jsonmergepatch' || t === 'jsonMergePatch') return 'JsonMergePatch';
|
|
23
|
-
return t;
|
|
24
|
-
});
|
|
25
|
-
return tokens.join(' ');
|
|
26
|
-
}
|