@openapi-qraft/plugin 1.13.0-beta.2 → 1.14.0-beta.0

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/lib/QraftCommand.d.ts.map +1 -1
  3. package/dist/lib/QraftCommand.js +27 -8
  4. package/dist/lib/QraftCommand.js.map +1 -1
  5. package/dist/lib/createServicePathMatch.d.ts +0 -9
  6. package/dist/lib/createServicePathMatch.d.ts.map +1 -1
  7. package/dist/lib/createServicePathMatch.js +0 -15
  8. package/dist/lib/createServicePathMatch.js.map +1 -1
  9. package/dist/lib/filterDocumentPaths.d.ts +1 -1
  10. package/dist/lib/filterDocumentPaths.d.ts.map +1 -1
  11. package/dist/lib/filterDocumentPaths.js +1 -1
  12. package/dist/lib/filterDocumentPaths.js.map +1 -1
  13. package/dist/lib/parseOperationGlobs.d.ts +17 -0
  14. package/dist/lib/parseOperationGlobs.d.ts.map +1 -0
  15. package/dist/lib/parseOperationGlobs.js +37 -0
  16. package/dist/lib/parseOperationGlobs.js.map +1 -0
  17. package/dist/lib/predefineSchemaParameters.d.ts +15 -11
  18. package/dist/lib/predefineSchemaParameters.d.ts.map +1 -1
  19. package/dist/lib/predefineSchemaParameters.js +50 -30
  20. package/dist/lib/predefineSchemaParameters.js.map +1 -1
  21. package/dist/lib/processOperationNameModifierOption.d.ts +57 -0
  22. package/dist/lib/processOperationNameModifierOption.d.ts.map +1 -0
  23. package/dist/lib/processOperationNameModifierOption.js +102 -0
  24. package/dist/lib/processOperationNameModifierOption.js.map +1 -0
  25. package/dist/lib/splitCommaSeparatedGlobs.d.ts +7 -0
  26. package/dist/lib/splitCommaSeparatedGlobs.d.ts.map +1 -0
  27. package/dist/lib/splitCommaSeparatedGlobs.js +16 -0
  28. package/dist/lib/splitCommaSeparatedGlobs.js.map +1 -0
  29. package/package.json +3 -3
  30. package/src/lib/QraftCommand.ts +59 -10
  31. package/src/lib/createServicePathMatch.ts +0 -18
  32. package/src/lib/filterDocumentPaths.ts +2 -2
  33. package/src/lib/parseOperationGlobs.ts +54 -0
  34. package/src/lib/predefineSchemaParameters.ts +108 -71
  35. package/src/lib/processOperationNameModifierOption.ts +205 -0
  36. package/src/lib/splitCommaSeparatedGlobs.ts +16 -0
