@abapify/openai-codegen 0.4.33 → 0.4.36
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 +15 -324
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +20 -9
- package/dist/cli.mjs.map +1 -1
- package/dist/{generate-DgXsowgP.mjs → generate-BevNTSFF.mjs} +534 -475
- package/dist/generate-BevNTSFF.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +31 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/generate-DgXsowgP.mjs.map +0 -1
|
@@ -166,77 +166,91 @@ function normalizeSecuritySchemes(raw) {
|
|
|
166
166
|
if (!isRecord$4(raw)) return out;
|
|
167
167
|
for (const [name, schemeRaw] of Object.entries(raw)) {
|
|
168
168
|
if (!isRecord$4(schemeRaw)) continue;
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
switch (type) {
|
|
172
|
-
case "apiKey": {
|
|
173
|
-
const inLoc = asString(schemeRaw.in);
|
|
174
|
-
if (inLoc !== "header" && inLoc !== "query" && inLoc !== "cookie") continue;
|
|
175
|
-
const scheme = {
|
|
176
|
-
type: "apiKey",
|
|
177
|
-
name: asString(schemeRaw.name) ?? name,
|
|
178
|
-
in: inLoc
|
|
179
|
-
};
|
|
180
|
-
if (description !== void 0) scheme.description = description;
|
|
181
|
-
out[name] = scheme;
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
case "http": {
|
|
185
|
-
const scheme = {
|
|
186
|
-
type: "http",
|
|
187
|
-
scheme: asString(schemeRaw.scheme) ?? "bearer"
|
|
188
|
-
};
|
|
189
|
-
const bf = asString(schemeRaw.bearerFormat);
|
|
190
|
-
if (bf !== void 0) scheme.bearerFormat = bf;
|
|
191
|
-
if (description !== void 0) scheme.description = description;
|
|
192
|
-
out[name] = scheme;
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
case "oauth2": {
|
|
196
|
-
const flowsRaw = isRecord$4(schemeRaw.flows) ? schemeRaw.flows : {};
|
|
197
|
-
const scheme = {
|
|
198
|
-
type: "oauth2",
|
|
199
|
-
flows: {}
|
|
200
|
-
};
|
|
201
|
-
for (const flowName of [
|
|
202
|
-
"implicit",
|
|
203
|
-
"password",
|
|
204
|
-
"clientCredentials",
|
|
205
|
-
"authorizationCode"
|
|
206
|
-
]) {
|
|
207
|
-
const f = flowsRaw[flowName];
|
|
208
|
-
if (!isRecord$4(f)) continue;
|
|
209
|
-
const flow = { scopes: {} };
|
|
210
|
-
if (isRecord$4(f.scopes)) {
|
|
211
|
-
for (const [k, v] of Object.entries(f.scopes)) if (typeof v === "string") flow.scopes[k] = v;
|
|
212
|
-
}
|
|
213
|
-
const au = asString(f.authorizationUrl);
|
|
214
|
-
if (au !== void 0) flow.authorizationUrl = au;
|
|
215
|
-
const tu = asString(f.tokenUrl);
|
|
216
|
-
if (tu !== void 0) flow.tokenUrl = tu;
|
|
217
|
-
const ru = asString(f.refreshUrl);
|
|
218
|
-
if (ru !== void 0) flow.refreshUrl = ru;
|
|
219
|
-
scheme.flows[flowName] = flow;
|
|
220
|
-
}
|
|
221
|
-
if (description !== void 0) scheme.description = description;
|
|
222
|
-
out[name] = scheme;
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
case "openIdConnect": {
|
|
226
|
-
const url = asString(schemeRaw.openIdConnectUrl);
|
|
227
|
-
if (url === void 0) continue;
|
|
228
|
-
const scheme = {
|
|
229
|
-
type: "openIdConnect",
|
|
230
|
-
openIdConnectUrl: url
|
|
231
|
-
};
|
|
232
|
-
if (description !== void 0) scheme.description = description;
|
|
233
|
-
out[name] = scheme;
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
169
|
+
const scheme = normalizeSecurityScheme(name, schemeRaw);
|
|
170
|
+
if (scheme !== void 0) out[name] = scheme;
|
|
237
171
|
}
|
|
238
172
|
return out;
|
|
239
173
|
}
|
|
174
|
+
function normalizeSecurityScheme(name, schemeRaw) {
|
|
175
|
+
const type = asString(schemeRaw.type);
|
|
176
|
+
let scheme;
|
|
177
|
+
switch (type) {
|
|
178
|
+
case "apiKey":
|
|
179
|
+
scheme = normalizeApiKeyScheme(name, schemeRaw);
|
|
180
|
+
break;
|
|
181
|
+
case "http":
|
|
182
|
+
scheme = normalizeHttpScheme(schemeRaw);
|
|
183
|
+
break;
|
|
184
|
+
case "oauth2":
|
|
185
|
+
scheme = normalizeOAuth2Scheme(schemeRaw);
|
|
186
|
+
break;
|
|
187
|
+
case "openIdConnect":
|
|
188
|
+
scheme = normalizeOpenIdConnectScheme(schemeRaw);
|
|
189
|
+
break;
|
|
190
|
+
default: scheme = void 0;
|
|
191
|
+
}
|
|
192
|
+
if (scheme === void 0) return void 0;
|
|
193
|
+
const description = asString(schemeRaw.description);
|
|
194
|
+
if (description !== void 0) scheme.description = description;
|
|
195
|
+
return scheme;
|
|
196
|
+
}
|
|
197
|
+
function normalizeApiKeyScheme(name, raw) {
|
|
198
|
+
const inLoc = asString(raw.in);
|
|
199
|
+
if (inLoc !== "header" && inLoc !== "query" && inLoc !== "cookie") return;
|
|
200
|
+
return {
|
|
201
|
+
type: "apiKey",
|
|
202
|
+
name: asString(raw.name) ?? name,
|
|
203
|
+
in: inLoc
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function normalizeHttpScheme(raw) {
|
|
207
|
+
const scheme = {
|
|
208
|
+
type: "http",
|
|
209
|
+
scheme: asString(raw.scheme) ?? "bearer"
|
|
210
|
+
};
|
|
211
|
+
const bf = asString(raw.bearerFormat);
|
|
212
|
+
if (bf !== void 0) scheme.bearerFormat = bf;
|
|
213
|
+
return scheme;
|
|
214
|
+
}
|
|
215
|
+
function normalizeOAuth2Scheme(raw) {
|
|
216
|
+
const flowsRaw = isRecord$4(raw.flows) ? raw.flows : {};
|
|
217
|
+
const scheme = {
|
|
218
|
+
type: "oauth2",
|
|
219
|
+
flows: {}
|
|
220
|
+
};
|
|
221
|
+
for (const flowName of [
|
|
222
|
+
"implicit",
|
|
223
|
+
"password",
|
|
224
|
+
"clientCredentials",
|
|
225
|
+
"authorizationCode"
|
|
226
|
+
]) {
|
|
227
|
+
const f = flowsRaw[flowName];
|
|
228
|
+
if (!isRecord$4(f)) continue;
|
|
229
|
+
scheme.flows[flowName] = normalizeOAuth2Flow(f);
|
|
230
|
+
}
|
|
231
|
+
return scheme;
|
|
232
|
+
}
|
|
233
|
+
function normalizeOAuth2Flow(f) {
|
|
234
|
+
const flow = { scopes: {} };
|
|
235
|
+
if (isRecord$4(f.scopes)) {
|
|
236
|
+
for (const [k, v] of Object.entries(f.scopes)) if (typeof v === "string") flow.scopes[k] = v;
|
|
237
|
+
}
|
|
238
|
+
const au = asString(f.authorizationUrl);
|
|
239
|
+
if (au !== void 0) flow.authorizationUrl = au;
|
|
240
|
+
const tu = asString(f.tokenUrl);
|
|
241
|
+
if (tu !== void 0) flow.tokenUrl = tu;
|
|
242
|
+
const ru = asString(f.refreshUrl);
|
|
243
|
+
if (ru !== void 0) flow.refreshUrl = ru;
|
|
244
|
+
return flow;
|
|
245
|
+
}
|
|
246
|
+
function normalizeOpenIdConnectScheme(raw) {
|
|
247
|
+
const url = asString(raw.openIdConnectUrl);
|
|
248
|
+
if (url === void 0) return void 0;
|
|
249
|
+
return {
|
|
250
|
+
type: "openIdConnect",
|
|
251
|
+
openIdConnectUrl: url
|
|
252
|
+
};
|
|
253
|
+
}
|
|
240
254
|
function normalizeSecurityRequirements(raw) {
|
|
241
255
|
return asArray(raw).filter(isRecord$4).map((req) => {
|
|
242
256
|
const out = {};
|
|
@@ -253,28 +267,31 @@ function normalizeOperations(pathsRaw, topLevelSecurity) {
|
|
|
253
267
|
for (const method of HTTP_METHODS) {
|
|
254
268
|
const opRaw = pathItemRaw[method];
|
|
255
269
|
if (!isRecord$4(opRaw)) continue;
|
|
256
|
-
|
|
257
|
-
const op = {
|
|
258
|
-
operationId: asString(opRaw.operationId) ?? synthesizeOperationId(method, path),
|
|
259
|
-
method,
|
|
260
|
-
path,
|
|
261
|
-
tags: asStringArray(opRaw.tags),
|
|
262
|
-
deprecated: asBool(opRaw.deprecated, false),
|
|
263
|
-
parameters,
|
|
264
|
-
responses: normalizeResponses(opRaw.responses),
|
|
265
|
-
security: opRaw.security === void 0 ? topLevelSecurity : normalizeSecurityRequirements(opRaw.security)
|
|
266
|
-
};
|
|
267
|
-
const summary = asString(opRaw.summary);
|
|
268
|
-
if (summary !== void 0) op.summary = summary;
|
|
269
|
-
const description = asString(opRaw.description);
|
|
270
|
-
if (description !== void 0) op.description = description;
|
|
271
|
-
const requestBody = normalizeRequestBody(opRaw.requestBody);
|
|
272
|
-
if (requestBody !== void 0) op.requestBody = requestBody;
|
|
273
|
-
ops.push(op);
|
|
270
|
+
ops.push(buildOperation(method, path, opRaw, pathLevelParams, topLevelSecurity));
|
|
274
271
|
}
|
|
275
272
|
}
|
|
276
273
|
return ops;
|
|
277
274
|
}
|
|
275
|
+
function buildOperation(method, path, opRaw, pathLevelParams, topLevelSecurity) {
|
|
276
|
+
const parameters = mergeParameters(pathLevelParams, normalizeParameters(opRaw.parameters));
|
|
277
|
+
const op = {
|
|
278
|
+
operationId: asString(opRaw.operationId) ?? synthesizeOperationId(method, path),
|
|
279
|
+
method,
|
|
280
|
+
path,
|
|
281
|
+
tags: asStringArray(opRaw.tags),
|
|
282
|
+
deprecated: asBool(opRaw.deprecated, false),
|
|
283
|
+
parameters,
|
|
284
|
+
responses: normalizeResponses(opRaw.responses),
|
|
285
|
+
security: opRaw.security === void 0 ? topLevelSecurity : normalizeSecurityRequirements(opRaw.security)
|
|
286
|
+
};
|
|
287
|
+
const summary = asString(opRaw.summary);
|
|
288
|
+
if (summary !== void 0) op.summary = summary;
|
|
289
|
+
const description = asString(opRaw.description);
|
|
290
|
+
if (description !== void 0) op.description = description;
|
|
291
|
+
const requestBody = normalizeRequestBody(opRaw.requestBody);
|
|
292
|
+
if (requestBody !== void 0) op.requestBody = requestBody;
|
|
293
|
+
return op;
|
|
294
|
+
}
|
|
278
295
|
function normalizeParameters(raw) {
|
|
279
296
|
return asArray(raw).filter(isRecord$4).map((p) => {
|
|
280
297
|
const inLoc = asString(p.in);
|
|
@@ -303,16 +320,19 @@ function mergeParameters(pathLevel, opLevel) {
|
|
|
303
320
|
for (const p of opLevel) merged.set(key(p), p);
|
|
304
321
|
return [...merged.values()];
|
|
305
322
|
}
|
|
306
|
-
function
|
|
307
|
-
if (!isRecord$4(raw)) return void 0;
|
|
323
|
+
function normalizeContentMap(raw) {
|
|
308
324
|
const content = {};
|
|
309
|
-
if (isRecord$4(raw
|
|
325
|
+
if (isRecord$4(raw)) for (const [mt, mtRaw] of Object.entries(raw)) {
|
|
310
326
|
if (!isRecord$4(mtRaw)) continue;
|
|
311
327
|
content[mt] = { schema: isRecord$4(mtRaw.schema) ? mtRaw.schema : {} };
|
|
312
328
|
}
|
|
329
|
+
return content;
|
|
330
|
+
}
|
|
331
|
+
function normalizeRequestBody(raw) {
|
|
332
|
+
if (!isRecord$4(raw)) return void 0;
|
|
313
333
|
const body = {
|
|
314
334
|
required: asBool(raw.required, false),
|
|
315
|
-
content
|
|
335
|
+
content: normalizeContentMap(raw.content)
|
|
316
336
|
};
|
|
317
337
|
const desc = asString(raw.description);
|
|
318
338
|
if (desc !== void 0) body.description = desc;
|
|
@@ -322,37 +342,40 @@ function normalizeResponses(raw) {
|
|
|
322
342
|
if (!isRecord$4(raw)) return [];
|
|
323
343
|
const entries = Object.entries(raw).filter((entry) => isRecord$4(entry[1]));
|
|
324
344
|
const has2xx = entries.some(([code]) => /^2\d\d$/.test(code));
|
|
325
|
-
return entries.map(([statusCode, respRaw]) =>
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
function
|
|
345
|
+
return entries.map(([statusCode, respRaw]) => normalizeResponse(statusCode, respRaw, has2xx));
|
|
346
|
+
}
|
|
347
|
+
function normalizeResponse(statusCode, respRaw, has2xx) {
|
|
348
|
+
const resp = {
|
|
349
|
+
statusCode,
|
|
350
|
+
isSuccess: /^2\d\d$/.test(statusCode) || statusCode === "default" && !has2xx,
|
|
351
|
+
isError: /^[45]\d\d$/.test(statusCode) || statusCode === "default" && has2xx,
|
|
352
|
+
content: normalizeContentMap(respRaw.content),
|
|
353
|
+
headers: normalizeResponseHeaders(respRaw.headers)
|
|
354
|
+
};
|
|
355
|
+
const desc = asString(respRaw.description);
|
|
356
|
+
if (desc !== void 0) resp.description = desc;
|
|
357
|
+
return resp;
|
|
358
|
+
}
|
|
359
|
+
function normalizeResponseHeaders(raw) {
|
|
360
|
+
const headers = {};
|
|
361
|
+
if (isRecord$4(raw)) for (const [hn, hRaw] of Object.entries(raw)) {
|
|
362
|
+
if (!isRecord$4(hRaw)) continue;
|
|
363
|
+
headers[hn] = normalizeHeader(hRaw);
|
|
364
|
+
}
|
|
365
|
+
return headers;
|
|
366
|
+
}
|
|
367
|
+
function normalizeHeader(hRaw) {
|
|
368
|
+
const header = { schema: isRecord$4(hRaw.schema) ? hRaw.schema : {} };
|
|
369
|
+
const desc = asString(hRaw.description);
|
|
370
|
+
if (desc !== void 0) header.description = desc;
|
|
371
|
+
if (typeof hRaw.required === "boolean") header.required = hRaw.required;
|
|
372
|
+
if (typeof hRaw.deprecated === "boolean") header.deprecated = hRaw.deprecated;
|
|
373
|
+
return header;
|
|
374
|
+
}
|
|
375
|
+
function isAlnumChar(ch) {
|
|
376
|
+
return ch >= "A" && ch <= "Z" || ch >= "a" && ch <= "z" || ch >= "0" && ch <= "9";
|
|
377
|
+
}
|
|
378
|
+
function sanitizePathChars(path) {
|
|
356
379
|
const out = [];
|
|
357
380
|
let underscore = false;
|
|
358
381
|
let braceDepth = 0;
|
|
@@ -365,7 +388,7 @@ function synthesizeOperationId(method, path) {
|
|
|
365
388
|
if (braceDepth > 0) braceDepth -= 1;
|
|
366
389
|
continue;
|
|
367
390
|
}
|
|
368
|
-
if (ch
|
|
391
|
+
if (isAlnumChar(ch)) {
|
|
369
392
|
out.push(ch);
|
|
370
393
|
underscore = false;
|
|
371
394
|
} else if (!underscore) {
|
|
@@ -373,6 +396,10 @@ function synthesizeOperationId(method, path) {
|
|
|
373
396
|
underscore = true;
|
|
374
397
|
}
|
|
375
398
|
}
|
|
399
|
+
return out;
|
|
400
|
+
}
|
|
401
|
+
function synthesizeOperationId(method, path) {
|
|
402
|
+
const out = sanitizePathChars(path);
|
|
376
403
|
let start = 0;
|
|
377
404
|
let end = out.length;
|
|
378
405
|
while (start < end && out[start] === "_") start += 1;
|
|
@@ -408,7 +435,7 @@ function sanitizeIdent(raw, kind, opts = {}) {
|
|
|
408
435
|
if (kind === "class") base = words.map((w) => w.toUpperCase()).join(joiner);
|
|
409
436
|
else base = words.map((w) => w.toLowerCase()).join(joiner);
|
|
410
437
|
if (!base) base = kind === "class" ? "X" : "x";
|
|
411
|
-
if (
|
|
438
|
+
if (/^\d/.test(base)) base = (kind === "class" ? "N_" : "n_") + base;
|
|
412
439
|
let full = prefix + base;
|
|
413
440
|
if (full.length > maxLen) {
|
|
414
441
|
const suffix = "_" + shortHash(raw, 4);
|
|
@@ -487,67 +514,86 @@ function isNonTrivialInline(schema) {
|
|
|
487
514
|
*/
|
|
488
515
|
function collectFromSchema(rootId, rootSchema, plannedIds, enqueueInline, schemaToId) {
|
|
489
516
|
const deps = /* @__PURE__ */ new Set();
|
|
517
|
+
const ctx = {
|
|
518
|
+
rootId,
|
|
519
|
+
deps,
|
|
520
|
+
plannedIds,
|
|
521
|
+
enqueueInline,
|
|
522
|
+
schemaToId
|
|
523
|
+
};
|
|
490
524
|
const visit = (schema, path, atRoot) => {
|
|
491
525
|
if (!isRecord$3(schema)) return;
|
|
492
|
-
if (
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
526
|
+
if (classifyVisit(schema, path, atRoot, ctx)) return;
|
|
527
|
+
descendSchema(schema, path, visit);
|
|
528
|
+
};
|
|
529
|
+
visit(rootSchema, [], true);
|
|
530
|
+
return [...deps];
|
|
531
|
+
}
|
|
532
|
+
/** Classify a non-trivial schema node: register a dep (or inline entry) and
|
|
533
|
+
* report whether descent should stop. */
|
|
534
|
+
function classifyVisit(schema, path, atRoot, ctx) {
|
|
535
|
+
const { rootId, deps, schemaToId } = ctx;
|
|
536
|
+
if (isRef(schema)) {
|
|
537
|
+
const name = componentNameFromRef$2(schema.$ref);
|
|
538
|
+
if (name) {
|
|
539
|
+
const depId = `components.schemas.${name}`;
|
|
540
|
+
deps.add(depId);
|
|
499
541
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
deps.add(rootId);
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
if (!atRoot) {
|
|
545
|
+
const hitId = schemaToId.get(schema);
|
|
546
|
+
if (hitId && hitId !== rootId) {
|
|
547
|
+
deps.add(hitId);
|
|
548
|
+
return true;
|
|
510
549
|
}
|
|
511
|
-
if (
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
enqueueInline(id, schema);
|
|
515
|
-
schemaToId.set(schema, id);
|
|
516
|
-
}
|
|
517
|
-
deps.add(id);
|
|
518
|
-
return;
|
|
550
|
+
if (hitId === rootId) {
|
|
551
|
+
deps.add(rootId);
|
|
552
|
+
return true;
|
|
519
553
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
"properties",
|
|
524
|
-
name
|
|
525
|
-
], false);
|
|
526
|
-
if (rec.items !== void 0) visit(rec.items, [...path, "items"], false);
|
|
527
|
-
if (isRecord$3(rec.additionalProperties)) visit(rec.additionalProperties, [...path, "additionalProperties"], false);
|
|
528
|
-
for (const c of [
|
|
529
|
-
"allOf",
|
|
530
|
-
"anyOf",
|
|
531
|
-
"oneOf"
|
|
532
|
-
]) {
|
|
533
|
-
const arr = rec[c];
|
|
534
|
-
if (Array.isArray(arr)) arr.forEach((sub, idx) => {
|
|
535
|
-
visit(sub, [
|
|
536
|
-
...path,
|
|
537
|
-
c,
|
|
538
|
-
String(idx)
|
|
539
|
-
], false);
|
|
540
|
-
});
|
|
554
|
+
if (isNonTrivialInline(schema)) {
|
|
555
|
+
deps.add(registerInlineEntry(schema, path, ctx));
|
|
556
|
+
return true;
|
|
541
557
|
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
|
|
558
|
+
}
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
function registerInlineEntry(schema, path, ctx) {
|
|
562
|
+
const { rootId, plannedIds, enqueueInline, schemaToId } = ctx;
|
|
563
|
+
const id = `${rootId}.${path.join(".")}`;
|
|
564
|
+
if (!plannedIds.has(id)) {
|
|
565
|
+
enqueueInline(id, schema);
|
|
566
|
+
schemaToId.set(schema, id);
|
|
567
|
+
}
|
|
568
|
+
return id;
|
|
569
|
+
}
|
|
570
|
+
function descendSchema(schema, path, visit) {
|
|
571
|
+
if (isRecord$3(schema.properties)) for (const [name, sub] of Object.entries(schema.properties)) visit(sub, [
|
|
572
|
+
...path,
|
|
573
|
+
"properties",
|
|
574
|
+
name
|
|
575
|
+
], false);
|
|
576
|
+
if (schema.items !== void 0) visit(schema.items, [...path, "items"], false);
|
|
577
|
+
if (isRecord$3(schema.additionalProperties)) visit(schema.additionalProperties, [...path, "additionalProperties"], false);
|
|
578
|
+
for (const c of [
|
|
579
|
+
"allOf",
|
|
580
|
+
"anyOf",
|
|
581
|
+
"oneOf"
|
|
582
|
+
]) {
|
|
583
|
+
const arr = schema[c];
|
|
584
|
+
if (Array.isArray(arr)) arr.forEach((sub, idx) => {
|
|
585
|
+
visit(sub, [
|
|
586
|
+
...path,
|
|
587
|
+
c,
|
|
588
|
+
String(idx)
|
|
589
|
+
], false);
|
|
590
|
+
});
|
|
591
|
+
}
|
|
545
592
|
}
|
|
546
593
|
/** Plan the ABAP type universe for a normalized spec. */
|
|
547
594
|
function planTypes(spec, opts) {
|
|
548
595
|
const alloc = makeNameAllocator(/* @__PURE__ */ new Set());
|
|
549
596
|
const entries = [];
|
|
550
|
-
const byId = /* @__PURE__ */ new Map();
|
|
551
597
|
const plannedIds = /* @__PURE__ */ new Set();
|
|
552
598
|
const schemaToId = /* @__PURE__ */ new Map();
|
|
553
599
|
const queue = [];
|
|
@@ -573,15 +619,13 @@ function planTypes(spec, opts) {
|
|
|
573
619
|
source: item.source
|
|
574
620
|
};
|
|
575
621
|
entries.push(entry);
|
|
576
|
-
byId.set(item.id, entry);
|
|
577
622
|
entry.dependencies = collectFromSchema(item.id, item.schema, plannedIds, (id, schema) => {
|
|
578
623
|
enqueue(id, schema, "inline");
|
|
579
624
|
}, schemaToId);
|
|
580
625
|
}
|
|
581
626
|
if (entries.some((e) => hasOpenAdditional(e.schema))) {
|
|
582
|
-
const kvId = "aux.kv";
|
|
583
627
|
const kvEntry = {
|
|
584
|
-
id:
|
|
628
|
+
id: "aux.kv",
|
|
585
629
|
abapName: alloc("kv", "type", { prefix: "ty_" + (opts.typePrefix ?? "") }),
|
|
586
630
|
schema: {
|
|
587
631
|
type: "object",
|
|
@@ -594,7 +638,6 @@ function planTypes(spec, opts) {
|
|
|
594
638
|
source: "auxiliary"
|
|
595
639
|
};
|
|
596
640
|
entries.push(kvEntry);
|
|
597
|
-
byId.set(kvId, kvEntry);
|
|
598
641
|
}
|
|
599
642
|
const sorted = topoSort(entries);
|
|
600
643
|
return {
|
|
@@ -636,16 +679,7 @@ function topoSort(entries) {
|
|
|
636
679
|
const entry = byId.get(id);
|
|
637
680
|
if (!entry) return;
|
|
638
681
|
if (s === "gray") {
|
|
639
|
-
|
|
640
|
-
const cycle = cycleStart >= 0 ? stack.slice(cycleStart) : [id];
|
|
641
|
-
if (cycle.length === 1) {
|
|
642
|
-
entry.selfReferential = true;
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
for (const pid of cycle) {
|
|
646
|
-
const ent = byId.get(pid);
|
|
647
|
-
if (ent) ent.selfReferential = true;
|
|
648
|
-
}
|
|
682
|
+
markCycleParticipants(id, stack, byId, entry);
|
|
649
683
|
return;
|
|
650
684
|
}
|
|
651
685
|
state.set(id, "gray");
|
|
@@ -657,12 +691,7 @@ function topoSort(entries) {
|
|
|
657
691
|
}
|
|
658
692
|
if (!byId.has(dep)) continue;
|
|
659
693
|
if (state.get(dep) === "gray") {
|
|
660
|
-
|
|
661
|
-
const cycle = cycleStart >= 0 ? stack.slice(cycleStart) : [dep];
|
|
662
|
-
for (const pid of [...cycle, id]) {
|
|
663
|
-
const ent = byId.get(pid);
|
|
664
|
-
if (ent) ent.selfReferential = true;
|
|
665
|
-
}
|
|
694
|
+
markBackEdgeCycle(dep, id, stack, byId);
|
|
666
695
|
continue;
|
|
667
696
|
}
|
|
668
697
|
visit(dep, stack);
|
|
@@ -675,6 +704,30 @@ function topoSort(entries) {
|
|
|
675
704
|
if (out.length !== entries.length) throw new CyclicTypeError(`planTypes: unable to topologically sort ${entries.length} entries (got ${out.length}).`);
|
|
676
705
|
return out;
|
|
677
706
|
}
|
|
707
|
+
/** Mark the participants of a cycle discovered on a gray node and allow the
|
|
708
|
+
* traversal to continue — the emitter will insert a TYPE REF TO indirection
|
|
709
|
+
* for the back edge. */
|
|
710
|
+
function markCycleParticipants(id, stack, byId, entry) {
|
|
711
|
+
const cycleStart = stack.indexOf(id);
|
|
712
|
+
const cycle = cycleStart >= 0 ? stack.slice(cycleStart) : [id];
|
|
713
|
+
if (cycle.length === 1) {
|
|
714
|
+
entry.selfReferential = true;
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
for (const pid of cycle) {
|
|
718
|
+
const ent = byId.get(pid);
|
|
719
|
+
if (ent) ent.selfReferential = true;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
/** Mark participants of a back-edge cycle (dep already on the gray stack). */
|
|
723
|
+
function markBackEdgeCycle(dep, id, stack, byId) {
|
|
724
|
+
const cycleStart = stack.indexOf(dep);
|
|
725
|
+
const cycle = cycleStart >= 0 ? stack.slice(cycleStart) : [dep];
|
|
726
|
+
for (const pid of [...cycle, id]) {
|
|
727
|
+
const ent = byId.get(pid);
|
|
728
|
+
if (ent) ent.selfReferential = true;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
678
731
|
|
|
679
732
|
// src/types/map.ts
|
|
680
733
|
function isRecord$2(x) {
|
|
@@ -719,11 +772,7 @@ function isNullable$1(schema) {
|
|
|
719
772
|
}
|
|
720
773
|
/** Resolve a schema to an ABAP TypeRef. */
|
|
721
774
|
function mapSchemaToTypeRef(schema, plan, ctx = {}) {
|
|
722
|
-
if (isRef(schema))
|
|
723
|
-
const entry = refToEntry(schema.$ref, plan);
|
|
724
|
-
if (!entry) throw new UnsupportedSchemaError(`mapSchemaToTypeRef: unresolved $ref "${schema.$ref}"`);
|
|
725
|
-
return namedTypeRef({ name: entry.abapName });
|
|
726
|
-
}
|
|
775
|
+
if (isRef(schema)) return refTypeRef(schema.$ref, plan);
|
|
727
776
|
const type = pluckType$2(schema);
|
|
728
777
|
if (type === "array") {
|
|
729
778
|
const items = schema.items;
|
|
@@ -733,26 +782,33 @@ function mapSchemaToTypeRef(schema, plan, ctx = {}) {
|
|
|
733
782
|
tableKind: "standard"
|
|
734
783
|
});
|
|
735
784
|
}
|
|
736
|
-
if (type === "object" || isRecord$2(schema.properties))
|
|
785
|
+
if (type === "object" || isRecord$2(schema.properties)) return objectTypeRef(schema, plan, ctx);
|
|
786
|
+
if (type === void 0) return untypedTypeRef(schema, plan, ctx);
|
|
787
|
+
return builtinType({ name: mapPrimitive(schema) });
|
|
788
|
+
}
|
|
789
|
+
function refTypeRef(ref, plan) {
|
|
790
|
+
const entry = refToEntry(ref, plan);
|
|
791
|
+
if (!entry) throw new UnsupportedSchemaError(`mapSchemaToTypeRef: unresolved $ref "${ref}"`);
|
|
792
|
+
return namedTypeRef({ name: entry.abapName });
|
|
793
|
+
}
|
|
794
|
+
function objectTypeRef(schema, plan, ctx) {
|
|
795
|
+
const matched = findPlannedEntryBySchema$1(schema, plan, ctx.entryId);
|
|
796
|
+
if (matched) return namedTypeRef({ name: matched.abapName });
|
|
797
|
+
const fields = buildStructureFields$1(schema, plan, ctx);
|
|
798
|
+
if (fields.length === 0) return builtinType({ name: "string" });
|
|
799
|
+
return structureType({ fields });
|
|
800
|
+
}
|
|
801
|
+
function untypedTypeRef(schema, plan, ctx) {
|
|
802
|
+
for (const c of [
|
|
803
|
+
"allOf",
|
|
804
|
+
"oneOf",
|
|
805
|
+
"anyOf"
|
|
806
|
+
]) if (Array.isArray(schema[c])) {
|
|
737
807
|
const matched = findPlannedEntryBySchema$1(schema, plan, ctx.entryId);
|
|
738
808
|
if (matched) return namedTypeRef({ name: matched.abapName });
|
|
739
|
-
const fields = buildStructureFields$1(schema, plan, ctx);
|
|
740
|
-
if (fields.length === 0) return builtinType({ name: "string" });
|
|
741
|
-
return structureType({ fields });
|
|
742
|
-
}
|
|
743
|
-
if (type === void 0) {
|
|
744
|
-
for (const c of [
|
|
745
|
-
"allOf",
|
|
746
|
-
"oneOf",
|
|
747
|
-
"anyOf"
|
|
748
|
-
]) if (Array.isArray(schema[c])) {
|
|
749
|
-
const matched = findPlannedEntryBySchema$1(schema, plan, ctx.entryId);
|
|
750
|
-
if (matched) return namedTypeRef({ name: matched.abapName });
|
|
751
|
-
return builtinType({ name: "string" });
|
|
752
|
-
}
|
|
753
809
|
return builtinType({ name: "string" });
|
|
754
810
|
}
|
|
755
|
-
return builtinType({ name:
|
|
811
|
+
return builtinType({ name: "string" });
|
|
756
812
|
}
|
|
757
813
|
/** If a schema is identical-by-reference to a planned entry, return it. */
|
|
758
814
|
function findPlannedEntryBySchema$1(schema, plan, excludeId) {
|
|
@@ -780,49 +836,59 @@ function buildEnumMembers(values) {
|
|
|
780
836
|
function buildStructureFields$1(schema, plan, ctx) {
|
|
781
837
|
const fields = [];
|
|
782
838
|
const seen = /* @__PURE__ */ new Map();
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
});
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
const subSchema = sub;
|
|
811
|
-
const subProps = isRef(subSchema) ? (() => {
|
|
812
|
-
const entry = refToEntry(subSchema.$ref, plan);
|
|
813
|
-
if (!entry) return void 0;
|
|
814
|
-
return entry.schema.properties;
|
|
815
|
-
})() : subSchema.properties;
|
|
816
|
-
if (isRecord$2(subProps)) for (const [name, propSchema] of Object.entries(subProps)) {
|
|
817
|
-
if (!isRecord$2(propSchema)) continue;
|
|
818
|
-
addField(name, mapSchemaToTypeRef(propSchema, plan, ctx), propSchema);
|
|
839
|
+
addAllOfFields(schema, plan, ctx, fields, seen);
|
|
840
|
+
addPropertyFields(schema.properties, plan, ctx, fields, seen);
|
|
841
|
+
addUnionFields(schema, plan, ctx, fields, seen);
|
|
842
|
+
addExtraField(schema, plan, fields, seen);
|
|
843
|
+
return fields;
|
|
844
|
+
}
|
|
845
|
+
function addStructureField(fields, seen, name, type, src) {
|
|
846
|
+
const sanitized = sanitizeIdent(name, "param");
|
|
847
|
+
const prev = seen.get(sanitized);
|
|
848
|
+
if (prev) {
|
|
849
|
+
if (prev === type || shallowTypeRefEqual(prev, type)) return;
|
|
850
|
+
throw new CollisionError(`buildStructureFields: duplicate field "${sanitized}" with conflicting types`);
|
|
851
|
+
}
|
|
852
|
+
seen.set(sanitized, type);
|
|
853
|
+
fields.push({
|
|
854
|
+
name: sanitized,
|
|
855
|
+
type
|
|
856
|
+
});
|
|
857
|
+
if (isNullable$1(src)) {
|
|
858
|
+
const flagName = sanitizeIdent(`${name}_is_null`, "param");
|
|
859
|
+
if (!seen.has(flagName)) {
|
|
860
|
+
const flagType = builtinType({ name: "abap_bool" });
|
|
861
|
+
seen.set(flagName, flagType);
|
|
862
|
+
fields.push({
|
|
863
|
+
name: flagName,
|
|
864
|
+
type: flagType
|
|
865
|
+
});
|
|
819
866
|
}
|
|
820
867
|
}
|
|
821
|
-
|
|
822
|
-
|
|
868
|
+
}
|
|
869
|
+
function addPropertyFields(props, plan, ctx, fields, seen) {
|
|
870
|
+
if (!isRecord$2(props)) return;
|
|
871
|
+
for (const [name, propSchema] of Object.entries(props)) {
|
|
823
872
|
if (!isRecord$2(propSchema)) continue;
|
|
824
|
-
|
|
873
|
+
addStructureField(fields, seen, name, mapSchemaToTypeRef(propSchema, plan, ctx), propSchema);
|
|
825
874
|
}
|
|
875
|
+
}
|
|
876
|
+
function addAllOfFields(schema, plan, ctx, fields, seen) {
|
|
877
|
+
const allOf = schema.allOf;
|
|
878
|
+
if (!Array.isArray(allOf)) return;
|
|
879
|
+
for (const sub of allOf) {
|
|
880
|
+
if (!isRecord$2(sub)) continue;
|
|
881
|
+
const subProps = resolvedProperties(sub, plan);
|
|
882
|
+
if (isRecord$2(subProps)) addPropertyFields(subProps, plan, ctx, fields, seen);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
function resolvedProperties(subSchema, plan) {
|
|
886
|
+
if (!isRef(subSchema)) return subSchema.properties;
|
|
887
|
+
const entry = refToEntry(subSchema.$ref, plan);
|
|
888
|
+
if (!entry) return void 0;
|
|
889
|
+
return entry.schema.properties;
|
|
890
|
+
}
|
|
891
|
+
function addUnionFields(schema, plan, ctx, fields, seen) {
|
|
826
892
|
for (const combinator of ["oneOf", "anyOf"]) {
|
|
827
893
|
const arr = schema[combinator];
|
|
828
894
|
if (!Array.isArray(arr)) continue;
|
|
@@ -831,8 +897,7 @@ function buildStructureFields$1(schema, plan, ctx) {
|
|
|
831
897
|
addFieldRaw(fields, seen, "kind", builtinType({ name: "string" }));
|
|
832
898
|
arr.forEach((sub, idx) => {
|
|
833
899
|
if (!isRecord$2(sub)) return;
|
|
834
|
-
|
|
835
|
-
addFieldRaw(fields, seen, variantName, mapSchemaToTypeRef(sub, plan, ctx));
|
|
900
|
+
addFieldRaw(fields, seen, variantFieldName(sub, idx), mapSchemaToTypeRef(sub, plan, ctx));
|
|
836
901
|
});
|
|
837
902
|
} else {
|
|
838
903
|
addFieldRaw(fields, seen, "variant_kind", builtinType({ name: "string" }));
|
|
@@ -844,17 +909,18 @@ function buildStructureFields$1(schema, plan, ctx) {
|
|
|
844
909
|
});
|
|
845
910
|
}
|
|
846
911
|
}
|
|
912
|
+
}
|
|
913
|
+
function addExtraField(schema, plan, fields, seen) {
|
|
847
914
|
const ap = schema.additionalProperties;
|
|
848
|
-
if (ap
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
}
|
|
857
|
-
return fields;
|
|
915
|
+
if (ap !== true && !isRecord$2(ap)) return;
|
|
916
|
+
const kvEntry = plan.byId.get("aux.kv");
|
|
917
|
+
if (!kvEntry) return;
|
|
918
|
+
addFieldRaw(fields, seen, "_extra", tableType({
|
|
919
|
+
rowType: namedTypeRef({ name: kvEntry.abapName }),
|
|
920
|
+
tableKind: "hashed",
|
|
921
|
+
uniqueness: "unique",
|
|
922
|
+
keyFields: ["key"]
|
|
923
|
+
}));
|
|
858
924
|
}
|
|
859
925
|
function addFieldRaw(fields, seen, rawName, type) {
|
|
860
926
|
const name = sanitizeIdent(rawName, "param");
|
|
@@ -959,7 +1025,7 @@ function validateLocal(field, value) {
|
|
|
959
1025
|
function deriveFromBase(base) {
|
|
960
1026
|
const trimmed = base.trim();
|
|
961
1027
|
if (trimmed.length === 0) throw new NamesConfigError("Invalid \"base\" name: value is empty or whitespace.");
|
|
962
|
-
if (!/^[A-Za-z]
|
|
1028
|
+
if (!/^[A-Za-z]\w*$/.test(trimmed)) throw new NamesConfigError(`Invalid "base" name: "${base}" must start with a letter and contain only letters, digits, and underscores.`);
|
|
963
1029
|
const upper = trimmed.toUpperCase();
|
|
964
1030
|
return {
|
|
965
1031
|
typesInterface: `ZIF_${upper}_TYPES`,
|
|
@@ -1037,10 +1103,7 @@ function emitTypesInterface(spec, plan, opts) {
|
|
|
1037
1103
|
for (const entry of plan.entries) {
|
|
1038
1104
|
if (entry.source === "auxiliary") continue;
|
|
1039
1105
|
const aux = ctx.mapAux.get(entry.id);
|
|
1040
|
-
if (aux)
|
|
1041
|
-
typeDefs.push(aux.entryTypeDef);
|
|
1042
|
-
typeDefs.push(aux.mapTypeDef);
|
|
1043
|
-
}
|
|
1106
|
+
if (aux) typeDefs.push(aux.entryTypeDef, aux.mapTypeDef);
|
|
1044
1107
|
typeDefs.push(buildEntryTypeDef(entry, ctx));
|
|
1045
1108
|
}
|
|
1046
1109
|
return {
|
|
@@ -1080,7 +1143,7 @@ function originalNameFromId(id) {
|
|
|
1080
1143
|
}
|
|
1081
1144
|
/** Normalise a raw name for v2: replace `$` with `_`, then snake_case ≤ 30. */
|
|
1082
1145
|
function v2Name(raw, allocator) {
|
|
1083
|
-
return allocator(raw.replaceAll(
|
|
1146
|
+
return allocator(raw.replaceAll("$", "_"), "type");
|
|
1084
1147
|
}
|
|
1085
1148
|
function buildContext(spec, plan, opts) {
|
|
1086
1149
|
const alloc = makeNameAllocator(/* @__PURE__ */ new Set());
|
|
@@ -1153,45 +1216,10 @@ function deriveRawName(entry) {
|
|
|
1153
1216
|
function buildEntryTypeDef(entry, ctx) {
|
|
1154
1217
|
const name = ctx.nameOf.get(entry.id);
|
|
1155
1218
|
const schema = entry.schema;
|
|
1156
|
-
const leadingDoc =
|
|
1157
|
-
const
|
|
1158
|
-
if (
|
|
1159
|
-
else if (entry.source === "inline") leadingDoc.push(`@openapi-path ${entry.id}`);
|
|
1160
|
-
const description = schema.description;
|
|
1161
|
-
if (typeof description === "string" && description.trim()) for (const line of description.split(/\r?\n/)) leadingDoc.push(`@openapi-description ${line}`);
|
|
1162
|
-
const enumValues = schema.enum;
|
|
1219
|
+
const leadingDoc = buildLeadingDoc(entry, ctx);
|
|
1220
|
+
const enumDef = tryEnumTypeDef(entry, name, leadingDoc);
|
|
1221
|
+
if (enumDef !== void 0) return enumDef;
|
|
1163
1222
|
const schemaType = pluckType$1(schema);
|
|
1164
|
-
if (Array.isArray(enumValues) && (schemaType === "string" || schemaType === void 0)) {
|
|
1165
|
-
const members = [];
|
|
1166
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1167
|
-
for (const v of enumValues) if (typeof v === "string") {
|
|
1168
|
-
let nm = sanitizeIdent(v, "type");
|
|
1169
|
-
let i = 2;
|
|
1170
|
-
while (seen.has(nm)) nm = `${nm}_${i++}`;
|
|
1171
|
-
seen.add(nm);
|
|
1172
|
-
members.push({
|
|
1173
|
-
name: nm,
|
|
1174
|
-
value: v
|
|
1175
|
-
});
|
|
1176
|
-
} else if (typeof v === "number") {
|
|
1177
|
-
let nm = sanitizeIdent(`v_${v}`, "type");
|
|
1178
|
-
let i = 2;
|
|
1179
|
-
while (seen.has(nm)) nm = `${nm}_${i++}`;
|
|
1180
|
-
seen.add(nm);
|
|
1181
|
-
members.push({
|
|
1182
|
-
name: nm,
|
|
1183
|
-
value: v
|
|
1184
|
-
});
|
|
1185
|
-
}
|
|
1186
|
-
if (members.length > 0) return typeDef({
|
|
1187
|
-
name,
|
|
1188
|
-
type: enumType({
|
|
1189
|
-
baseType: builtinType({ name: "string" }),
|
|
1190
|
-
members
|
|
1191
|
-
}),
|
|
1192
|
-
abapDoc: leadingDoc.length > 0 ? leadingDoc : void 0
|
|
1193
|
-
});
|
|
1194
|
-
}
|
|
1195
1223
|
if (schemaType === "array") {
|
|
1196
1224
|
const items = schema.items;
|
|
1197
1225
|
const rowSchema = isRecord$1(items) ? items : {};
|
|
@@ -1222,6 +1250,54 @@ function buildEntryTypeDef(entry, ctx) {
|
|
|
1222
1250
|
abapDoc: finaliseDoc(leadingDoc, ctx.backRefs.get(entry.id) ?? [])
|
|
1223
1251
|
});
|
|
1224
1252
|
}
|
|
1253
|
+
function buildLeadingDoc(entry, ctx) {
|
|
1254
|
+
const leadingDoc = [];
|
|
1255
|
+
const original = ctx.originalNameOf.get(entry.id);
|
|
1256
|
+
if (original !== void 0) leadingDoc.push(`@openapi-schema ${original}`);
|
|
1257
|
+
else if (entry.source === "inline") leadingDoc.push(`@openapi-path ${entry.id}`);
|
|
1258
|
+
const description = entry.schema.description;
|
|
1259
|
+
if (typeof description === "string" && description.trim()) for (const line of description.split(/\r?\n/)) leadingDoc.push(`@openapi-description ${line}`);
|
|
1260
|
+
return leadingDoc;
|
|
1261
|
+
}
|
|
1262
|
+
/** Enum shortcut: string with enum values. Returns undefined when the entry
|
|
1263
|
+
* is not enum-shaped or has no usable members. */
|
|
1264
|
+
function tryEnumTypeDef(entry, name, leadingDoc) {
|
|
1265
|
+
const schema = entry.schema;
|
|
1266
|
+
const enumValues = schema.enum;
|
|
1267
|
+
const schemaType = pluckType$1(schema);
|
|
1268
|
+
if (!Array.isArray(enumValues)) return void 0;
|
|
1269
|
+
if (schemaType !== "string" && schemaType !== void 0) return void 0;
|
|
1270
|
+
const members = buildDedupedEnumMembers(enumValues);
|
|
1271
|
+
if (members.length === 0) return void 0;
|
|
1272
|
+
return typeDef({
|
|
1273
|
+
name,
|
|
1274
|
+
type: enumType({
|
|
1275
|
+
baseType: builtinType({ name: "string" }),
|
|
1276
|
+
members
|
|
1277
|
+
}),
|
|
1278
|
+
abapDoc: leadingDoc.length > 0 ? leadingDoc : void 0
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
function buildDedupedEnumMembers(enumValues) {
|
|
1282
|
+
const members = [];
|
|
1283
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1284
|
+
for (const v of enumValues) if (typeof v === "string") members.push({
|
|
1285
|
+
name: uniqueEnumName(sanitizeIdent(v, "type"), seen),
|
|
1286
|
+
value: v
|
|
1287
|
+
});
|
|
1288
|
+
else if (typeof v === "number") members.push({
|
|
1289
|
+
name: uniqueEnumName(sanitizeIdent(`v_${v}`, "type"), seen),
|
|
1290
|
+
value: v
|
|
1291
|
+
});
|
|
1292
|
+
return members;
|
|
1293
|
+
}
|
|
1294
|
+
function uniqueEnumName(base, seen) {
|
|
1295
|
+
let nm = base;
|
|
1296
|
+
let i = 2;
|
|
1297
|
+
while (seen.has(nm)) nm = `${nm}_${i++}`;
|
|
1298
|
+
seen.add(nm);
|
|
1299
|
+
return nm;
|
|
1300
|
+
}
|
|
1225
1301
|
function finaliseDoc(base, backRefs) {
|
|
1226
1302
|
const out = [...base];
|
|
1227
1303
|
for (const br of backRefs) out.push(br);
|
|
@@ -1233,7 +1309,7 @@ function buildStructureFields(entry, ctx) {
|
|
|
1233
1309
|
const seen = /* @__PURE__ */ new Map();
|
|
1234
1310
|
const addField = (rawName, rawType, src) => {
|
|
1235
1311
|
const type = asFieldTypeRef(rawType);
|
|
1236
|
-
const fieldName = sanitizeIdent(rawName.replaceAll(
|
|
1312
|
+
const fieldName = sanitizeIdent(rawName.replaceAll("$", "_"), "param");
|
|
1237
1313
|
const prev = seen.get(fieldName);
|
|
1238
1314
|
if (prev !== void 0) {
|
|
1239
1315
|
if (!typeRefEqual(prev, type)) throw new PolymorphismConflictError(`buildStructureFields: conflicting types for field "${fieldName}" in "${entry.id}"`);
|
|
@@ -1264,26 +1340,9 @@ function buildStructureFields(entry, ctx) {
|
|
|
1264
1340
|
addField(propName, ref, propSchema);
|
|
1265
1341
|
}
|
|
1266
1342
|
};
|
|
1267
|
-
|
|
1268
|
-
if (Array.isArray(allOf)) for (const sub of allOf) {
|
|
1269
|
-
if (!isRecord$1(sub)) continue;
|
|
1270
|
-
if (isRef(sub)) {
|
|
1271
|
-
const refEntry = resolveRefEntry(sub.$ref, ctx);
|
|
1272
|
-
if (refEntry !== void 0) mergeProperties(refEntry.schema);
|
|
1273
|
-
} else mergeProperties(sub);
|
|
1274
|
-
}
|
|
1343
|
+
mergeVariantList(schema.allOf, ctx, mergeProperties);
|
|
1275
1344
|
mergeProperties(schema);
|
|
1276
|
-
for (const combinator of ["oneOf", "anyOf"])
|
|
1277
|
-
const arr = schema[combinator];
|
|
1278
|
-
if (!Array.isArray(arr)) continue;
|
|
1279
|
-
for (const sub of arr) {
|
|
1280
|
-
if (!isRecord$1(sub)) continue;
|
|
1281
|
-
if (isRef(sub)) {
|
|
1282
|
-
const refEntry = resolveRefEntry(sub.$ref, ctx);
|
|
1283
|
-
if (refEntry !== void 0) mergeProperties(refEntry.schema);
|
|
1284
|
-
} else mergeProperties(sub);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1345
|
+
for (const combinator of ["oneOf", "anyOf"]) mergeVariantList(schema[combinator], ctx, mergeProperties);
|
|
1287
1346
|
const aux = ctx.mapAux.get(entry.id);
|
|
1288
1347
|
if (aux) {
|
|
1289
1348
|
const fieldName = sanitizeIdent("entries", "param");
|
|
@@ -1298,6 +1357,17 @@ function buildStructureFields(entry, ctx) {
|
|
|
1298
1357
|
}
|
|
1299
1358
|
return fields;
|
|
1300
1359
|
}
|
|
1360
|
+
function mergeVariantList(variants, ctx, merge) {
|
|
1361
|
+
if (!Array.isArray(variants)) return;
|
|
1362
|
+
for (const sub of variants) mergeVariantProperties(sub, ctx, merge);
|
|
1363
|
+
}
|
|
1364
|
+
function mergeVariantProperties(sub, ctx, merge) {
|
|
1365
|
+
if (!isRecord$1(sub)) return;
|
|
1366
|
+
if (isRef(sub)) {
|
|
1367
|
+
const refEntry = resolveRefEntry(sub.$ref, ctx);
|
|
1368
|
+
if (refEntry !== void 0) merge(refEntry.schema);
|
|
1369
|
+
} else merge(sub);
|
|
1370
|
+
}
|
|
1301
1371
|
function resolveRefEntry(ref, ctx) {
|
|
1302
1372
|
const name = componentNameFromRef$1(ref);
|
|
1303
1373
|
if (!name) return void 0;
|
|
@@ -1326,23 +1396,7 @@ function asFieldTypeRef(t) {
|
|
|
1326
1396
|
return namedTypeRef({ name: `STANDARD TABLE OF ${rowExpr} WITH EMPTY KEY` });
|
|
1327
1397
|
}
|
|
1328
1398
|
function resolveTypeRef(schema, ownerEntryId, ctx, fieldName) {
|
|
1329
|
-
if (isRef(schema))
|
|
1330
|
-
const target = resolveRefEntry(schema.$ref, ctx);
|
|
1331
|
-
if (target === void 0) return builtinType({ name: "string" });
|
|
1332
|
-
const ownerPos = ctx.positionOf.get(ownerEntryId) ?? -1;
|
|
1333
|
-
const targetPos = ctx.positionOf.get(target.id) ?? -1;
|
|
1334
|
-
const isBackEdge = targetPos >= 0 && ownerPos >= 0 && targetPos >= ownerPos;
|
|
1335
|
-
if (target.id === ownerEntryId || isBackEdge) {
|
|
1336
|
-
const targetOriginal = ctx.originalNameOf.get(target.id) ?? ctx.nameOf.get(target.id) ?? target.id;
|
|
1337
|
-
const backRefs = ctx.backRefs.get(ownerEntryId);
|
|
1338
|
-
if (backRefs !== void 0) {
|
|
1339
|
-
const label = fieldName ? `${fieldName}:${targetOriginal}` : targetOriginal;
|
|
1340
|
-
backRefs.push(`@openapi-ref ${label}`);
|
|
1341
|
-
}
|
|
1342
|
-
return namedTypeRef({ name: "REF TO data" });
|
|
1343
|
-
}
|
|
1344
|
-
return namedTypeRef({ name: ctx.nameOf.get(target.id) ?? target.abapName });
|
|
1345
|
-
}
|
|
1399
|
+
if (isRef(schema)) return resolveNamedTypeRef(schema, ownerEntryId, ctx, fieldName);
|
|
1346
1400
|
const type = pluckType$1(schema);
|
|
1347
1401
|
if (type === "array") {
|
|
1348
1402
|
const items = schema.items;
|
|
@@ -1353,31 +1407,45 @@ function resolveTypeRef(schema, ownerEntryId, ctx, fieldName) {
|
|
|
1353
1407
|
});
|
|
1354
1408
|
}
|
|
1355
1409
|
const props = schema.properties;
|
|
1356
|
-
if (type === "object" || isRecord$1(props)) {
|
|
1357
|
-
|
|
1358
|
-
if (matched !== void 0) {
|
|
1359
|
-
const name = ctx.nameOf.get(matched.id);
|
|
1360
|
-
if (name !== void 0) return namedTypeRef({ name });
|
|
1361
|
-
}
|
|
1362
|
-
return builtinType({ name: "string" });
|
|
1363
|
-
}
|
|
1364
|
-
if (type === void 0) {
|
|
1365
|
-
for (const c of [
|
|
1366
|
-
"allOf",
|
|
1367
|
-
"oneOf",
|
|
1368
|
-
"anyOf"
|
|
1369
|
-
]) if (Array.isArray(schema[c])) {
|
|
1370
|
-
const matched = findPlannedEntryBySchema(schema, ctx.plan, ownerEntryId);
|
|
1371
|
-
if (matched !== void 0) {
|
|
1372
|
-
const name = ctx.nameOf.get(matched.id);
|
|
1373
|
-
if (name !== void 0) return namedTypeRef({ name });
|
|
1374
|
-
}
|
|
1375
|
-
return builtinType({ name: "string" });
|
|
1376
|
-
}
|
|
1377
|
-
return builtinType({ name: "string" });
|
|
1378
|
-
}
|
|
1410
|
+
if (type === "object" || isRecord$1(props)) return plannedEntryRef(schema, ctx, ownerEntryId) ?? builtinType({ name: "string" });
|
|
1411
|
+
if (type === void 0) return resolveUntypedTypeRef(schema, ctx, ownerEntryId);
|
|
1379
1412
|
return builtinType({ name: mapPrimitiveLocal(schema) });
|
|
1380
1413
|
}
|
|
1414
|
+
function resolveNamedTypeRef(schema, ownerEntryId, ctx, fieldName) {
|
|
1415
|
+
const target = resolveRefEntry(schema.$ref, ctx);
|
|
1416
|
+
if (target === void 0) return builtinType({ name: "string" });
|
|
1417
|
+
const ownerPos = ctx.positionOf.get(ownerEntryId) ?? -1;
|
|
1418
|
+
const targetPos = ctx.positionOf.get(target.id) ?? -1;
|
|
1419
|
+
const isBackEdge = targetPos >= 0 && ownerPos >= 0 && targetPos >= ownerPos;
|
|
1420
|
+
if (target.id === ownerEntryId || isBackEdge) return buildBackEdgeRef(target, ownerEntryId, ctx, fieldName);
|
|
1421
|
+
return namedTypeRef({ name: ctx.nameOf.get(target.id) ?? target.abapName });
|
|
1422
|
+
}
|
|
1423
|
+
function buildBackEdgeRef(target, ownerEntryId, ctx, fieldName) {
|
|
1424
|
+
const targetOriginal = ctx.originalNameOf.get(target.id) ?? ctx.nameOf.get(target.id) ?? target.id;
|
|
1425
|
+
const backRefs = ctx.backRefs.get(ownerEntryId);
|
|
1426
|
+
if (backRefs !== void 0) {
|
|
1427
|
+
const label = fieldName ? `${fieldName}:${targetOriginal}` : targetOriginal;
|
|
1428
|
+
backRefs.push(`@openapi-ref ${label}`);
|
|
1429
|
+
}
|
|
1430
|
+
return namedTypeRef({ name: "REF TO data" });
|
|
1431
|
+
}
|
|
1432
|
+
/** Name ref for a schema object that has a planned entry; undefined when no
|
|
1433
|
+
* planned entry (or no emitted name) exists. */
|
|
1434
|
+
function plannedEntryRef(schema, ctx, ownerEntryId) {
|
|
1435
|
+
const matched = findPlannedEntryBySchema(schema, ctx.plan, ownerEntryId);
|
|
1436
|
+
if (matched === void 0) return void 0;
|
|
1437
|
+
const name = ctx.nameOf.get(matched.id);
|
|
1438
|
+
if (name === void 0) return void 0;
|
|
1439
|
+
return namedTypeRef({ name });
|
|
1440
|
+
}
|
|
1441
|
+
function resolveUntypedTypeRef(schema, ctx, ownerEntryId) {
|
|
1442
|
+
for (const c of [
|
|
1443
|
+
"allOf",
|
|
1444
|
+
"oneOf",
|
|
1445
|
+
"anyOf"
|
|
1446
|
+
]) if (Array.isArray(schema[c])) return plannedEntryRef(schema, ctx, ownerEntryId) ?? builtinType({ name: "string" });
|
|
1447
|
+
return builtinType({ name: "string" });
|
|
1448
|
+
}
|
|
1381
1449
|
function findPlannedEntryBySchema(schema, plan, excludeId) {
|
|
1382
1450
|
for (const entry of plan.entries) {
|
|
1383
1451
|
if (entry.id === excludeId) continue;
|
|
@@ -1622,8 +1690,7 @@ function orderParams(params) {
|
|
|
1622
1690
|
}
|
|
1623
1691
|
function buildMethodAbapDoc(op, cookieSkipped) {
|
|
1624
1692
|
const lines = [];
|
|
1625
|
-
lines.push(`@openapi-operation ${op.operationId}`);
|
|
1626
|
-
lines.push(`@openapi-path ${op.method.toUpperCase()} ${op.path}`);
|
|
1693
|
+
lines.push(`@openapi-operation ${op.operationId}`, `@openapi-path ${op.method.toUpperCase()} ${op.path}`);
|
|
1627
1694
|
if (op.summary) {
|
|
1628
1695
|
for (const l of op.summary.split(/\r?\n/)) if (l.trim().length > 0) lines.push(l.trim());
|
|
1629
1696
|
}
|
|
@@ -1639,81 +1706,95 @@ function emitOperationsInterface(spec, _plan, opts) {
|
|
|
1639
1706
|
const tableAliases = createTableAliasRegistry();
|
|
1640
1707
|
const opsInterfaceName = opts.name;
|
|
1641
1708
|
for (const op of spec.operations) {
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
}
|
|
1665
|
-
const bodySchema = pickRequestBodySchema$1(op);
|
|
1666
|
-
const hasBody = bodySchema !== void 0;
|
|
1667
|
-
if (hasBody) {
|
|
1668
|
-
const bodyName = allocParam("body", "param");
|
|
1669
|
-
const ref = schemaToTypeRef(bodySchema, compIndex, opts.typesInterfaceName, opsInterfaceName, tableAliases);
|
|
1670
|
-
abapParams.push(methodParam({
|
|
1671
|
-
paramKind: "importing",
|
|
1672
|
-
name: bodyName,
|
|
1673
|
-
typeRef: ref,
|
|
1674
|
-
optional: op.requestBody?.required === false ? true : false
|
|
1675
|
-
}));
|
|
1676
|
-
}
|
|
1677
|
-
const success = pickSuccess(op);
|
|
1678
|
-
let successStatus;
|
|
1679
|
-
let successIsEmptyBody;
|
|
1680
|
-
let returningName;
|
|
1681
|
-
let returningRef;
|
|
1682
|
-
if (!success) {
|
|
1683
|
-
successStatus = 200;
|
|
1684
|
-
successIsEmptyBody = true;
|
|
1685
|
-
returningName = allocParam("success", "param");
|
|
1686
|
-
returningRef = builtinType({ name: "abap_bool" });
|
|
1687
|
-
} else if (success.schema === void 0) {
|
|
1688
|
-
successStatus = success.status;
|
|
1689
|
-
successIsEmptyBody = true;
|
|
1690
|
-
returningName = allocParam("success", "param");
|
|
1691
|
-
returningRef = builtinType({ name: "abap_bool" });
|
|
1692
|
-
} else {
|
|
1693
|
-
successStatus = success.status;
|
|
1694
|
-
successIsEmptyBody = false;
|
|
1695
|
-
returningName = allocParam(deriveReturningName(success.schema, compIndex), "param");
|
|
1696
|
-
returningRef = schemaToTypeRef(success.schema, compIndex, opts.typesInterfaceName, opsInterfaceName, tableAliases);
|
|
1697
|
-
}
|
|
1709
|
+
const { method, mapping } = buildOperationMethod(op, allocMethod(op.operationId, "method"), compIndex, opts, opsInterfaceName, tableAliases);
|
|
1710
|
+
methods.push(method);
|
|
1711
|
+
mappings.push(mapping);
|
|
1712
|
+
}
|
|
1713
|
+
const aliasTypeDefs = buildAliasTypeDefs(tableAliases);
|
|
1714
|
+
return {
|
|
1715
|
+
interface: interfaceDef({
|
|
1716
|
+
name: opts.name.toLowerCase(),
|
|
1717
|
+
members: [...aliasTypeDefs, ...methods],
|
|
1718
|
+
abapDoc: opts.interfaceAbapDoc
|
|
1719
|
+
}),
|
|
1720
|
+
operations: mappings
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
function buildOperationMethod(op, methodName, compIndex, opts, opsInterfaceName, tableAliases) {
|
|
1724
|
+
const { emitted, cookieSkipped } = orderParams(op.parameters);
|
|
1725
|
+
const allocParam = makeNameAllocator(/* @__PURE__ */ new Set());
|
|
1726
|
+
const abapParams = [];
|
|
1727
|
+
const paramMappings = [];
|
|
1728
|
+
for (const p of emitted) {
|
|
1729
|
+
const abapName = allocParam(p.name, "param");
|
|
1730
|
+
const ref = schemaToTypeRef(p.schema, compIndex, opts.typesInterfaceName, opsInterfaceName, tableAliases);
|
|
1698
1731
|
abapParams.push(methodParam({
|
|
1699
|
-
paramKind: "
|
|
1700
|
-
name:
|
|
1701
|
-
typeRef:
|
|
1732
|
+
paramKind: "importing",
|
|
1733
|
+
name: abapName,
|
|
1734
|
+
typeRef: ref,
|
|
1735
|
+
optional: !p.required
|
|
1702
1736
|
}));
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1737
|
+
paramMappings.push({
|
|
1738
|
+
name: abapName,
|
|
1739
|
+
openapiName: p.name,
|
|
1740
|
+
location: p.in,
|
|
1741
|
+
required: p.required,
|
|
1742
|
+
typeRefSource: renderTypeRefSource(ref),
|
|
1743
|
+
isTable: pluckType(p.schema) === "array"
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
const bodySchema = pickRequestBodySchema$1(op);
|
|
1747
|
+
const hasBody = bodySchema !== void 0;
|
|
1748
|
+
if (hasBody) {
|
|
1749
|
+
const bodyName = allocParam("body", "param");
|
|
1750
|
+
const ref = schemaToTypeRef(bodySchema, compIndex, opts.typesInterfaceName, opsInterfaceName, tableAliases);
|
|
1751
|
+
abapParams.push(methodParam({
|
|
1752
|
+
paramKind: "importing",
|
|
1753
|
+
name: bodyName,
|
|
1754
|
+
typeRef: ref,
|
|
1755
|
+
optional: op.requestBody?.required === false
|
|
1756
|
+
}));
|
|
1757
|
+
}
|
|
1758
|
+
const success = pickSuccess(op);
|
|
1759
|
+
let successStatus;
|
|
1760
|
+
let successIsEmptyBody;
|
|
1761
|
+
let returningName;
|
|
1762
|
+
let returningRef;
|
|
1763
|
+
if (!success) {
|
|
1764
|
+
successStatus = 200;
|
|
1765
|
+
successIsEmptyBody = true;
|
|
1766
|
+
returningName = allocParam("success", "param");
|
|
1767
|
+
returningRef = builtinType({ name: "abap_bool" });
|
|
1768
|
+
} else if (success.schema === void 0) {
|
|
1769
|
+
successStatus = success.status;
|
|
1770
|
+
successIsEmptyBody = true;
|
|
1771
|
+
returningName = allocParam("success", "param");
|
|
1772
|
+
returningRef = builtinType({ name: "abap_bool" });
|
|
1773
|
+
} else {
|
|
1774
|
+
successStatus = success.status;
|
|
1775
|
+
successIsEmptyBody = false;
|
|
1776
|
+
returningName = allocParam(deriveReturningName(success.schema, compIndex), "param");
|
|
1777
|
+
returningRef = schemaToTypeRef(success.schema, compIndex, opts.typesInterfaceName, opsInterfaceName, tableAliases);
|
|
1778
|
+
}
|
|
1779
|
+
abapParams.push(methodParam({
|
|
1780
|
+
paramKind: "returning",
|
|
1781
|
+
name: returningName,
|
|
1782
|
+
typeRef: returningRef
|
|
1783
|
+
}));
|
|
1784
|
+
const errorResponses = {};
|
|
1785
|
+
for (const r of op.responses) {
|
|
1786
|
+
if (!r.isError) continue;
|
|
1787
|
+
errorResponses[r.statusCode] = r.description ? { description: r.description } : {};
|
|
1788
|
+
}
|
|
1789
|
+
return {
|
|
1790
|
+
method: methodDef({
|
|
1709
1791
|
name: methodName,
|
|
1710
1792
|
visibility: "public",
|
|
1711
1793
|
params: abapParams,
|
|
1712
1794
|
raising: [namedTypeRef({ name: opts.exceptionClassName.toLowerCase() })],
|
|
1713
1795
|
abapDoc: buildMethodAbapDoc(op, cookieSkipped)
|
|
1714
|
-
})
|
|
1715
|
-
|
|
1716
|
-
mappings.push({
|
|
1796
|
+
}),
|
|
1797
|
+
mapping: {
|
|
1717
1798
|
operationId: op.operationId,
|
|
1718
1799
|
methodName,
|
|
1719
1800
|
method: op.method.toUpperCase(),
|
|
@@ -1724,16 +1805,7 @@ function emitOperationsInterface(spec, _plan, opts) {
|
|
|
1724
1805
|
successIsEmptyBody,
|
|
1725
1806
|
errorResponses,
|
|
1726
1807
|
returningName
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
const aliasTypeDefs = buildAliasTypeDefs(tableAliases);
|
|
1730
|
-
return {
|
|
1731
|
-
interface: interfaceDef({
|
|
1732
|
-
name: opts.name.toLowerCase(),
|
|
1733
|
-
members: [...aliasTypeDefs, ...methods],
|
|
1734
|
-
abapDoc: opts.interfaceAbapDoc
|
|
1735
|
-
}),
|
|
1736
|
-
operations: mappings
|
|
1808
|
+
}
|
|
1737
1809
|
};
|
|
1738
1810
|
}
|
|
1739
1811
|
function renderTypeRefSource(ref) {
|
|
@@ -1873,7 +1945,6 @@ function emitExceptionClass(opts) {
|
|
|
1873
1945
|
// src/emit/templates/locals-def.abap.ts
|
|
1874
1946
|
function buildLocalsDef(names) {
|
|
1875
1947
|
const { localJsonClass: JSON_CLS, localJsonParserClass: JSON_PARSER, localResponseClass: RESPONSE, localHttpClass: HTTP } = names;
|
|
1876
|
-
names.exceptionClass;
|
|
1877
1948
|
return `* Generated by @abapify/openai-codegen - local class declarations.
|
|
1878
1949
|
* ZERO Z-dependencies: these locals wrap SAP kernel APIs only.
|
|
1879
1950
|
* Per-operation methods map HTTP status codes to the custom exception.
|
|
@@ -2240,9 +2311,7 @@ function renderSuccessBody(opts) {
|
|
|
2240
2311
|
function renderErrorBranch(statusCode, description, opts) {
|
|
2241
2312
|
const responseVar = opts.responseVarName ?? "response";
|
|
2242
2313
|
const lines = [];
|
|
2243
|
-
lines.push(` WHEN ${statusCode}
|
|
2244
|
-
lines.push(` RAISE EXCEPTION NEW ${opts.exceptionClassName}(`);
|
|
2245
|
-
lines.push(` status = ${statusCode}`);
|
|
2314
|
+
lines.push(` WHEN ${statusCode}.`, ` RAISE EXCEPTION NEW ${opts.exceptionClassName}(`, ` status = ${statusCode}`);
|
|
2246
2315
|
if (description !== void 0 && description.length > 0) lines.push(` description = '${escapeAbapLiteral(description)}'`);
|
|
2247
2316
|
lines.push(` body = ${responseVar}->body( ) ).`);
|
|
2248
2317
|
return lines;
|
|
@@ -2250,9 +2319,7 @@ function renderErrorBranch(statusCode, description, opts) {
|
|
|
2250
2319
|
function renderOthersBranch(description, opts) {
|
|
2251
2320
|
const responseVar = opts.responseVarName ?? "response";
|
|
2252
2321
|
const lines = [];
|
|
2253
|
-
lines.push(` WHEN OTHERS
|
|
2254
|
-
lines.push(` RAISE EXCEPTION NEW ${opts.exceptionClassName}(`);
|
|
2255
|
-
lines.push(` status = ${responseVar}->status( )`);
|
|
2322
|
+
lines.push(` WHEN OTHERS.`, ` RAISE EXCEPTION NEW ${opts.exceptionClassName}(`, ` status = ${responseVar}->status( )`);
|
|
2256
2323
|
if (description !== void 0 && description.length > 0) lines.push(` description = '${escapeAbapLiteral(description)}'`);
|
|
2257
2324
|
lines.push(` body = ${responseVar}->body( ) ).`);
|
|
2258
2325
|
return lines;
|
|
@@ -2262,23 +2329,18 @@ function mapResponseHandling(operation, opts) {
|
|
|
2262
2329
|
const lines = [];
|
|
2263
2330
|
lines.push(`CASE ${responseVar}->status( ).`);
|
|
2264
2331
|
const success = pickSuccessStatus(operation.responses);
|
|
2265
|
-
const successConsumedOthers = success
|
|
2266
|
-
if (success !== void 0 && !successConsumedOthers) {
|
|
2267
|
-
lines.push(` WHEN ${success.whenLabel}.`);
|
|
2268
|
-
lines.push(` ${renderSuccessBody(opts)}`);
|
|
2269
|
-
}
|
|
2332
|
+
const successConsumedOthers = success?.whenLabel === "OTHERS";
|
|
2333
|
+
if (success !== void 0 && !successConsumedOthers) lines.push(` WHEN ${success.whenLabel}.`, ` ${renderSuccessBody(opts)}`);
|
|
2270
2334
|
for (const resp of operation.responses) {
|
|
2271
2335
|
if (!resp.isError) continue;
|
|
2272
2336
|
if (resp.statusCode === "default") continue;
|
|
2273
2337
|
if (!/^\d+$/.test(resp.statusCode)) continue;
|
|
2274
2338
|
lines.push(...renderErrorBranch(resp.statusCode, resp.description, opts));
|
|
2275
2339
|
}
|
|
2276
|
-
if (successConsumedOthers) {
|
|
2277
|
-
|
|
2278
|
-
lines.push(` ${renderSuccessBody(opts)}`);
|
|
2279
|
-
} else {
|
|
2340
|
+
if (successConsumedOthers) lines.push(` WHEN OTHERS.`, ` ${renderSuccessBody(opts)}`);
|
|
2341
|
+
else {
|
|
2280
2342
|
const defaultResp = operation.responses.find((r) => r.statusCode === "default");
|
|
2281
|
-
const description = defaultResp
|
|
2343
|
+
const description = defaultResp?.isError ? defaultResp.description : void 0;
|
|
2282
2344
|
lines.push(...renderOthersBranch(description, opts));
|
|
2283
2345
|
}
|
|
2284
2346
|
lines.push(`ENDCASE.`);
|
|
@@ -2353,7 +2415,7 @@ function buildClasXml(className, description, language) {
|
|
|
2353
2415
|
`;
|
|
2354
2416
|
}
|
|
2355
2417
|
function escapeXml(value) {
|
|
2356
|
-
return value.replaceAll(
|
|
2418
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
2357
2419
|
}
|
|
2358
2420
|
async function writeAbapgitLayout(artifact, outDir) {
|
|
2359
2421
|
assertValidClassName(artifact.className);
|
|
@@ -2575,15 +2637,13 @@ function writeLayout(artifact, format, outDir) {
|
|
|
2575
2637
|
}
|
|
2576
2638
|
async function writeClientBundle(artifacts, format, outDir) {
|
|
2577
2639
|
const all = /* @__PURE__ */ new Set();
|
|
2578
|
-
|
|
2640
|
+
const layouts = await Promise.all([
|
|
2579
2641
|
artifacts.types,
|
|
2580
2642
|
artifacts.operations,
|
|
2581
2643
|
artifacts.exception,
|
|
2582
2644
|
artifacts.implementation
|
|
2583
|
-
])
|
|
2584
|
-
|
|
2585
|
-
for (const f of r.files) all.add(f);
|
|
2586
|
-
}
|
|
2645
|
+
].map((artifact) => writeLayout(artifact, format, outDir)));
|
|
2646
|
+
for (const r of layouts) for (const f of r.files) all.add(f);
|
|
2587
2647
|
return { files: [...all].sort((a, b) => a.localeCompare(b)) };
|
|
2588
2648
|
}
|
|
2589
2649
|
|
|
@@ -2693,8 +2753,7 @@ function renderFetchCall(mapping, bodyIsBinary, jsonLocalClass) {
|
|
|
2693
2753
|
args.push({
|
|
2694
2754
|
key: "method",
|
|
2695
2755
|
value: `'${mapping.method}'`
|
|
2696
|
-
}
|
|
2697
|
-
args.push({
|
|
2756
|
+
}, {
|
|
2698
2757
|
key: "path",
|
|
2699
2758
|
value: renderPathValue(mapping)
|
|
2700
2759
|
});
|
|
@@ -2934,4 +2993,4 @@ async function generate(options) {
|
|
|
2934
2993
|
}
|
|
2935
2994
|
|
|
2936
2995
|
export { makeNameAllocator as C, isRef as D, normalizeSpec as E, UnsupportedSchemaError as S, loadSpec as T, mapSchemaToTypeDef as _, writeGctsLayout as a, CollisionError as b, mapResponseHandling as c, emitOperationsInterface as d, PolymorphismConflictError as f, mapPrimitive as g, resolveNames as h, writeGctsInterface as i, emitLocalClasses as l, NamesConfigError as m, writeClientBundle as n, writeAbapgitInterface as o, emitTypesInterface as p, writeLayout as r, writeAbapgitLayout as s, generate as t, emitExceptionClass as u, mapSchemaToTypeRef as v, sanitizeIdent as w, CyclicTypeError as x, planTypes as y };
|
|
2937
|
-
//# sourceMappingURL=generate-
|
|
2996
|
+
//# sourceMappingURL=generate-BevNTSFF.mjs.map
|