@@ -0,0 +1,205 @@
1
+ import { createServicePathMatch } from './createServicePathMatch.js';
2
+ import { Service } from './open-api/getServices.js';
3
+ import {
4
+ OperationGlobMethods,
5
+ parseOperationGlobs,
6
+ } from './parseOperationGlobs.js';
7
+ import { splitCommaSeparatedGlobs } from './splitCommaSeparatedGlobs.js';
8
+
9
+ export const processOperationNameModifierOption = (
10
+ modifiers: OperationNameModifier[],
11
+ services: Service[]
12
+ ) => {
13
+ if (!modifiers.length)
14
+ return {
15
+ errors: [],
16
+ services,
17
+ };
18
+
19
+ const operationNameModifiers = modifiers.map((modifier) => ({
20
+ ...modifier,
21
+ isPathMatch: createServicePathMatch(
22
+ splitCommaSeparatedGlobs(modifier.pathGlobs)
23
+ ),
24
+ }));
25
+
26
+ type ServiceName = string;
27
+ type ReplacedOperationNameMap = string;
28
+ type OriginalOperationName = string;
29
+
30
+ const serviceOperationReplacements = new Map<
31
+ ServiceName,
32
+ Map<
33
+ ReplacedOperationNameMap,
34
+ Map<OriginalOperationName, OperationNameModifier[]>
35
+ >
36
+ >();
37
+
38
+ const replacedOperationNamesServices = services.map((service) => {
39
+ serviceOperationReplacements.set(service.name, new Map());
40
+
41
+ return {
42
+ ...service,
43
+ operations: service.operations.map((operation) => {
44
+ const operationReplacements = serviceOperationReplacements.get(
45
+ service.name
46
+ );
47
+
48
+ if (!operationReplacements)
49
+ throw new Error('operationReplacements not found');
50
+
51
+ const operationModifiers = operationNameModifiers.filter(
52
+ (modifier) =>
53
+ modifier.isPathMatch(operation.path) &&
54
+ (modifier.methods === undefined ||
55
+ modifier.methods.includes(operation.method)) &&
56
+ normalizeOperationNameModifierRegex(
57
+ modifier.operationNameModifierRegex
58
+ ).test(operation.name)
59
+ );
60
+
61
+ const replacedOperationName = operationModifiers.reduce<string>(
62
+ (operationName, modifier) =>
63
+ operationName.replace(
64
+ normalizeOperationNameModifierRegex(
65
+ modifier.operationNameModifierRegex
66
+ ),
67
+ modifier.operationNameModifierReplace
68
+ ),
69
+ operation.name
70
+ );
71
+
72
+ if (replacedOperationName !== operation.name) {
73
+ if (!operationReplacements.has(replacedOperationName))
74
+ operationReplacements.set(replacedOperationName, new Map());
75
+ operationReplacements.get(replacedOperationName)?.set(
76
+ operation.name,
77
+ operationModifiers.map(
78
+ ({ isPathMatch: _, ...operationModifiersRest }) =>
79
+ operationModifiersRest
80
+ )
81
+ );
82
+ }
83
+
84
+ return {
85
+ ...operation,
86
+ name: replacedOperationName,
87
+ };
88
+ }),
89
+ };
90
+ });
91
+
92
+ const errors = Array.from(serviceOperationReplacements).flatMap(
93
+ ([serviceName, modifiedOperations]) =>
94
+ Array.from(modifiedOperations).flatMap(
95
+ ([replacedOperationName, operationModifierMap]) => {
96
+ if (operationModifierMap.size > 1) {
97
+ return Array.from(operationModifierMap).map(
98
+ ([originalOperationName, modifiers]) => ({
99
+ serviceName,
100
+ replacedOperationName,
101
+ originalOperationName,
102
+ modifiers,
103
+ })
104
+ );
105
+ }
106
+
107
+ const [originalOperationName, modifiers] =
108
+ Array.from(operationModifierMap).at(0) ?? [];
109
+
110
+ if (modifiers && modifiers.length > 1) {
111
+ return [
112
+ {
113
+ serviceName,
114
+ replacedOperationName,
115
+ originalOperationName,
116
+ modifiers,
117
+ },
118
+ ];
119
+ }
120
+
121
+ return [];
122
+ }
123
+ )
124
+ );
125
+
126
+ return {
127
+ errors,
128
+ services: replacedOperationNamesServices,
129
+ };
130
+ };
131
+
132
+ function normalizeOperationNameModifierRegex(regex: string) {
133
+ return new RegExp(regex, 'g');
134
+ }
135
+
136
+ export type OperationNameModifier = {
137
+ methods: OperationGlobMethods[] | undefined;
138
+ /**
139
+ * Glob pattern to match service paths, eg: `/foo,/bar/**`
140
+ */
141
+ pathGlobs: string;
142
+ /**
143
+ * Regular expression to match operation names
144
+ */
145
+ operationNameModifierRegex: string;
146
+ /**
147
+ * Replacement string for matched operation names
148
+ */
149
+ operationNameModifierReplace: string;
150
+ };
151
+
152
+ /**
153
+ * Parses the given options string into a structured format.
154
+ *
155
+ * @param optionItems - The configuration string to parse. Eg. `/foo,/bar/**:post[A-Z][A-Za-z]+sId[A-Z][A-Za-z]+ ==> createOne` or `post /** ==> createOne`
156
+ * @returns The parsed configuration.
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * const parsedConfig = parseOperationNameModifier("/foo,/bar/**:/**:post[A-Z][A-Za-z]+sId[A-Z][A-Za-z]+ ==> createOne");
161
+ * ```
162
+ */
163
+ export function parseOperationNameModifier(
164
+ ...optionItems: string[]
165
+ ): OperationNameModifier[] {
166
+ const globOperationNameModifierMap: Array<OperationNameModifier> = [];
167
+
168
+ for (const optionItem of optionItems) {
169
+ const operationGlobsRaw = optionItem.slice(
170
+ 0,
171
+ Math.max(0, optionItem.indexOf(':'))
172
+ );
173
+
174
+ if (!operationGlobsRaw.length)
175
+ throw new Error(
176
+ `Invalid operation name modifier: ${optionItem}. Must be in the format of 'pathGlobs:operationNameModifierRegex ==> operationNameModifierReplace'`
177
+ );
178
+
179
+ const modifierPattern = optionItem.slice(operationGlobsRaw.length + 1);
180
+
181
+ const patternRegex = modifierPattern.slice(
182
+ 0,
183
+ modifierPattern.indexOf('==>')
184
+ );
185
+ const patternReplace = modifierPattern.slice(
186
+ modifierPattern.indexOf('==>') + '==>'.length + 1
187
+ );
188
+
189
+ const { methods, pathGlobs } = parseOperationGlobs(operationGlobsRaw);
190
+
191
+ if (!splitCommaSeparatedGlobs(pathGlobs).length)
192
+ throw new Error(
193
+ `Invalid path glob: ${pathGlobs}. Must be a comma-separated list of globs.`
194
+ );
195
+
196
+ globOperationNameModifierMap.push({
197
+ methods,
198
+ pathGlobs,
199
+ operationNameModifierRegex: patternRegex.trim(),
200
+ operationNameModifierReplace: patternReplace.trim(),
201
+ });
202
+ }
203
+
204
+ return globOperationNameModifierMap;
205
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Normalize a comma-separated list of globs
3
+ * @param commaSeparatedGlobs - Example: `/foo , /bar/**, ,`
4
+ * @returns Example: `/foo,/bar/**`
5
+ */
6
+ export function splitCommaSeparatedGlobs(
7
+ commaSeparatedGlobs: string | undefined
8
+ ): string[] {
9
+ if (commaSeparatedGlobs === undefined) return [];
10
+ if (typeof commaSeparatedGlobs !== 'string') throw new Error('Invalid input');
11
+
12
+ return commaSeparatedGlobs
13
+ .split(',')
14
+ .map((path) => path.trim())
15
+ .filter(Boolean);
16
+ }