@abapify/adt-plugin-abapgit 0.4.0 → 0.4.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/dist/index.mjs ADDED
@@ -0,0 +1,4518 @@
1
+ import { createPlugin, registerFormatPlugin } from "@abapify/adt-plugin";
2
+ import { AdkClass, AdkDataElement, AdkDomain, AdkFunctionGroup, AdkInterface, AdkPackage, AdkProgram, AdkStructure, AdkTable, AdkTableType, createAdk, getMainType, getTypeForKind } from "@abapify/adk";
3
+ import { typedSchema } from "@abapify/ts-xsd";
4
+ import { parse } from "@abapify/acds";
5
+ import { tablesettings } from "@abapify/adt-schemas";
6
+ import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
7
+ import { basename, join, relative } from "path";
8
+ import { createAbapGitResolver as createFindingResolver } from "@abapify/adt-atc";
9
+
10
+ //#region src/lib/handlers/xml-format.ts
11
+ /**
12
+ * XML formatting utilities for abapGit serialization.
13
+ *
14
+ * Centralizes XML post-processing that was previously duplicated
15
+ * across base.ts, fugr.ts, tabl.ts, and roundtrip.ts.
16
+ *
17
+ * Uses indexOf-based parsing instead of regex to avoid
18
+ * super-linear backtracking (SonarQube S5852).
19
+ */
20
+ /**
21
+ * Extract `name="value"` attribute pairs from an XML attribute string
22
+ * using indexOf-based scanning (no regex).
23
+ */
24
+ function extractAttributes(content) {
25
+ const attrs = [];
26
+ let i = 0;
27
+ while (i < content.length) {
28
+ while (i < content.length && (content[i] === " " || content[i] === "\n" || content[i] === " ")) i++;
29
+ if (i >= content.length) break;
30
+ const eqIdx = content.indexOf("=", i);
31
+ if (eqIdx === -1) break;
32
+ const openQuote = content.indexOf("\"", eqIdx + 1);
33
+ if (openQuote === -1) break;
34
+ const closeQuote = content.indexOf("\"", openQuote + 1);
35
+ if (closeQuote === -1) break;
36
+ attrs.push(content.slice(i, closeQuote + 1));
37
+ i = closeQuote + 1;
38
+ }
39
+ return attrs;
40
+ }
41
+ /**
42
+ * Format XML attributes on separate lines for better diff readability.
43
+ *
44
+ * Turns `<tag a="1" b="2">` into:
45
+ * ```
46
+ * <tag
47
+ * a="1"
48
+ * b="2"
49
+ * >
50
+ * ```
51
+ *
52
+ * Uses indexOf-based scanning to avoid regex backtracking (S5852).
53
+ */
54
+ function formatXmlAttributes(xml) {
55
+ let result = "";
56
+ let pos = 0;
57
+ while (pos < xml.length) {
58
+ const openBracket = xml.indexOf("<", pos);
59
+ if (openBracket === -1) {
60
+ result += xml.slice(pos);
61
+ break;
62
+ }
63
+ result += xml.slice(pos, openBracket);
64
+ const closeBracket = xml.indexOf(">", openBracket);
65
+ if (closeBracket === -1) {
66
+ result += xml.slice(openBracket);
67
+ break;
68
+ }
69
+ const tagContent = xml.slice(openBracket + 1, closeBracket);
70
+ const spaceIdx = tagContent.indexOf(" ");
71
+ if (spaceIdx === -1 || tagContent[0] === "/" || tagContent[0] === "!" || tagContent[0] === "?") {
72
+ result += xml.slice(openBracket, closeBracket + 1);
73
+ pos = closeBracket + 1;
74
+ continue;
75
+ }
76
+ const tag = tagContent.slice(0, spaceIdx);
77
+ const attrPart = tagContent.slice(spaceIdx + 1);
78
+ const isSelfClosing = attrPart.trimEnd().endsWith("/");
79
+ const attrs = extractAttributes(isSelfClosing ? attrPart.slice(0, attrPart.lastIndexOf("/")) : attrPart);
80
+ if (attrs.length === 0) result += xml.slice(openBracket, closeBracket + 1);
81
+ else {
82
+ const attrsJoined = attrs.map((a) => `\n ${a}`).join("");
83
+ result += `<${tag}${attrsJoined}\n${isSelfClosing ? "/" : ""}>`;
84
+ }
85
+ pos = closeBracket + 1;
86
+ }
87
+ return result;
88
+ }
89
+ /**
90
+ * Move `xmlns:asx` declaration from root `<abapGit>` to nested `<asx:abap>`.
91
+ *
92
+ * Uses indexOf-based approach instead of regex to avoid backtracking on
93
+ * the `[\s\S]*?` pattern that SonarQube flags.
94
+ */
95
+ function moveNamespaceToAbap(xml) {
96
+ const nsDecl = " xmlns:asx=\"http://www.sap.com/abapxml\"";
97
+ const nsIdx = xml.indexOf(nsDecl);
98
+ if (nsIdx === -1) return xml;
99
+ if (xml.lastIndexOf("<abapGit", nsIdx) === -1) return xml;
100
+ const stripped = xml.slice(0, nsIdx) + xml.slice(nsIdx + 39);
101
+ const asxIdx = stripped.indexOf("<asx:abap");
102
+ if (asxIdx === -1) return stripped;
103
+ return stripped.slice(0, asxIdx + 9) + "\n " + nsDecl.trim() + stripped.slice(asxIdx + 9);
104
+ }
105
+ /**
106
+ * Apply standard abapGit XML formatting:
107
+ * 1. Format attributes on separate lines
108
+ * 2. Move xmlns:asx to asx:abap element
109
+ */
110
+ function formatAbapGitXml(xml) {
111
+ return moveNamespaceToAbap(formatXmlAttributes(xml));
112
+ }
113
+
114
+ //#endregion
115
+ //#region src/lib/handlers/base.ts
116
+ const handlerRegistry = /* @__PURE__ */ new Map();
117
+ /**
118
+ * Get handler for object type
119
+ *
120
+ * Tries the full type first (e.g., 'TABL/DS'), then falls back to the
121
+ * main type (e.g., 'CLAS/OC' → 'CLAS'). This matches ADK's resolveType()
122
+ * behaviour and handles quickSearch results that return subtypes.
123
+ */
124
+ function getHandler(type) {
125
+ return handlerRegistry.get(type) ?? handlerRegistry.get(getMainType(type));
126
+ }
127
+ /**
128
+ * Check if object type is supported
129
+ *
130
+ * Tries the full type first, then falls back to the main type.
131
+ */
132
+ function isSupported(type) {
133
+ return handlerRegistry.has(type) || handlerRegistry.has(getMainType(type));
134
+ }
135
+ /**
136
+ * Get all supported object types
137
+ */
138
+ function getSupportedTypes() {
139
+ return [...handlerRegistry.keys()];
140
+ }
141
+ /**
142
+ * Create an object handler
143
+ *
144
+ * @param adkClassOrType - ADK object class or ABAP type string
145
+ * @param definition - Handler definition with schema, toAbapGit, serialize
146
+ * @returns ObjectHandler that is auto-registered
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * // With ADK class (preferred)
151
+ * import { AdkPackage } from '@abapify/adk';
152
+ * export const packageHandler = createHandler(AdkPackage, { ... });
153
+ *
154
+ * // With ABAP type string (for objects without ADK class)
155
+ * export const dataElementHandler = createHandler('DTEL', { ... });
156
+ * ```
157
+ */
158
+ function createHandler(adkClassOrType, definition) {
159
+ let type;
160
+ if (typeof adkClassOrType === "string") type = adkClassOrType;
161
+ else {
162
+ const kind = adkClassOrType.kind;
163
+ const derivedType = getTypeForKind(kind);
164
+ if (!derivedType) throw new Error(`Unknown ADK kind: ${kind}. Make sure the ADK class has a static 'kind' property.`);
165
+ type = derivedType;
166
+ }
167
+ const fileExtension = getMainType(type).toLowerCase();
168
+ const ctx = {
169
+ type,
170
+ fileExtension,
171
+ getObjectName(object) {
172
+ return object.name.toLowerCase();
173
+ },
174
+ getData(object) {
175
+ return object.dataSync;
176
+ },
177
+ async resolveContent(content) {
178
+ if (!content) return "";
179
+ if (typeof content === "string") return content;
180
+ if (typeof content === "function") return await content();
181
+ return "";
182
+ },
183
+ toAbapGitXml(object) {
184
+ const fullPayload = {
185
+ abap: {
186
+ version: "1.0",
187
+ values: definition.toAbapGit(object)
188
+ },
189
+ version: definition.version,
190
+ serializer: definition.serializer,
191
+ serializer_version: definition.serializer_version
192
+ };
193
+ return formatAbapGitXml(definition.schema.build(fullPayload, { pretty: true }));
194
+ },
195
+ createFile(path, content, encoding) {
196
+ return {
197
+ path,
198
+ content,
199
+ encoding
200
+ };
201
+ },
202
+ createXmlFile(objectName, xmlContent) {
203
+ return {
204
+ path: `${objectName}.${fileExtension}.xml`,
205
+ content: xmlContent
206
+ };
207
+ },
208
+ createAbapFile(objectName, content, suffix) {
209
+ return {
210
+ path: suffix ? `${objectName}.${fileExtension}.${suffix}.abap` : `${objectName}.${fileExtension}.abap`,
211
+ content
212
+ };
213
+ }
214
+ };
215
+ const defaultSerialize = async (object) => {
216
+ const objectName = ctx.getObjectName(object);
217
+ const files = [];
218
+ if (definition.getSources) {
219
+ const rawSources = definition.getSources(object);
220
+ const sources = await Promise.all(rawSources.map(async ({ suffix, content }) => ({
221
+ suffix,
222
+ content: await content
223
+ })));
224
+ for (const { suffix, content } of sources) if (content) files.push(ctx.createAbapFile(objectName, content, suffix));
225
+ } else if (definition.getSource) {
226
+ const source = await definition.getSource(object);
227
+ files.push(ctx.createAbapFile(objectName, source));
228
+ }
229
+ const xmlContent = ctx.toAbapGitXml(object);
230
+ let xmlFileName;
231
+ if (definition.xmlFileName) xmlFileName = typeof definition.xmlFileName === "function" ? definition.xmlFileName(object, ctx) : definition.xmlFileName;
232
+ else xmlFileName = `${objectName}.${fileExtension}.xml`;
233
+ files.push(ctx.createFile(xmlFileName, xmlContent));
234
+ return files;
235
+ };
236
+ const defaultFromAbapGit = definition.fromAbapGit ? (values) => {
237
+ return definition.fromAbapGit(values);
238
+ } : void 0;
239
+ const handler = {
240
+ type,
241
+ fileExtension,
242
+ schema: definition.schema,
243
+ suffixToSourceKey: definition.suffixToSourceKey,
244
+ serialize: definition.serialize ? (object) => definition.serialize(object, ctx) : defaultSerialize,
245
+ fromAbapGit: defaultFromAbapGit,
246
+ setSources: definition.setSources
247
+ };
248
+ handlerRegistry.set(type, handler);
249
+ return handler;
250
+ }
251
+
252
+ //#endregion
253
+ //#region src/lib/handlers/abapgit-schema.ts
254
+ /**
255
+ * AbapGit Schema - extends TypedSchema with values type
256
+ *
257
+ * Provides both:
258
+ * - _type: Full AbapGitType (for XML build/parse)
259
+ * - _values: Inner values type (for handler mapping)
260
+ */
261
+ /**
262
+ * Create an AbapGit typed schema wrapper from raw schema
263
+ *
264
+ * @param rawSchema - Raw schema literal (with `as const`)
265
+ * @returns AbapGitSchema with both _type and _values
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * import _devc from './schemas/devc';
270
+ *
271
+ * const devc = abapGitSchema<DevcAbapGitType, DevcType>(_devc);
272
+ *
273
+ * // Access types:
274
+ * type Full = typeof devc._type; // DevcAbapGitType
275
+ * type Values = typeof devc._values; // DevcType
276
+ * ```
277
+ */
278
+ function abapGitSchema(rawSchema) {
279
+ const base = typedSchema(rawSchema);
280
+ return {
281
+ _type: base._type,
282
+ _values: null,
283
+ schema: base.schema,
284
+ parse: base.parse,
285
+ build: base.build
286
+ };
287
+ }
288
+
289
+ //#endregion
290
+ //#region src/schemas/generated/schemas/clas.ts
291
+ /**
292
+ * Auto-generated schema from XSD
293
+ *
294
+ * DO NOT EDIT - Generated by ts-xsd codegen
295
+ * Source: abapgit/clas.xsd
296
+ */
297
+ var clas_default = {
298
+ $xmlns: {
299
+ xs: "http://www.w3.org/2001/XMLSchema",
300
+ asx: "http://www.sap.com/abapxml"
301
+ },
302
+ targetNamespace: "http://www.sap.com/abapxml",
303
+ elementFormDefault: "unqualified",
304
+ element: [
305
+ {
306
+ name: "abapGit",
307
+ complexType: {
308
+ sequence: { element: [{ ref: "asx:abap" }] },
309
+ attribute: [
310
+ {
311
+ name: "version",
312
+ type: "xs:string",
313
+ use: "required"
314
+ },
315
+ {
316
+ name: "serializer",
317
+ type: "xs:string",
318
+ use: "required"
319
+ },
320
+ {
321
+ name: "serializer_version",
322
+ type: "xs:string",
323
+ use: "required"
324
+ }
325
+ ]
326
+ }
327
+ },
328
+ {
329
+ name: "Schema",
330
+ abstract: true
331
+ },
332
+ {
333
+ name: "values",
334
+ type: "asx:AbapValuesType"
335
+ },
336
+ {
337
+ name: "abap",
338
+ type: "asx:AbapType"
339
+ }
340
+ ],
341
+ complexType: [
342
+ {
343
+ name: "AbapValuesType",
344
+ all: { element: [{
345
+ name: "VSEOCLASS",
346
+ type: "asx:VseoClassType",
347
+ minOccurs: "0"
348
+ }] }
349
+ },
350
+ {
351
+ name: "VseoClassType",
352
+ all: { element: [
353
+ {
354
+ name: "CLSNAME",
355
+ type: "xs:string"
356
+ },
357
+ {
358
+ name: "LANGU",
359
+ type: "xs:string",
360
+ minOccurs: "0"
361
+ },
362
+ {
363
+ name: "DESCRIPT",
364
+ type: "xs:string",
365
+ minOccurs: "0"
366
+ },
367
+ {
368
+ name: "STATE",
369
+ type: "xs:string",
370
+ minOccurs: "0"
371
+ },
372
+ {
373
+ name: "CATEGORY",
374
+ type: "xs:string",
375
+ minOccurs: "0"
376
+ },
377
+ {
378
+ name: "EXPOSURE",
379
+ type: "xs:string",
380
+ minOccurs: "0"
381
+ },
382
+ {
383
+ name: "CLSFINAL",
384
+ type: "xs:string",
385
+ minOccurs: "0"
386
+ },
387
+ {
388
+ name: "CLSABSTRCT",
389
+ type: "xs:string",
390
+ minOccurs: "0"
391
+ },
392
+ {
393
+ name: "CLSCCINCL",
394
+ type: "xs:string",
395
+ minOccurs: "0"
396
+ },
397
+ {
398
+ name: "FIXPT",
399
+ type: "xs:string",
400
+ minOccurs: "0"
401
+ },
402
+ {
403
+ name: "UNICODE",
404
+ type: "xs:string",
405
+ minOccurs: "0"
406
+ },
407
+ {
408
+ name: "WITH_UNIT_TESTS",
409
+ type: "xs:string",
410
+ minOccurs: "0"
411
+ },
412
+ {
413
+ name: "DURATION",
414
+ type: "xs:string",
415
+ minOccurs: "0"
416
+ },
417
+ {
418
+ name: "RISK",
419
+ type: "xs:string",
420
+ minOccurs: "0"
421
+ },
422
+ {
423
+ name: "MSG_ID",
424
+ type: "xs:string",
425
+ minOccurs: "0"
426
+ },
427
+ {
428
+ name: "REFCLSNAME",
429
+ type: "xs:string",
430
+ minOccurs: "0"
431
+ },
432
+ {
433
+ name: "SHRM_ENABLED",
434
+ type: "xs:string",
435
+ minOccurs: "0"
436
+ },
437
+ {
438
+ name: "ABAP_LANGUAGE_VERSION",
439
+ type: "xs:string",
440
+ minOccurs: "0"
441
+ }
442
+ ] }
443
+ },
444
+ {
445
+ name: "AbapType",
446
+ sequence: { element: [{ ref: "asx:values" }] },
447
+ attribute: [{
448
+ name: "version",
449
+ type: "xs:string",
450
+ "default": "1.0"
451
+ }]
452
+ }
453
+ ]
454
+ };
455
+
456
+ //#endregion
457
+ //#region src/schemas/generated/schemas/devc.ts
458
+ /**
459
+ * Auto-generated schema from XSD
460
+ *
461
+ * DO NOT EDIT - Generated by ts-xsd codegen
462
+ * Source: abapgit/devc.xsd
463
+ */
464
+ var devc_default = {
465
+ $xmlns: {
466
+ xs: "http://www.w3.org/2001/XMLSchema",
467
+ asx: "http://www.sap.com/abapxml"
468
+ },
469
+ targetNamespace: "http://www.sap.com/abapxml",
470
+ elementFormDefault: "unqualified",
471
+ element: [
472
+ {
473
+ name: "abapGit",
474
+ complexType: {
475
+ sequence: { element: [{ ref: "asx:abap" }] },
476
+ attribute: [
477
+ {
478
+ name: "version",
479
+ type: "xs:string",
480
+ use: "required"
481
+ },
482
+ {
483
+ name: "serializer",
484
+ type: "xs:string",
485
+ use: "required"
486
+ },
487
+ {
488
+ name: "serializer_version",
489
+ type: "xs:string",
490
+ use: "required"
491
+ }
492
+ ]
493
+ }
494
+ },
495
+ {
496
+ name: "Schema",
497
+ abstract: true
498
+ },
499
+ {
500
+ name: "values",
501
+ type: "asx:AbapValuesType"
502
+ },
503
+ {
504
+ name: "abap",
505
+ type: "asx:AbapType"
506
+ }
507
+ ],
508
+ complexType: [
509
+ {
510
+ name: "AbapValuesType",
511
+ all: { element: [{
512
+ name: "DEVC",
513
+ type: "asx:DevcType",
514
+ minOccurs: "0"
515
+ }] }
516
+ },
517
+ {
518
+ name: "DevcType",
519
+ all: { element: [{
520
+ name: "CTEXT",
521
+ type: "xs:string"
522
+ }] }
523
+ },
524
+ {
525
+ name: "AbapType",
526
+ sequence: { element: [{ ref: "asx:values" }] },
527
+ attribute: [{
528
+ name: "version",
529
+ type: "xs:string",
530
+ "default": "1.0"
531
+ }]
532
+ }
533
+ ]
534
+ };
535
+
536
+ //#endregion
537
+ //#region src/schemas/generated/schemas/doma.ts
538
+ /**
539
+ * Auto-generated schema from XSD
540
+ *
541
+ * DO NOT EDIT - Generated by ts-xsd codegen
542
+ * Source: abapgit/doma.xsd
543
+ */
544
+ var doma_default = {
545
+ $xmlns: {
546
+ xs: "http://www.w3.org/2001/XMLSchema",
547
+ asx: "http://www.sap.com/abapxml"
548
+ },
549
+ targetNamespace: "http://www.sap.com/abapxml",
550
+ elementFormDefault: "unqualified",
551
+ element: [
552
+ {
553
+ name: "abapGit",
554
+ complexType: {
555
+ sequence: { element: [{ ref: "asx:abap" }] },
556
+ attribute: [
557
+ {
558
+ name: "version",
559
+ type: "xs:string",
560
+ use: "required"
561
+ },
562
+ {
563
+ name: "serializer",
564
+ type: "xs:string",
565
+ use: "required"
566
+ },
567
+ {
568
+ name: "serializer_version",
569
+ type: "xs:string",
570
+ use: "required"
571
+ }
572
+ ]
573
+ }
574
+ },
575
+ {
576
+ name: "Schema",
577
+ abstract: true
578
+ },
579
+ {
580
+ name: "values",
581
+ type: "asx:AbapValuesType"
582
+ },
583
+ {
584
+ name: "abap",
585
+ type: "asx:AbapType"
586
+ }
587
+ ],
588
+ complexType: [
589
+ {
590
+ name: "AbapValuesType",
591
+ all: { element: [{
592
+ name: "DD01V",
593
+ type: "asx:Dd01vType",
594
+ minOccurs: "0"
595
+ }, {
596
+ name: "DD07V_TAB",
597
+ type: "asx:Dd07vTabType",
598
+ minOccurs: "0"
599
+ }] }
600
+ },
601
+ {
602
+ name: "Dd01vType",
603
+ all: { element: [
604
+ {
605
+ name: "DOMNAME",
606
+ type: "xs:string"
607
+ },
608
+ {
609
+ name: "DDLANGUAGE",
610
+ type: "xs:string",
611
+ minOccurs: "0"
612
+ },
613
+ {
614
+ name: "DATATYPE",
615
+ type: "xs:string",
616
+ minOccurs: "0"
617
+ },
618
+ {
619
+ name: "LENG",
620
+ type: "xs:string",
621
+ minOccurs: "0"
622
+ },
623
+ {
624
+ name: "OUTPUTLEN",
625
+ type: "xs:string",
626
+ minOccurs: "0"
627
+ },
628
+ {
629
+ name: "DECIMALS",
630
+ type: "xs:string",
631
+ minOccurs: "0"
632
+ },
633
+ {
634
+ name: "LOWERCASE",
635
+ type: "xs:string",
636
+ minOccurs: "0"
637
+ },
638
+ {
639
+ name: "SIGNFLAG",
640
+ type: "xs:string",
641
+ minOccurs: "0"
642
+ },
643
+ {
644
+ name: "VALEXI",
645
+ type: "xs:string",
646
+ minOccurs: "0"
647
+ },
648
+ {
649
+ name: "ENTITYTAB",
650
+ type: "xs:string",
651
+ minOccurs: "0"
652
+ },
653
+ {
654
+ name: "CONVEXIT",
655
+ type: "xs:string",
656
+ minOccurs: "0"
657
+ },
658
+ {
659
+ name: "DDTEXT",
660
+ type: "xs:string",
661
+ minOccurs: "0"
662
+ },
663
+ {
664
+ name: "DOMMASTER",
665
+ type: "xs:string",
666
+ minOccurs: "0"
667
+ }
668
+ ] }
669
+ },
670
+ {
671
+ name: "Dd07vType",
672
+ all: { element: [
673
+ {
674
+ name: "DOMNAME",
675
+ type: "xs:string",
676
+ minOccurs: "0"
677
+ },
678
+ {
679
+ name: "VALPOS",
680
+ type: "xs:string",
681
+ minOccurs: "0"
682
+ },
683
+ {
684
+ name: "DDLANGUAGE",
685
+ type: "xs:string",
686
+ minOccurs: "0"
687
+ },
688
+ {
689
+ name: "DOMVALUE_L",
690
+ type: "xs:string",
691
+ minOccurs: "0"
692
+ },
693
+ {
694
+ name: "DOMVALUE_H",
695
+ type: "xs:string",
696
+ minOccurs: "0"
697
+ },
698
+ {
699
+ name: "DDTEXT",
700
+ type: "xs:string",
701
+ minOccurs: "0"
702
+ }
703
+ ] }
704
+ },
705
+ {
706
+ name: "Dd07vTabType",
707
+ sequence: { element: [{
708
+ name: "DD07V",
709
+ type: "Dd07vType",
710
+ minOccurs: "0",
711
+ maxOccurs: "unbounded"
712
+ }] }
713
+ },
714
+ {
715
+ name: "AbapType",
716
+ sequence: { element: [{ ref: "asx:values" }] },
717
+ attribute: [{
718
+ name: "version",
719
+ type: "xs:string",
720
+ "default": "1.0"
721
+ }]
722
+ }
723
+ ]
724
+ };
725
+
726
+ //#endregion
727
+ //#region src/schemas/generated/schemas/dtel.ts
728
+ /**
729
+ * Auto-generated schema from XSD
730
+ *
731
+ * DO NOT EDIT - Generated by ts-xsd codegen
732
+ * Source: abapgit/dtel.xsd
733
+ */
734
+ var dtel_default = {
735
+ $xmlns: {
736
+ xs: "http://www.w3.org/2001/XMLSchema",
737
+ asx: "http://www.sap.com/abapxml"
738
+ },
739
+ targetNamespace: "http://www.sap.com/abapxml",
740
+ elementFormDefault: "unqualified",
741
+ element: [
742
+ {
743
+ name: "abapGit",
744
+ complexType: {
745
+ sequence: { element: [{ ref: "asx:abap" }] },
746
+ attribute: [
747
+ {
748
+ name: "version",
749
+ type: "xs:string",
750
+ use: "required"
751
+ },
752
+ {
753
+ name: "serializer",
754
+ type: "xs:string",
755
+ use: "required"
756
+ },
757
+ {
758
+ name: "serializer_version",
759
+ type: "xs:string",
760
+ use: "required"
761
+ }
762
+ ]
763
+ }
764
+ },
765
+ {
766
+ name: "Schema",
767
+ abstract: true
768
+ },
769
+ {
770
+ name: "values",
771
+ type: "asx:AbapValuesType"
772
+ },
773
+ {
774
+ name: "abap",
775
+ type: "asx:AbapType"
776
+ }
777
+ ],
778
+ complexType: [
779
+ {
780
+ name: "AbapValuesType",
781
+ all: { element: [{
782
+ name: "DD04V",
783
+ type: "asx:Dd04vType",
784
+ minOccurs: "0"
785
+ }] }
786
+ },
787
+ {
788
+ name: "Dd04vType",
789
+ sequence: { element: [
790
+ {
791
+ name: "ROLLNAME",
792
+ type: "xs:string"
793
+ },
794
+ {
795
+ name: "DDLANGUAGE",
796
+ type: "xs:string",
797
+ minOccurs: "0"
798
+ },
799
+ {
800
+ name: "DOMNAME",
801
+ type: "xs:string",
802
+ minOccurs: "0"
803
+ },
804
+ {
805
+ name: "HEADLEN",
806
+ type: "xs:string",
807
+ minOccurs: "0"
808
+ },
809
+ {
810
+ name: "SCRLEN1",
811
+ type: "xs:string",
812
+ minOccurs: "0"
813
+ },
814
+ {
815
+ name: "SCRLEN2",
816
+ type: "xs:string",
817
+ minOccurs: "0"
818
+ },
819
+ {
820
+ name: "SCRLEN3",
821
+ type: "xs:string",
822
+ minOccurs: "0"
823
+ },
824
+ {
825
+ name: "DDTEXT",
826
+ type: "xs:string",
827
+ minOccurs: "0"
828
+ },
829
+ {
830
+ name: "REPTEXT",
831
+ type: "xs:string",
832
+ minOccurs: "0"
833
+ },
834
+ {
835
+ name: "SCRTEXT_S",
836
+ type: "xs:string",
837
+ minOccurs: "0"
838
+ },
839
+ {
840
+ name: "SCRTEXT_M",
841
+ type: "xs:string",
842
+ minOccurs: "0"
843
+ },
844
+ {
845
+ name: "SCRTEXT_L",
846
+ type: "xs:string",
847
+ minOccurs: "0"
848
+ },
849
+ {
850
+ name: "DTELMASTER",
851
+ type: "xs:string",
852
+ minOccurs: "0"
853
+ },
854
+ {
855
+ name: "DATATYPE",
856
+ type: "xs:string",
857
+ minOccurs: "0"
858
+ },
859
+ {
860
+ name: "LENG",
861
+ type: "xs:string",
862
+ minOccurs: "0"
863
+ },
864
+ {
865
+ name: "DECIMALS",
866
+ type: "xs:string",
867
+ minOccurs: "0"
868
+ },
869
+ {
870
+ name: "OUTPUTLEN",
871
+ type: "xs:string",
872
+ minOccurs: "0"
873
+ },
874
+ {
875
+ name: "REFKIND",
876
+ type: "xs:string",
877
+ minOccurs: "0"
878
+ },
879
+ {
880
+ name: "REFTYPE",
881
+ type: "xs:string",
882
+ minOccurs: "0"
883
+ },
884
+ {
885
+ name: "ABAP_LANGUAGE_VERSION",
886
+ type: "xs:string",
887
+ minOccurs: "0"
888
+ }
889
+ ] }
890
+ },
891
+ {
892
+ name: "AbapType",
893
+ sequence: { element: [{ ref: "asx:values" }] },
894
+ attribute: [{
895
+ name: "version",
896
+ type: "xs:string",
897
+ "default": "1.0"
898
+ }]
899
+ }
900
+ ]
901
+ };
902
+
903
+ //#endregion
904
+ //#region src/schemas/generated/schemas/intf.ts
905
+ /**
906
+ * Auto-generated schema from XSD
907
+ *
908
+ * DO NOT EDIT - Generated by ts-xsd codegen
909
+ * Source: abapgit/intf.xsd
910
+ */
911
+ var intf_default = {
912
+ $xmlns: {
913
+ xs: "http://www.w3.org/2001/XMLSchema",
914
+ asx: "http://www.sap.com/abapxml"
915
+ },
916
+ targetNamespace: "http://www.sap.com/abapxml",
917
+ elementFormDefault: "unqualified",
918
+ element: [
919
+ {
920
+ name: "abapGit",
921
+ complexType: {
922
+ sequence: { element: [{ ref: "asx:abap" }] },
923
+ attribute: [
924
+ {
925
+ name: "version",
926
+ type: "xs:string",
927
+ use: "required"
928
+ },
929
+ {
930
+ name: "serializer",
931
+ type: "xs:string",
932
+ use: "required"
933
+ },
934
+ {
935
+ name: "serializer_version",
936
+ type: "xs:string",
937
+ use: "required"
938
+ }
939
+ ]
940
+ }
941
+ },
942
+ {
943
+ name: "Schema",
944
+ abstract: true
945
+ },
946
+ {
947
+ name: "values",
948
+ type: "asx:AbapValuesType"
949
+ },
950
+ {
951
+ name: "abap",
952
+ type: "asx:AbapType"
953
+ }
954
+ ],
955
+ complexType: [
956
+ {
957
+ name: "AbapValuesType",
958
+ all: { element: [{
959
+ name: "VSEOINTERF",
960
+ type: "asx:VseoInterfType",
961
+ minOccurs: "0"
962
+ }] }
963
+ },
964
+ {
965
+ name: "VseoInterfType",
966
+ all: { element: [
967
+ {
968
+ name: "CLSNAME",
969
+ type: "xs:string"
970
+ },
971
+ {
972
+ name: "LANGU",
973
+ type: "xs:string",
974
+ minOccurs: "0"
975
+ },
976
+ {
977
+ name: "DESCRIPT",
978
+ type: "xs:string",
979
+ minOccurs: "0"
980
+ },
981
+ {
982
+ name: "EXPOSURE",
983
+ type: "xs:string",
984
+ minOccurs: "0"
985
+ },
986
+ {
987
+ name: "STATE",
988
+ type: "xs:string",
989
+ minOccurs: "0"
990
+ },
991
+ {
992
+ name: "UNICODE",
993
+ type: "xs:string",
994
+ minOccurs: "0"
995
+ },
996
+ {
997
+ name: "ABAP_LANGUAGE_VERSION",
998
+ type: "xs:string",
999
+ minOccurs: "0"
1000
+ }
1001
+ ] }
1002
+ },
1003
+ {
1004
+ name: "AbapType",
1005
+ sequence: { element: [{ ref: "asx:values" }] },
1006
+ attribute: [{
1007
+ name: "version",
1008
+ type: "xs:string",
1009
+ "default": "1.0"
1010
+ }]
1011
+ }
1012
+ ]
1013
+ };
1014
+
1015
+ //#endregion
1016
+ //#region src/schemas/generated/schemas/prog.ts
1017
+ /**
1018
+ * Auto-generated schema from XSD
1019
+ *
1020
+ * DO NOT EDIT - Generated by ts-xsd codegen
1021
+ * Source: abapgit/prog.xsd
1022
+ */
1023
+ var prog_default = {
1024
+ $xmlns: {
1025
+ xs: "http://www.w3.org/2001/XMLSchema",
1026
+ asx: "http://www.sap.com/abapxml"
1027
+ },
1028
+ elementFormDefault: "unqualified",
1029
+ element: [{
1030
+ name: "abapGit",
1031
+ complexType: {
1032
+ sequence: { element: [{
1033
+ name: "abap",
1034
+ type: "ProgAbapType"
1035
+ }] },
1036
+ attribute: [
1037
+ {
1038
+ name: "version",
1039
+ type: "xs:string",
1040
+ use: "required"
1041
+ },
1042
+ {
1043
+ name: "serializer",
1044
+ type: "xs:string",
1045
+ use: "required"
1046
+ },
1047
+ {
1048
+ name: "serializer_version",
1049
+ type: "xs:string",
1050
+ use: "required"
1051
+ }
1052
+ ]
1053
+ }
1054
+ }, {
1055
+ name: "Schema",
1056
+ abstract: true
1057
+ }],
1058
+ complexType: [
1059
+ {
1060
+ name: "ProgValuesType",
1061
+ all: { element: [{
1062
+ name: "PROGDIR",
1063
+ type: "ProgdirType",
1064
+ minOccurs: "0"
1065
+ }, {
1066
+ name: "TPOOL",
1067
+ type: "TpoolType",
1068
+ minOccurs: "0"
1069
+ }] }
1070
+ },
1071
+ {
1072
+ name: "ProgAbapType",
1073
+ sequence: { element: [{
1074
+ name: "values",
1075
+ type: "ProgValuesType"
1076
+ }] },
1077
+ attribute: [{
1078
+ name: "version",
1079
+ type: "xs:string",
1080
+ "default": "1.0"
1081
+ }]
1082
+ },
1083
+ {
1084
+ name: "AbapValuesType",
1085
+ sequence: { element: [{
1086
+ ref: "asx:Schema",
1087
+ minOccurs: "0",
1088
+ maxOccurs: "unbounded"
1089
+ }] }
1090
+ },
1091
+ {
1092
+ name: "AbapType",
1093
+ sequence: { element: [{ ref: "asx:values" }] },
1094
+ attribute: [{
1095
+ name: "version",
1096
+ type: "xs:string",
1097
+ "default": "1.0"
1098
+ }]
1099
+ },
1100
+ {
1101
+ name: "ProgdirType",
1102
+ all: { element: [
1103
+ {
1104
+ name: "NAME",
1105
+ type: "xs:string"
1106
+ },
1107
+ {
1108
+ name: "STATE",
1109
+ type: "xs:string",
1110
+ minOccurs: "0"
1111
+ },
1112
+ {
1113
+ name: "SUBC",
1114
+ type: "xs:string",
1115
+ minOccurs: "0"
1116
+ },
1117
+ {
1118
+ name: "FIXPT",
1119
+ type: "xs:string",
1120
+ minOccurs: "0"
1121
+ },
1122
+ {
1123
+ name: "UNICODE",
1124
+ type: "xs:string",
1125
+ minOccurs: "0"
1126
+ },
1127
+ {
1128
+ name: "DTEFUNC",
1129
+ type: "xs:string",
1130
+ minOccurs: "0"
1131
+ },
1132
+ {
1133
+ name: "RLOAD",
1134
+ type: "xs:string",
1135
+ minOccurs: "0"
1136
+ },
1137
+ {
1138
+ name: "UCCHECK",
1139
+ type: "xs:string",
1140
+ minOccurs: "0"
1141
+ },
1142
+ {
1143
+ name: "ABAP_LANGUAGE_VERSION",
1144
+ type: "xs:string",
1145
+ minOccurs: "0"
1146
+ }
1147
+ ] }
1148
+ },
1149
+ {
1150
+ name: "TpoolItemType",
1151
+ all: { element: [
1152
+ {
1153
+ name: "ID",
1154
+ type: "xs:string"
1155
+ },
1156
+ {
1157
+ name: "ENTRY",
1158
+ type: "xs:string",
1159
+ minOccurs: "0"
1160
+ },
1161
+ {
1162
+ name: "LENGTH",
1163
+ type: "xs:string",
1164
+ minOccurs: "0"
1165
+ }
1166
+ ] }
1167
+ },
1168
+ {
1169
+ name: "TpoolType",
1170
+ sequence: { element: [{
1171
+ name: "item",
1172
+ type: "TpoolItemType",
1173
+ minOccurs: "0",
1174
+ maxOccurs: "unbounded"
1175
+ }] }
1176
+ }
1177
+ ]
1178
+ };
1179
+
1180
+ //#endregion
1181
+ //#region src/schemas/generated/schemas/fugr.ts
1182
+ /**
1183
+ * Auto-generated schema from XSD
1184
+ *
1185
+ * DO NOT EDIT - Generated by ts-xsd codegen
1186
+ * Source: abapgit/fugr.xsd
1187
+ */
1188
+ var fugr_default = {
1189
+ $xmlns: {
1190
+ xs: "http://www.w3.org/2001/XMLSchema",
1191
+ asx: "http://www.sap.com/abapxml"
1192
+ },
1193
+ elementFormDefault: "unqualified",
1194
+ element: [{
1195
+ name: "abapGit",
1196
+ complexType: {
1197
+ sequence: { element: [{
1198
+ name: "abap",
1199
+ type: "FugrAbapType"
1200
+ }] },
1201
+ attribute: [
1202
+ {
1203
+ name: "version",
1204
+ type: "xs:string",
1205
+ use: "required"
1206
+ },
1207
+ {
1208
+ name: "serializer",
1209
+ type: "xs:string",
1210
+ use: "required"
1211
+ },
1212
+ {
1213
+ name: "serializer_version",
1214
+ type: "xs:string",
1215
+ use: "required"
1216
+ }
1217
+ ]
1218
+ }
1219
+ }, {
1220
+ name: "Schema",
1221
+ abstract: true
1222
+ }],
1223
+ complexType: [
1224
+ {
1225
+ name: "FugrValuesType",
1226
+ all: { element: [
1227
+ {
1228
+ name: "AREAT",
1229
+ type: "xs:string",
1230
+ minOccurs: "0"
1231
+ },
1232
+ {
1233
+ name: "INCLUDES",
1234
+ type: "FugrIncludesType",
1235
+ minOccurs: "0"
1236
+ },
1237
+ {
1238
+ name: "FUNCTIONS",
1239
+ type: "FugrFunctionsType",
1240
+ minOccurs: "0"
1241
+ }
1242
+ ] }
1243
+ },
1244
+ {
1245
+ name: "FugrAbapType",
1246
+ sequence: { element: [{
1247
+ name: "values",
1248
+ type: "FugrValuesType"
1249
+ }] },
1250
+ attribute: [{
1251
+ name: "version",
1252
+ type: "xs:string",
1253
+ "default": "1.0"
1254
+ }]
1255
+ },
1256
+ {
1257
+ name: "AbapValuesType",
1258
+ sequence: { element: [{
1259
+ ref: "asx:Schema",
1260
+ minOccurs: "0",
1261
+ maxOccurs: "unbounded"
1262
+ }] }
1263
+ },
1264
+ {
1265
+ name: "AbapType",
1266
+ sequence: { element: [{ ref: "asx:values" }] },
1267
+ attribute: [{
1268
+ name: "version",
1269
+ type: "xs:string",
1270
+ "default": "1.0"
1271
+ }]
1272
+ },
1273
+ {
1274
+ name: "FugrParamType",
1275
+ all: { element: [
1276
+ {
1277
+ name: "PARAMETER",
1278
+ type: "xs:string",
1279
+ minOccurs: "0"
1280
+ },
1281
+ {
1282
+ name: "TYP",
1283
+ type: "xs:string",
1284
+ minOccurs: "0"
1285
+ },
1286
+ {
1287
+ name: "DBFIELD",
1288
+ type: "xs:string",
1289
+ minOccurs: "0"
1290
+ },
1291
+ {
1292
+ name: "DEFAULT",
1293
+ type: "xs:string",
1294
+ minOccurs: "0"
1295
+ },
1296
+ {
1297
+ name: "OPTIONAL",
1298
+ type: "xs:string",
1299
+ minOccurs: "0"
1300
+ },
1301
+ {
1302
+ name: "REFERENCE",
1303
+ type: "xs:string",
1304
+ minOccurs: "0"
1305
+ }
1306
+ ] }
1307
+ },
1308
+ {
1309
+ name: "FugrTableParamType",
1310
+ all: { element: [
1311
+ {
1312
+ name: "PARAMETER",
1313
+ type: "xs:string",
1314
+ minOccurs: "0"
1315
+ },
1316
+ {
1317
+ name: "DBSTRUCT",
1318
+ type: "xs:string",
1319
+ minOccurs: "0"
1320
+ },
1321
+ {
1322
+ name: "TYP",
1323
+ type: "xs:string",
1324
+ minOccurs: "0"
1325
+ },
1326
+ {
1327
+ name: "OPTIONAL",
1328
+ type: "xs:string",
1329
+ minOccurs: "0"
1330
+ }
1331
+ ] }
1332
+ },
1333
+ {
1334
+ name: "FugrExceptionType",
1335
+ all: { element: [{
1336
+ name: "EXCEPTION",
1337
+ type: "xs:string",
1338
+ minOccurs: "0"
1339
+ }] }
1340
+ },
1341
+ {
1342
+ name: "FugrDocParamType",
1343
+ all: { element: [
1344
+ {
1345
+ name: "PARAMETER",
1346
+ type: "xs:string",
1347
+ minOccurs: "0"
1348
+ },
1349
+ {
1350
+ name: "KIND",
1351
+ type: "xs:string",
1352
+ minOccurs: "0"
1353
+ },
1354
+ {
1355
+ name: "STEXT",
1356
+ type: "xs:string",
1357
+ minOccurs: "0"
1358
+ }
1359
+ ] }
1360
+ },
1361
+ {
1362
+ name: "FugrImportType",
1363
+ sequence: { element: [{
1364
+ name: "RSIMP",
1365
+ type: "FugrParamType",
1366
+ minOccurs: "0",
1367
+ maxOccurs: "unbounded"
1368
+ }] }
1369
+ },
1370
+ {
1371
+ name: "FugrExportType",
1372
+ sequence: { element: [{
1373
+ name: "RSEXP",
1374
+ type: "FugrParamType",
1375
+ minOccurs: "0",
1376
+ maxOccurs: "unbounded"
1377
+ }] }
1378
+ },
1379
+ {
1380
+ name: "FugrChangingType",
1381
+ sequence: { element: [{
1382
+ name: "RSCHA",
1383
+ type: "FugrParamType",
1384
+ minOccurs: "0",
1385
+ maxOccurs: "unbounded"
1386
+ }] }
1387
+ },
1388
+ {
1389
+ name: "FugrTablesType",
1390
+ sequence: { element: [{
1391
+ name: "RSTBL",
1392
+ type: "FugrTableParamType",
1393
+ minOccurs: "0",
1394
+ maxOccurs: "unbounded"
1395
+ }] }
1396
+ },
1397
+ {
1398
+ name: "FugrExceptionsType",
1399
+ sequence: { element: [{
1400
+ name: "RSEXC",
1401
+ type: "FugrExceptionType",
1402
+ minOccurs: "0",
1403
+ maxOccurs: "unbounded"
1404
+ }] }
1405
+ },
1406
+ {
1407
+ name: "FugrDocumentationType",
1408
+ sequence: { element: [{
1409
+ name: "RSFDO",
1410
+ type: "FugrDocParamType",
1411
+ minOccurs: "0",
1412
+ maxOccurs: "unbounded"
1413
+ }] }
1414
+ },
1415
+ {
1416
+ name: "FugrFunctionItemType",
1417
+ all: { element: [
1418
+ {
1419
+ name: "FUNCNAME",
1420
+ type: "xs:string"
1421
+ },
1422
+ {
1423
+ name: "GLOBAL_FLAG",
1424
+ type: "xs:string",
1425
+ minOccurs: "0"
1426
+ },
1427
+ {
1428
+ name: "REMOTE_CALL",
1429
+ type: "xs:string",
1430
+ minOccurs: "0"
1431
+ },
1432
+ {
1433
+ name: "UPDATE_TASK",
1434
+ type: "xs:string",
1435
+ minOccurs: "0"
1436
+ },
1437
+ {
1438
+ name: "SHORT_TEXT",
1439
+ type: "xs:string",
1440
+ minOccurs: "0"
1441
+ },
1442
+ {
1443
+ name: "REMOTE_BASXML",
1444
+ type: "xs:string",
1445
+ minOccurs: "0"
1446
+ },
1447
+ {
1448
+ name: "EXCEPTION_CLASSES",
1449
+ type: "xs:string",
1450
+ minOccurs: "0"
1451
+ },
1452
+ {
1453
+ name: "IMPORT",
1454
+ type: "FugrImportType",
1455
+ minOccurs: "0"
1456
+ },
1457
+ {
1458
+ name: "CHANGING",
1459
+ type: "FugrChangingType",
1460
+ minOccurs: "0"
1461
+ },
1462
+ {
1463
+ name: "EXPORT",
1464
+ type: "FugrExportType",
1465
+ minOccurs: "0"
1466
+ },
1467
+ {
1468
+ name: "TABLES",
1469
+ type: "FugrTablesType",
1470
+ minOccurs: "0"
1471
+ },
1472
+ {
1473
+ name: "EXCEPTION",
1474
+ type: "FugrExceptionsType",
1475
+ minOccurs: "0"
1476
+ },
1477
+ {
1478
+ name: "DOCUMENTATION",
1479
+ type: "FugrDocumentationType",
1480
+ minOccurs: "0"
1481
+ }
1482
+ ] }
1483
+ },
1484
+ {
1485
+ name: "FugrFunctionsType",
1486
+ sequence: { element: [{
1487
+ name: "item",
1488
+ type: "FugrFunctionItemType",
1489
+ minOccurs: "0",
1490
+ maxOccurs: "unbounded"
1491
+ }] }
1492
+ },
1493
+ {
1494
+ name: "FugrIncludesType",
1495
+ sequence: { element: [{
1496
+ name: "SOBJ_NAME",
1497
+ type: "xs:string",
1498
+ minOccurs: "0",
1499
+ maxOccurs: "unbounded"
1500
+ }] }
1501
+ }
1502
+ ]
1503
+ };
1504
+
1505
+ //#endregion
1506
+ //#region src/schemas/generated/schemas/tabl.ts
1507
+ /**
1508
+ * Auto-generated schema from XSD
1509
+ *
1510
+ * DO NOT EDIT - Generated by ts-xsd codegen
1511
+ * Source: abapgit/tabl.xsd
1512
+ */
1513
+ var tabl_default = {
1514
+ $xmlns: {
1515
+ xs: "http://www.w3.org/2001/XMLSchema",
1516
+ asx: "http://www.sap.com/abapxml"
1517
+ },
1518
+ targetNamespace: "http://www.sap.com/abapxml",
1519
+ elementFormDefault: "unqualified",
1520
+ element: [
1521
+ {
1522
+ name: "abapGit",
1523
+ complexType: {
1524
+ sequence: { element: [{ ref: "asx:abap" }] },
1525
+ attribute: [
1526
+ {
1527
+ name: "version",
1528
+ type: "xs:string",
1529
+ use: "required"
1530
+ },
1531
+ {
1532
+ name: "serializer",
1533
+ type: "xs:string",
1534
+ use: "required"
1535
+ },
1536
+ {
1537
+ name: "serializer_version",
1538
+ type: "xs:string",
1539
+ use: "required"
1540
+ }
1541
+ ]
1542
+ }
1543
+ },
1544
+ {
1545
+ name: "Schema",
1546
+ abstract: true
1547
+ },
1548
+ {
1549
+ name: "values",
1550
+ type: "asx:AbapValuesType"
1551
+ },
1552
+ {
1553
+ name: "abap",
1554
+ type: "asx:AbapType"
1555
+ }
1556
+ ],
1557
+ complexType: [
1558
+ {
1559
+ name: "AbapValuesType",
1560
+ all: { element: [
1561
+ {
1562
+ name: "DD02V",
1563
+ type: "asx:Dd02vType",
1564
+ minOccurs: "0"
1565
+ },
1566
+ {
1567
+ name: "DD09L",
1568
+ type: "asx:Dd09lType",
1569
+ minOccurs: "0"
1570
+ },
1571
+ {
1572
+ name: "DD03P_TABLE",
1573
+ type: "asx:Dd03pTableType",
1574
+ minOccurs: "0"
1575
+ },
1576
+ {
1577
+ name: "TABL_EXTRAS",
1578
+ type: "asx:TablExtrasType",
1579
+ minOccurs: "0"
1580
+ }
1581
+ ] }
1582
+ },
1583
+ {
1584
+ name: "Dd02vType",
1585
+ sequence: { element: [
1586
+ {
1587
+ name: "TABNAME",
1588
+ type: "xs:string"
1589
+ },
1590
+ {
1591
+ name: "DDLANGUAGE",
1592
+ type: "xs:string",
1593
+ minOccurs: "0"
1594
+ },
1595
+ {
1596
+ name: "TABCLASS",
1597
+ type: "xs:string",
1598
+ minOccurs: "0"
1599
+ },
1600
+ {
1601
+ name: "LANGDEP",
1602
+ type: "xs:string",
1603
+ minOccurs: "0"
1604
+ },
1605
+ {
1606
+ name: "CLIDEP",
1607
+ type: "xs:string",
1608
+ minOccurs: "0"
1609
+ },
1610
+ {
1611
+ name: "SQLTAB",
1612
+ type: "xs:string",
1613
+ minOccurs: "0"
1614
+ },
1615
+ {
1616
+ name: "DATCLASS",
1617
+ type: "xs:string",
1618
+ minOccurs: "0"
1619
+ },
1620
+ {
1621
+ name: "DDTEXT",
1622
+ type: "xs:string",
1623
+ minOccurs: "0"
1624
+ },
1625
+ {
1626
+ name: "MASTERLANG",
1627
+ type: "xs:string",
1628
+ minOccurs: "0"
1629
+ },
1630
+ {
1631
+ name: "BUFFERED",
1632
+ type: "xs:string",
1633
+ minOccurs: "0"
1634
+ },
1635
+ {
1636
+ name: "MATEFLAG",
1637
+ type: "xs:string",
1638
+ minOccurs: "0"
1639
+ },
1640
+ {
1641
+ name: "CONTFLAG",
1642
+ type: "xs:string",
1643
+ minOccurs: "0"
1644
+ },
1645
+ {
1646
+ name: "SHLPEXI",
1647
+ type: "xs:string",
1648
+ minOccurs: "0"
1649
+ },
1650
+ {
1651
+ name: "EXCLASS",
1652
+ type: "xs:string",
1653
+ minOccurs: "0"
1654
+ },
1655
+ {
1656
+ name: "AUTHCLASS",
1657
+ type: "xs:string",
1658
+ minOccurs: "0"
1659
+ }
1660
+ ] }
1661
+ },
1662
+ {
1663
+ name: "Dd09lType",
1664
+ sequence: { element: [
1665
+ {
1666
+ name: "TABNAME",
1667
+ type: "xs:string",
1668
+ minOccurs: "0"
1669
+ },
1670
+ {
1671
+ name: "AS4LOCAL",
1672
+ type: "xs:string",
1673
+ minOccurs: "0"
1674
+ },
1675
+ {
1676
+ name: "TABKAT",
1677
+ type: "xs:string",
1678
+ minOccurs: "0"
1679
+ },
1680
+ {
1681
+ name: "TABART",
1682
+ type: "xs:string",
1683
+ minOccurs: "0"
1684
+ },
1685
+ {
1686
+ name: "BUFALLOW",
1687
+ type: "xs:string",
1688
+ minOccurs: "0"
1689
+ },
1690
+ {
1691
+ name: "PUFFERUNG",
1692
+ type: "xs:string",
1693
+ minOccurs: "0"
1694
+ },
1695
+ {
1696
+ name: "SCHFELDANZ",
1697
+ type: "xs:string",
1698
+ minOccurs: "0"
1699
+ },
1700
+ {
1701
+ name: "PROTOKOLL",
1702
+ type: "xs:string",
1703
+ minOccurs: "0"
1704
+ },
1705
+ {
1706
+ name: "SPEESSION",
1707
+ type: "xs:string",
1708
+ minOccurs: "0"
1709
+ },
1710
+ {
1711
+ name: "UESSION",
1712
+ type: "xs:string",
1713
+ minOccurs: "0"
1714
+ },
1715
+ {
1716
+ name: "ROESSION",
1717
+ type: "xs:string",
1718
+ minOccurs: "0"
1719
+ }
1720
+ ] }
1721
+ },
1722
+ {
1723
+ name: "Dd03pType",
1724
+ sequence: { element: [
1725
+ {
1726
+ name: "FIELDNAME",
1727
+ type: "xs:string",
1728
+ minOccurs: "0"
1729
+ },
1730
+ {
1731
+ name: "POSITION",
1732
+ type: "xs:string",
1733
+ minOccurs: "0"
1734
+ },
1735
+ {
1736
+ name: "KEYFLAG",
1737
+ type: "xs:string",
1738
+ minOccurs: "0"
1739
+ },
1740
+ {
1741
+ name: "ROLLNAME",
1742
+ type: "xs:string",
1743
+ minOccurs: "0"
1744
+ },
1745
+ {
1746
+ name: "ADMINFIELD",
1747
+ type: "xs:string",
1748
+ minOccurs: "0"
1749
+ },
1750
+ {
1751
+ name: "INTTYPE",
1752
+ type: "xs:string",
1753
+ minOccurs: "0"
1754
+ },
1755
+ {
1756
+ name: "INTLEN",
1757
+ type: "xs:string",
1758
+ minOccurs: "0"
1759
+ },
1760
+ {
1761
+ name: "REFTABLE",
1762
+ type: "xs:string",
1763
+ minOccurs: "0"
1764
+ },
1765
+ {
1766
+ name: "REFFIELD",
1767
+ type: "xs:string",
1768
+ minOccurs: "0"
1769
+ },
1770
+ {
1771
+ name: "PRECFIELD",
1772
+ type: "xs:string",
1773
+ minOccurs: "0"
1774
+ },
1775
+ {
1776
+ name: "NOTNULL",
1777
+ type: "xs:string",
1778
+ minOccurs: "0"
1779
+ },
1780
+ {
1781
+ name: "DATATYPE",
1782
+ type: "xs:string",
1783
+ minOccurs: "0"
1784
+ },
1785
+ {
1786
+ name: "LENG",
1787
+ type: "xs:string",
1788
+ minOccurs: "0"
1789
+ },
1790
+ {
1791
+ name: "DECIMALS",
1792
+ type: "xs:string",
1793
+ minOccurs: "0"
1794
+ },
1795
+ {
1796
+ name: "DOMNAME",
1797
+ type: "xs:string",
1798
+ minOccurs: "0"
1799
+ },
1800
+ {
1801
+ name: "MASK",
1802
+ type: "xs:string",
1803
+ minOccurs: "0"
1804
+ },
1805
+ {
1806
+ name: "SHLPORIGIN",
1807
+ type: "xs:string",
1808
+ minOccurs: "0"
1809
+ },
1810
+ {
1811
+ name: "DDTEXT",
1812
+ type: "xs:string",
1813
+ minOccurs: "0"
1814
+ },
1815
+ {
1816
+ name: "COMPTYPE",
1817
+ type: "xs:string",
1818
+ minOccurs: "0"
1819
+ },
1820
+ {
1821
+ name: "TABNAME",
1822
+ type: "xs:string",
1823
+ minOccurs: "0"
1824
+ },
1825
+ {
1826
+ name: "DDLANGUAGE",
1827
+ type: "xs:string",
1828
+ minOccurs: "0"
1829
+ },
1830
+ {
1831
+ name: "CONRFLAG",
1832
+ type: "xs:string",
1833
+ minOccurs: "0"
1834
+ }
1835
+ ] }
1836
+ },
1837
+ {
1838
+ name: "Dd03pTableType",
1839
+ sequence: { element: [{
1840
+ name: "DD03P",
1841
+ type: "Dd03pType",
1842
+ minOccurs: "0",
1843
+ maxOccurs: "unbounded"
1844
+ }] }
1845
+ },
1846
+ {
1847
+ name: "TddatType",
1848
+ sequence: { element: [
1849
+ {
1850
+ name: "TABNAME",
1851
+ type: "xs:string",
1852
+ minOccurs: "0"
1853
+ },
1854
+ {
1855
+ name: "CCLASS",
1856
+ type: "xs:string",
1857
+ minOccurs: "0"
1858
+ },
1859
+ {
1860
+ name: "VIEWGRANT",
1861
+ type: "xs:string",
1862
+ minOccurs: "0"
1863
+ },
1864
+ {
1865
+ name: "TVDIR",
1866
+ type: "xs:string",
1867
+ minOccurs: "0"
1868
+ },
1869
+ {
1870
+ name: "GENERICRANGE",
1871
+ type: "xs:string",
1872
+ minOccurs: "0"
1873
+ }
1874
+ ] }
1875
+ },
1876
+ {
1877
+ name: "TablExtrasType",
1878
+ sequence: { element: [{
1879
+ name: "TDDAT",
1880
+ type: "TddatType",
1881
+ minOccurs: "0"
1882
+ }] }
1883
+ },
1884
+ {
1885
+ name: "AbapType",
1886
+ sequence: { element: [{ ref: "asx:values" }] },
1887
+ attribute: [{
1888
+ name: "version",
1889
+ type: "xs:string",
1890
+ "default": "1.0"
1891
+ }]
1892
+ }
1893
+ ]
1894
+ };
1895
+
1896
+ //#endregion
1897
+ //#region src/schemas/generated/schemas/ttyp.ts
1898
+ /**
1899
+ * Auto-generated schema from XSD
1900
+ *
1901
+ * DO NOT EDIT - Generated by ts-xsd codegen
1902
+ * Source: abapgit/ttyp.xsd
1903
+ */
1904
+ var ttyp_default = {
1905
+ $xmlns: {
1906
+ xs: "http://www.w3.org/2001/XMLSchema",
1907
+ asx: "http://www.sap.com/abapxml"
1908
+ },
1909
+ targetNamespace: "http://www.sap.com/abapxml",
1910
+ elementFormDefault: "unqualified",
1911
+ element: [
1912
+ {
1913
+ name: "abapGit",
1914
+ complexType: {
1915
+ sequence: { element: [{ ref: "asx:abap" }] },
1916
+ attribute: [
1917
+ {
1918
+ name: "version",
1919
+ type: "xs:string",
1920
+ use: "required"
1921
+ },
1922
+ {
1923
+ name: "serializer",
1924
+ type: "xs:string",
1925
+ use: "required"
1926
+ },
1927
+ {
1928
+ name: "serializer_version",
1929
+ type: "xs:string",
1930
+ use: "required"
1931
+ }
1932
+ ]
1933
+ }
1934
+ },
1935
+ {
1936
+ name: "Schema",
1937
+ abstract: true
1938
+ },
1939
+ {
1940
+ name: "values",
1941
+ type: "asx:AbapValuesType"
1942
+ },
1943
+ {
1944
+ name: "abap",
1945
+ type: "asx:AbapType"
1946
+ }
1947
+ ],
1948
+ complexType: [
1949
+ {
1950
+ name: "AbapValuesType",
1951
+ all: { element: [{
1952
+ name: "DD40V",
1953
+ type: "asx:Dd40vType",
1954
+ minOccurs: "0"
1955
+ }] }
1956
+ },
1957
+ {
1958
+ name: "Dd40vType",
1959
+ all: { element: [
1960
+ {
1961
+ name: "TYPENAME",
1962
+ type: "xs:string"
1963
+ },
1964
+ {
1965
+ name: "DDLANGUAGE",
1966
+ type: "xs:string",
1967
+ minOccurs: "0"
1968
+ },
1969
+ {
1970
+ name: "ROWTYPE",
1971
+ type: "xs:string",
1972
+ minOccurs: "0"
1973
+ },
1974
+ {
1975
+ name: "ROWKIND",
1976
+ type: "xs:string",
1977
+ minOccurs: "0"
1978
+ },
1979
+ {
1980
+ name: "DATATYPE",
1981
+ type: "xs:string",
1982
+ minOccurs: "0"
1983
+ },
1984
+ {
1985
+ name: "ACCESSMODE",
1986
+ type: "xs:string",
1987
+ minOccurs: "0"
1988
+ },
1989
+ {
1990
+ name: "KEYDEF",
1991
+ type: "xs:string",
1992
+ minOccurs: "0"
1993
+ },
1994
+ {
1995
+ name: "KEYKIND",
1996
+ type: "xs:string",
1997
+ minOccurs: "0"
1998
+ },
1999
+ {
2000
+ name: "GENERIC",
2001
+ type: "xs:string",
2002
+ minOccurs: "0"
2003
+ },
2004
+ {
2005
+ name: "LENG",
2006
+ type: "xs:string",
2007
+ minOccurs: "0"
2008
+ },
2009
+ {
2010
+ name: "DECIMALS",
2011
+ type: "xs:string",
2012
+ minOccurs: "0"
2013
+ },
2014
+ {
2015
+ name: "DDTEXT",
2016
+ type: "xs:string",
2017
+ minOccurs: "0"
2018
+ },
2019
+ {
2020
+ name: "TYPELEN",
2021
+ type: "xs:string",
2022
+ minOccurs: "0"
2023
+ },
2024
+ {
2025
+ name: "DEFFDNAME",
2026
+ type: "xs:string",
2027
+ minOccurs: "0"
2028
+ },
2029
+ {
2030
+ name: "ABAP_LANGUAGE_VERSION",
2031
+ type: "xs:string",
2032
+ minOccurs: "0"
2033
+ }
2034
+ ] }
2035
+ },
2036
+ {
2037
+ name: "AbapType",
2038
+ sequence: { element: [{ ref: "asx:values" }] },
2039
+ attribute: [{
2040
+ name: "version",
2041
+ type: "xs:string",
2042
+ "default": "1.0"
2043
+ }]
2044
+ }
2045
+ ]
2046
+ };
2047
+
2048
+ //#endregion
2049
+ //#region src/schemas/generated/schemas/bdef.ts
2050
+ /**
2051
+ * Auto-generated schema from XSD
2052
+ *
2053
+ * DO NOT EDIT - Generated by ts-xsd codegen
2054
+ * Source: abapgit/bdef.xsd
2055
+ */
2056
+ var bdef_default = {
2057
+ $xmlns: {
2058
+ xs: "http://www.w3.org/2001/XMLSchema",
2059
+ asx: "http://www.sap.com/abapxml"
2060
+ },
2061
+ elementFormDefault: "unqualified",
2062
+ element: [{
2063
+ name: "abapGit",
2064
+ complexType: {
2065
+ sequence: { element: [{
2066
+ name: "abap",
2067
+ type: "BdefAbapType"
2068
+ }] },
2069
+ attribute: [
2070
+ {
2071
+ name: "version",
2072
+ type: "xs:string",
2073
+ use: "required"
2074
+ },
2075
+ {
2076
+ name: "serializer",
2077
+ type: "xs:string",
2078
+ use: "required"
2079
+ },
2080
+ {
2081
+ name: "serializer_version",
2082
+ type: "xs:string",
2083
+ use: "required"
2084
+ }
2085
+ ]
2086
+ }
2087
+ }, {
2088
+ name: "Schema",
2089
+ abstract: true
2090
+ }],
2091
+ complexType: [
2092
+ {
2093
+ name: "SkeyType",
2094
+ all: { element: [{
2095
+ name: "TYPE",
2096
+ type: "xs:string",
2097
+ minOccurs: "0"
2098
+ }, {
2099
+ name: "NAME",
2100
+ type: "xs:string",
2101
+ minOccurs: "0"
2102
+ }] }
2103
+ },
2104
+ {
2105
+ name: "BdefValuesType",
2106
+ all: { element: [{
2107
+ name: "SKEY",
2108
+ type: "SkeyType",
2109
+ minOccurs: "0"
2110
+ }] }
2111
+ },
2112
+ {
2113
+ name: "BdefAbapType",
2114
+ sequence: { element: [{
2115
+ name: "values",
2116
+ type: "BdefValuesType"
2117
+ }] },
2118
+ attribute: [{
2119
+ name: "version",
2120
+ type: "xs:string",
2121
+ "default": "1.0"
2122
+ }]
2123
+ },
2124
+ {
2125
+ name: "AbapValuesType",
2126
+ sequence: { element: [{
2127
+ ref: "asx:Schema",
2128
+ minOccurs: "0",
2129
+ maxOccurs: "unbounded"
2130
+ }] }
2131
+ },
2132
+ {
2133
+ name: "AbapType",
2134
+ sequence: { element: [{ ref: "asx:values" }] },
2135
+ attribute: [{
2136
+ name: "version",
2137
+ type: "xs:string",
2138
+ "default": "1.0"
2139
+ }]
2140
+ }
2141
+ ]
2142
+ };
2143
+
2144
+ //#endregion
2145
+ //#region src/schemas/generated/schemas/srvd.ts
2146
+ /**
2147
+ * Auto-generated schema from XSD
2148
+ *
2149
+ * DO NOT EDIT - Generated by ts-xsd codegen
2150
+ * Source: abapgit/srvd.xsd
2151
+ */
2152
+ var srvd_default = {
2153
+ $xmlns: {
2154
+ xs: "http://www.w3.org/2001/XMLSchema",
2155
+ asx: "http://www.sap.com/abapxml"
2156
+ },
2157
+ elementFormDefault: "unqualified",
2158
+ element: [{
2159
+ name: "abapGit",
2160
+ complexType: {
2161
+ sequence: { element: [{
2162
+ name: "abap",
2163
+ type: "SrvdAbapType"
2164
+ }] },
2165
+ attribute: [
2166
+ {
2167
+ name: "version",
2168
+ type: "xs:string",
2169
+ use: "required"
2170
+ },
2171
+ {
2172
+ name: "serializer",
2173
+ type: "xs:string",
2174
+ use: "required"
2175
+ },
2176
+ {
2177
+ name: "serializer_version",
2178
+ type: "xs:string",
2179
+ use: "required"
2180
+ }
2181
+ ]
2182
+ }
2183
+ }, {
2184
+ name: "Schema",
2185
+ abstract: true
2186
+ }],
2187
+ complexType: [
2188
+ {
2189
+ name: "SkeyType",
2190
+ all: { element: [{
2191
+ name: "TYPE",
2192
+ type: "xs:string",
2193
+ minOccurs: "0"
2194
+ }, {
2195
+ name: "NAME",
2196
+ type: "xs:string",
2197
+ minOccurs: "0"
2198
+ }] }
2199
+ },
2200
+ {
2201
+ name: "SrvdValuesType",
2202
+ all: { element: [{
2203
+ name: "SKEY",
2204
+ type: "SkeyType",
2205
+ minOccurs: "0"
2206
+ }] }
2207
+ },
2208
+ {
2209
+ name: "SrvdAbapType",
2210
+ sequence: { element: [{
2211
+ name: "values",
2212
+ type: "SrvdValuesType"
2213
+ }] },
2214
+ attribute: [{
2215
+ name: "version",
2216
+ type: "xs:string",
2217
+ "default": "1.0"
2218
+ }]
2219
+ },
2220
+ {
2221
+ name: "AbapValuesType",
2222
+ sequence: { element: [{
2223
+ ref: "asx:Schema",
2224
+ minOccurs: "0",
2225
+ maxOccurs: "unbounded"
2226
+ }] }
2227
+ },
2228
+ {
2229
+ name: "AbapType",
2230
+ sequence: { element: [{ ref: "asx:values" }] },
2231
+ attribute: [{
2232
+ name: "version",
2233
+ type: "xs:string",
2234
+ "default": "1.0"
2235
+ }]
2236
+ }
2237
+ ]
2238
+ };
2239
+
2240
+ //#endregion
2241
+ //#region src/schemas/generated/schemas/srvb.ts
2242
+ /**
2243
+ * Auto-generated schema from XSD
2244
+ *
2245
+ * DO NOT EDIT - Generated by ts-xsd codegen
2246
+ * Source: abapgit/srvb.xsd
2247
+ */
2248
+ var srvb_default = {
2249
+ $xmlns: {
2250
+ xs: "http://www.w3.org/2001/XMLSchema",
2251
+ asx: "http://www.sap.com/abapxml"
2252
+ },
2253
+ elementFormDefault: "unqualified",
2254
+ element: [{
2255
+ name: "abapGit",
2256
+ complexType: {
2257
+ sequence: { element: [{
2258
+ name: "abap",
2259
+ type: "SrvbAbapType"
2260
+ }] },
2261
+ attribute: [
2262
+ {
2263
+ name: "version",
2264
+ type: "xs:string",
2265
+ use: "required"
2266
+ },
2267
+ {
2268
+ name: "serializer",
2269
+ type: "xs:string",
2270
+ use: "required"
2271
+ },
2272
+ {
2273
+ name: "serializer_version",
2274
+ type: "xs:string",
2275
+ use: "required"
2276
+ }
2277
+ ]
2278
+ }
2279
+ }, {
2280
+ name: "Schema",
2281
+ abstract: true
2282
+ }],
2283
+ complexType: [
2284
+ {
2285
+ name: "SkeyType",
2286
+ all: { element: [{
2287
+ name: "TYPE",
2288
+ type: "xs:string",
2289
+ minOccurs: "0"
2290
+ }, {
2291
+ name: "NAME",
2292
+ type: "xs:string",
2293
+ minOccurs: "0"
2294
+ }] }
2295
+ },
2296
+ {
2297
+ name: "BindingType",
2298
+ all: { element: [
2299
+ {
2300
+ name: "TYPE",
2301
+ type: "xs:string",
2302
+ minOccurs: "0"
2303
+ },
2304
+ {
2305
+ name: "VERSION",
2306
+ type: "xs:string",
2307
+ minOccurs: "0"
2308
+ },
2309
+ {
2310
+ name: "CATEGORY",
2311
+ type: "xs:string",
2312
+ minOccurs: "0"
2313
+ }
2314
+ ] }
2315
+ },
2316
+ {
2317
+ name: "SrvbValuesType",
2318
+ all: { element: [{
2319
+ name: "SKEY",
2320
+ type: "SkeyType",
2321
+ minOccurs: "0"
2322
+ }, {
2323
+ name: "BINDING",
2324
+ type: "BindingType",
2325
+ minOccurs: "0"
2326
+ }] }
2327
+ },
2328
+ {
2329
+ name: "SrvbAbapType",
2330
+ sequence: { element: [{
2331
+ name: "values",
2332
+ type: "SrvbValuesType"
2333
+ }] },
2334
+ attribute: [{
2335
+ name: "version",
2336
+ type: "xs:string",
2337
+ "default": "1.0"
2338
+ }]
2339
+ },
2340
+ {
2341
+ name: "AbapValuesType",
2342
+ sequence: { element: [{
2343
+ ref: "asx:Schema",
2344
+ minOccurs: "0",
2345
+ maxOccurs: "unbounded"
2346
+ }] }
2347
+ },
2348
+ {
2349
+ name: "AbapType",
2350
+ sequence: { element: [{ ref: "asx:values" }] },
2351
+ attribute: [{
2352
+ name: "version",
2353
+ type: "xs:string",
2354
+ "default": "1.0"
2355
+ }]
2356
+ }
2357
+ ]
2358
+ };
2359
+
2360
+ //#endregion
2361
+ //#region src/schemas/generated/index.ts
2362
+ /**
2363
+ * AbapGit Typed Schemas
2364
+ *
2365
+ * Auto-generated by ts-xsd codegen - DO NOT EDIT
2366
+ *
2367
+ * Each schema provides:
2368
+ * - _type: Full AbapGitType (for XML build/parse)
2369
+ * - _values: Inner values type (for handler mapping)
2370
+ * - parse(xml) → fully typed object
2371
+ * - build(data) → XML string
2372
+ * - schema → raw schema literal
2373
+ */
2374
+ const clas = abapGitSchema(clas_default);
2375
+ const devc = abapGitSchema(devc_default);
2376
+ const doma = abapGitSchema(doma_default);
2377
+ const dtel = abapGitSchema(dtel_default);
2378
+ const intf = abapGitSchema(intf_default);
2379
+ const prog = abapGitSchema(prog_default);
2380
+ const fugr = abapGitSchema(fugr_default);
2381
+ const tabl = abapGitSchema(tabl_default);
2382
+ const ttyp = abapGitSchema(ttyp_default);
2383
+ const bdef = abapGitSchema(bdef_default);
2384
+ const srvd = abapGitSchema(srvd_default);
2385
+ const srvb = abapGitSchema(srvb_default);
2386
+
2387
+ //#endregion
2388
+ //#region src/lib/handlers/lang.ts
2389
+ /**
2390
+ * SAP 1-character language code ↔ ISO 639-1 mapping
2391
+ *
2392
+ * abapGit stores SAP internal 1-char codes (e.g. "E" for English).
2393
+ * SAP ADT REST API expects ISO 639-1 codes (e.g. "EN").
2394
+ */
2395
+ const SAP_TO_ISO = {
2396
+ E: "EN",
2397
+ D: "DE",
2398
+ F: "FR",
2399
+ I: "IT",
2400
+ S: "ES",
2401
+ P: "PT",
2402
+ J: "JA",
2403
+ K: "KO",
2404
+ "1": "ZH",
2405
+ W: "RU",
2406
+ T: "TR",
2407
+ N: "NL",
2408
+ H: "HU",
2409
+ L: "PL",
2410
+ Q: "CS",
2411
+ R: "SK",
2412
+ U: "SV",
2413
+ V: "DA",
2414
+ Y: "FI",
2415
+ X: "NO",
2416
+ G: "EL",
2417
+ B: "HE",
2418
+ A: "AR",
2419
+ "3": "TH",
2420
+ M: "UK",
2421
+ "6": "HR",
2422
+ O: "SL",
2423
+ "7": "BG",
2424
+ "8": "SR",
2425
+ C: "RO"
2426
+ };
2427
+ const ISO_TO_SAP = Object.fromEntries(Object.entries(SAP_TO_ISO).map(([k, v]) => [v, k]));
2428
+ /**
2429
+ * Convert SAP 1-char language code to ISO 639-1.
2430
+ * Returns the input uppercased if no mapping exists (may already be ISO).
2431
+ */
2432
+ function sapLangToIso(sapLang) {
2433
+ if (!sapLang) return "EN";
2434
+ const upper = sapLang.toUpperCase();
2435
+ if (upper.length >= 2) return upper;
2436
+ return SAP_TO_ISO[upper] ?? upper;
2437
+ }
2438
+ /**
2439
+ * Convert ISO 639-1 language code to SAP 1-char code.
2440
+ * Returns "E" (English) if no mapping exists.
2441
+ */
2442
+ function isoToSapLang(isoLang) {
2443
+ if (!isoLang) return "E";
2444
+ const upper = isoLang.toUpperCase();
2445
+ if (upper.length === 1) return upper;
2446
+ return ISO_TO_SAP[upper] ?? "E";
2447
+ }
2448
+ /**
2449
+ * abapGit numeric code → ADT API string value
2450
+ *
2451
+ * abapGit serializes ABAP_LANGUAGE_VERSION as a numeric string (e.g. "5").
2452
+ * SAP ADT REST API expects descriptive strings (e.g. "cloudDevelopment").
2453
+ */
2454
+ const ABAP_LANG_VER_TO_ADT = {
2455
+ "2": "keyUser",
2456
+ "5": "cloudDevelopment"
2457
+ };
2458
+ const ABAP_LANG_VER_FROM_ADT = Object.fromEntries(Object.entries(ABAP_LANG_VER_TO_ADT).map(([k, v]) => [v, k]));
2459
+ /**
2460
+ * Convert abapGit ABAP_LANGUAGE_VERSION code to ADT API value.
2461
+ * Returns undefined if not set or standard ABAP.
2462
+ * Passes through values that are already in ADT format (e.g. "cloudDevelopment").
2463
+ */
2464
+ function abapLangVerToAdt(abapGitCode) {
2465
+ if (!abapGitCode) return void 0;
2466
+ return ABAP_LANG_VER_TO_ADT[abapGitCode] ?? abapGitCode;
2467
+ }
2468
+ /**
2469
+ * Convert ADT API abapLanguageVersion to abapGit ABAP_LANGUAGE_VERSION code.
2470
+ * Returns undefined if not set or standard ABAP (default — should not be emitted).
2471
+ */
2472
+ function abapLangVerFromAdt(adtValue) {
2473
+ if (!adtValue) return void 0;
2474
+ if (adtValue === "standard" || adtValue === "X") return void 0;
2475
+ return ABAP_LANG_VER_FROM_ADT[adtValue] ?? adtValue;
2476
+ }
2477
+
2478
+ //#endregion
2479
+ //#region src/lib/handlers/objects/clas.ts
2480
+ /**
2481
+ * Class (CLAS) object handler for abapGit format
2482
+ */
2483
+ /**
2484
+ * Map ADK ClassIncludeType to abapGit file suffix convention
2485
+ * Used for serialization (SAP → Git)
2486
+ */
2487
+ const ABAPGIT_SUFFIX = {
2488
+ main: void 0,
2489
+ definitions: "locals_def",
2490
+ implementations: "locals_imp",
2491
+ localtypes: "locals_types",
2492
+ macros: "macros",
2493
+ testclasses: "testclasses"
2494
+ };
2495
+ /**
2496
+ * Reverse mapping: abapGit file suffix to ADK source key
2497
+ * Derived from ABAPGIT_SUFFIX to avoid duplication
2498
+ */
2499
+ const SUFFIX_TO_SOURCE_KEY = Object.fromEntries(Object.entries(ABAPGIT_SUFFIX).filter(([, suffix]) => suffix !== void 0).map(([key, suffix]) => [suffix, key]));
2500
+ /**
2501
+ * Map ADT category enum → abapGit numeric code
2502
+ * SAP ADT returns string names, abapGit uses numeric codes from SEOCLASSDF-CATEGORY
2503
+ */
2504
+ const CATEGORY_FROM_ADT = {
2505
+ generalObjectType: "00",
2506
+ exitClass: "01",
2507
+ testClass: "02",
2508
+ areaClass: "03",
2509
+ factoryClass: "04",
2510
+ persistentClass: "30",
2511
+ exceptionClass: "40",
2512
+ bspClass: "60",
2513
+ staticTypedLcpClass: "70",
2514
+ behaviorPool: "80",
2515
+ rfcProxyClass: "90",
2516
+ entityEventHandler: "100",
2517
+ communicationConnectionClass: "110"
2518
+ };
2519
+ /**
2520
+ * Map visibility to EXPOSURE code (ADK → abapGit)
2521
+ */
2522
+ const VISIBILITY_TO_EXPOSURE = {
2523
+ private: "0",
2524
+ protected: "1",
2525
+ public: "2"
2526
+ };
2527
+ /**
2528
+ * Reverse mapping: EXPOSURE code to visibility (abapGit → ADK)
2529
+ */
2530
+ const EXPOSURE_TO_VISIBILITY = Object.fromEntries(Object.entries(VISIBILITY_TO_EXPOSURE).map(([k, v]) => [v, k]));
2531
+ const classHandler = createHandler(AdkClass, {
2532
+ schema: clas,
2533
+ version: "v1.0.0",
2534
+ serializer: "LCL_OBJECT_CLAS",
2535
+ serializer_version: "v1.0.0",
2536
+ suffixToSourceKey: SUFFIX_TO_SOURCE_KEY,
2537
+ toAbapGit: (cls) => {
2538
+ const data = cls.dataSync;
2539
+ const hasTestClasses = (data.include ?? []).some((inc) => String(inc.includeType) === "testclasses") || data.hasTests === true || data.withUnitTests === true;
2540
+ const categoryCode = CATEGORY_FROM_ADT[data.category ?? ""] ?? data.category ?? "00";
2541
+ const exposureCode = VISIBILITY_TO_EXPOSURE[data.visibility ?? "public"] ?? "2";
2542
+ return { VSEOCLASS: {
2543
+ CLSNAME: cls.name ?? "",
2544
+ LANGU: isoToSapLang(data.language),
2545
+ DESCRIPT: data.description ?? "",
2546
+ STATE: "1",
2547
+ CATEGORY: categoryCode !== "00" ? categoryCode : void 0,
2548
+ EXPOSURE: exposureCode !== "2" ? exposureCode : void 0,
2549
+ CLSFINAL: data.final ? "X" : void 0,
2550
+ CLSABSTRCT: data.abstract ? "X" : void 0,
2551
+ SHRM_ENABLED: data.sharedMemoryEnabled ? "X" : void 0,
2552
+ CLSCCINCL: "X",
2553
+ FIXPT: data.fixPointArithmetic ? "X" : void 0,
2554
+ UNICODE: "X",
2555
+ REFCLSNAME: data.superClassRef?.name,
2556
+ MSG_ID: data.messageClassRef?.name,
2557
+ ABAP_LANGUAGE_VERSION: abapLangVerFromAdt(data.abapLanguageVersion),
2558
+ ...hasTestClasses ? { WITH_UNIT_TESTS: "X" } : {}
2559
+ } };
2560
+ },
2561
+ getSources: (cls) => {
2562
+ return (cls.dataSync.include ?? []).map((inc) => ({
2563
+ suffix: ABAPGIT_SUFFIX[String(inc.includeType ?? "main")],
2564
+ content: cls.getIncludeSource(String(inc.includeType ?? "main"))
2565
+ }));
2566
+ },
2567
+ fromAbapGit: ({ VSEOCLASS }) => ({
2568
+ name: (VSEOCLASS?.CLSNAME ?? "").toUpperCase(),
2569
+ type: "CLAS/OC",
2570
+ description: VSEOCLASS?.DESCRIPT,
2571
+ language: sapLangToIso(VSEOCLASS?.LANGU),
2572
+ masterLanguage: sapLangToIso(VSEOCLASS?.LANGU),
2573
+ category: VSEOCLASS?.CATEGORY,
2574
+ final: VSEOCLASS?.CLSFINAL === "X",
2575
+ abstract: VSEOCLASS?.CLSABSTRCT === "X",
2576
+ visibility: EXPOSURE_TO_VISIBILITY[VSEOCLASS?.EXPOSURE ?? "2"] ?? "public",
2577
+ sharedMemoryEnabled: VSEOCLASS?.SHRM_ENABLED === "X",
2578
+ fixPointArithmetic: VSEOCLASS?.FIXPT === "X",
2579
+ activeUnicodeCheck: VSEOCLASS?.UNICODE === "X",
2580
+ withUnitTests: VSEOCLASS?.WITH_UNIT_TESTS === "X",
2581
+ superClassRef: VSEOCLASS?.REFCLSNAME ? { name: VSEOCLASS.REFCLSNAME } : void 0,
2582
+ messageClassRef: VSEOCLASS?.MSG_ID ? { name: VSEOCLASS.MSG_ID } : void 0,
2583
+ abapLanguageVersion: abapLangVerToAdt(VSEOCLASS?.ABAP_LANGUAGE_VERSION)
2584
+ }),
2585
+ setSources: (cls, sources) => {
2586
+ cls._pendingSources = sources;
2587
+ if (sources.main) cls._pendingSource = sources.main;
2588
+ }
2589
+ });
2590
+
2591
+ //#endregion
2592
+ //#region src/lib/handlers/objects/intf.ts
2593
+ /**
2594
+ * Interface (INTF) object handler for abapGit format
2595
+ */
2596
+ const interfaceHandler = createHandler(AdkInterface, {
2597
+ schema: intf,
2598
+ version: "v1.0.0",
2599
+ serializer: "LCL_OBJECT_INTF",
2600
+ serializer_version: "v1.0.0",
2601
+ toAbapGit: (obj) => ({ VSEOINTERF: {
2602
+ CLSNAME: obj.name ?? "",
2603
+ LANGU: isoToSapLang(obj.dataSync?.language),
2604
+ DESCRIPT: obj.description ?? "",
2605
+ EXPOSURE: "2",
2606
+ STATE: "1",
2607
+ UNICODE: "X"
2608
+ } }),
2609
+ getSource: (obj) => obj.getSource(),
2610
+ fromAbapGit: ({ VSEOINTERF }) => ({
2611
+ name: (VSEOINTERF?.CLSNAME ?? "").toUpperCase(),
2612
+ type: "INTF/OI",
2613
+ description: VSEOINTERF?.DESCRIPT,
2614
+ language: sapLangToIso(VSEOINTERF?.LANGU),
2615
+ masterLanguage: sapLangToIso(VSEOINTERF?.LANGU),
2616
+ abapLanguageVersion: abapLangVerToAdt(VSEOINTERF?.ABAP_LANGUAGE_VERSION)
2617
+ }),
2618
+ setSources: (intf, sources) => {
2619
+ if (sources.main) intf._pendingSource = sources.main;
2620
+ }
2621
+ });
2622
+
2623
+ //#endregion
2624
+ //#region src/lib/handlers/objects/devc.ts
2625
+ /**
2626
+ * Package (DEVC) object handler for abapGit format
2627
+ */
2628
+ /**
2629
+ * Package handler for abapGit serialization
2630
+ *
2631
+ * Note: Packages in abapGit use "package.devc.xml" as filename,
2632
+ * not "$packagename.devc.xml"
2633
+ */
2634
+ const packageHandler = createHandler(AdkPackage, {
2635
+ schema: devc,
2636
+ version: "v1.0.0",
2637
+ serializer: "LCL_OBJECT_DEVC",
2638
+ serializer_version: "v1.0.0",
2639
+ xmlFileName: "package.devc.xml",
2640
+ toAbapGit: (pkg) => ({ DEVC: { CTEXT: pkg.description ?? "" } }),
2641
+ fromAbapGit: ({ DEVC }) => ({
2642
+ name: "",
2643
+ description: DEVC?.CTEXT
2644
+ })
2645
+ });
2646
+
2647
+ //#endregion
2648
+ //#region src/lib/handlers/objects/prog.ts
2649
+ /**
2650
+ * Program (PROG) object handler for abapGit format
2651
+ */
2652
+ const programHandler = createHandler(AdkProgram, {
2653
+ schema: prog,
2654
+ version: "v1.0.0",
2655
+ serializer: "LCL_OBJECT_PROG",
2656
+ serializer_version: "v1.0.0",
2657
+ toAbapGit: (obj) => ({ PROGDIR: {
2658
+ NAME: obj.name ?? "",
2659
+ STATE: "A",
2660
+ SUBC: "1",
2661
+ FIXPT: "X",
2662
+ UNICODE: "X"
2663
+ } }),
2664
+ getSource: (obj) => obj.getSource(),
2665
+ fromAbapGit: ({ PROGDIR, TPOOL }) => {
2666
+ const rawItems = TPOOL?.item ?? [];
2667
+ const descriptionEntry = (Array.isArray(rawItems) ? rawItems : [rawItems]).find((t) => t.ID === "R");
2668
+ const subc = String(PROGDIR?.SUBC ?? "");
2669
+ return {
2670
+ name: (PROGDIR?.NAME ?? "").toUpperCase(),
2671
+ type: "PROG/P",
2672
+ description: descriptionEntry?.ENTRY ?? "Program",
2673
+ fixPointArithmetic: PROGDIR?.FIXPT === "X",
2674
+ activeUnicodeCheck: PROGDIR?.UNICODE === "X",
2675
+ programType: subc === "1" ? "executableProgram" : "subroutinePool"
2676
+ };
2677
+ },
2678
+ setSources: (obj, sources) => {
2679
+ if (sources.main) obj._pendingSource = sources.main;
2680
+ }
2681
+ });
2682
+
2683
+ //#endregion
2684
+ //#region src/lib/handlers/objects/fugr.ts
2685
+ /**
2686
+ * Function Group (FUGR) object handler for abapGit format
2687
+ *
2688
+ * FUGR is a compound object — abapGit serializes it as multiple files:
2689
+ * {name}.fugr.xml — Main metadata (AREAT + INCLUDES + FUNCTIONS)
2690
+ * {name}.fugr.l{name}top.abap — TOP-include source (editable)
2691
+ * {name}.fugr.l{name}top.xml — TOP-include PROGDIR metadata
2692
+ * {name}.fugr.sapl{name}.abap — Main program source (system-generated)
2693
+ * {name}.fugr.sapl{name}.xml — Main program PROGDIR metadata
2694
+ * {name}.fugr.{funcname}.abap — Function module source (per FM)
2695
+ *
2696
+ * Note: FM metadata is stored INSIDE the main XML under <FUNCTIONS>,
2697
+ * NOT in separate per-FM XML files (that's how abapGit works).
2698
+ */
2699
+ /**
2700
+ * Map ADT processingType to abapGit REMOTE_CALL flag
2701
+ */
2702
+ function processingTypeToRemoteCall(processingType) {
2703
+ switch (processingType) {
2704
+ case "rfc": return "R";
2705
+ case "update": return;
2706
+ default: return;
2707
+ }
2708
+ }
2709
+ /**
2710
+ * Map abapGit REMOTE_CALL flag to ADT processingType
2711
+ */
2712
+ function remoteCallToProcessingType(remoteCall, updateTask) {
2713
+ if (remoteCall === "R") return "rfc";
2714
+ if (updateTask && updateTask !== "" && updateTask !== " ") return "update";
2715
+ return "normal";
2716
+ }
2717
+ const functionGroupHandler = createHandler(AdkFunctionGroup, {
2718
+ schema: fugr,
2719
+ version: "v1.0.0",
2720
+ serializer: "LCL_OBJECT_FUGR",
2721
+ serializer_version: "v1.0.0",
2722
+ toAbapGit: (obj) => {
2723
+ const name = obj.name.toUpperCase();
2724
+ return {
2725
+ AREAT: obj.description ?? "",
2726
+ INCLUDES: { SOBJ_NAME: [`L${name}TOP`, `SAPL${name}`] }
2727
+ };
2728
+ },
2729
+ serialize: async (obj, ctx) => {
2730
+ const objectName = ctx.getObjectName(obj);
2731
+ const nameUpper = obj.name.toUpperCase();
2732
+ const files = [];
2733
+ const fmItems = await discoverFunctionModules(obj);
2734
+ const functions = await serializeFunctions(obj, fmItems);
2735
+ const values = {
2736
+ AREAT: obj.description ?? "",
2737
+ INCLUDES: { SOBJ_NAME: [`L${nameUpper}TOP`, `SAPL${nameUpper}`] }
2738
+ };
2739
+ if (functions.length > 0) values.FUNCTIONS = { item: functions };
2740
+ const fullPayload = { abapGit: {
2741
+ abap: {
2742
+ version: "1.0",
2743
+ values
2744
+ },
2745
+ version: "v1.0.0",
2746
+ serializer: "LCL_OBJECT_FUGR",
2747
+ serializer_version: "v1.0.0"
2748
+ } };
2749
+ let xmlContent = fugr.build(fullPayload, { pretty: true });
2750
+ xmlContent = formatAbapGitXml(xmlContent);
2751
+ files.push(ctx.createFile(`${objectName}.fugr.xml`, xmlContent));
2752
+ try {
2753
+ const topSource = await obj.getSource();
2754
+ if (topSource) files.push(ctx.createFile(`${objectName}.fugr.l${objectName}top.abap`, topSource));
2755
+ } catch {}
2756
+ const fixpt = ctx.getData(obj).fixPointArithmetic ? "X" : "";
2757
+ files.push(ctx.createFile(`${objectName}.fugr.l${objectName}top.xml`, buildProgdirXml(`L${nameUpper}TOP`, "I", fixpt)));
2758
+ files.push(ctx.createFile(`${objectName}.fugr.sapl${objectName}.abap`, buildMainProgramSource(nameUpper)), ctx.createFile(`${objectName}.fugr.sapl${objectName}.xml`, buildProgdirXml(`SAPL${nameUpper}`, "F", fixpt)));
2759
+ for (const fm of fmItems) {
2760
+ const funcName = fm.name.toLowerCase();
2761
+ try {
2762
+ const source = await obj.client.adt.functions.groups.fmodules.source.main.get(obj.name, fm.name);
2763
+ if (source) files.push(ctx.createFile(`${objectName}.fugr.${funcName}.abap`, source));
2764
+ } catch {}
2765
+ }
2766
+ return files;
2767
+ },
2768
+ fromAbapGit: ({ AREAT, FUNCTIONS }) => ({
2769
+ name: "",
2770
+ type: "FUGR/F",
2771
+ description: AREAT,
2772
+ language: "EN",
2773
+ masterLanguage: "EN",
2774
+ _functions: FUNCTIONS
2775
+ }),
2776
+ setSources: (obj, sources) => {
2777
+ const name = obj.name.toLowerCase();
2778
+ const topKey = `l${name}top`;
2779
+ const mainSource = sources.main ?? sources[topKey];
2780
+ if (mainSource) obj._pendingSource = mainSource;
2781
+ const fmSources = {};
2782
+ for (const [suffix, content] of Object.entries(sources)) {
2783
+ if (suffix === "main" || suffix === topKey || suffix.startsWith(`l${name}`) || suffix.startsWith(`sapl${name}`)) continue;
2784
+ fmSources[suffix] = content;
2785
+ }
2786
+ if (Object.keys(fmSources).length > 0) obj._pendingFmSources = fmSources;
2787
+ }
2788
+ });
2789
+ /**
2790
+ * Discover child function modules via object structure endpoint.
2791
+ * Falls back to empty list if the endpoint is unavailable.
2792
+ */
2793
+ async function discoverFunctionModules(obj) {
2794
+ try {
2795
+ const response = await obj.client.adt.functions.groups.objectstructure(obj.name);
2796
+ const responseStr = String(response);
2797
+ const fmNames = [];
2798
+ const regex = /type="FUGR\/FF"[^>]*adtcore:name="([^"]+)"/g;
2799
+ let match;
2800
+ while ((match = regex.exec(responseStr)) !== null) fmNames.push({ name: match[1] });
2801
+ const regex2 = /adtcore:name="([^"]+)"[^>]*type="FUGR\/FF"/g;
2802
+ while ((match = regex2.exec(responseStr)) !== null) if (!fmNames.some((f) => f.name === match[1])) fmNames.push({ name: match[1] });
2803
+ return fmNames;
2804
+ } catch {
2805
+ return [];
2806
+ }
2807
+ }
2808
+ /**
2809
+ * Serialize function module metadata into abapGit FUNCTIONS format.
2810
+ * Fetches each FM's metadata via the ADT fmodules contract.
2811
+ */
2812
+ async function serializeFunctions(obj, fmItems) {
2813
+ const functions = [];
2814
+ for (const fm of fmItems) try {
2815
+ const fmData = (await obj.client.adt.functions.groups.fmodules.get(obj.name, fm.name))?.abapFunctionModule;
2816
+ if (!fmData) continue;
2817
+ const item = {
2818
+ FUNCNAME: fm.name.toUpperCase(),
2819
+ SHORT_TEXT: fmData.description ?? ""
2820
+ };
2821
+ const remoteCall = processingTypeToRemoteCall(fmData.processingType);
2822
+ if (remoteCall) item.REMOTE_CALL = remoteCall;
2823
+ if (fmData.basXMLEnabled) item.REMOTE_BASXML = "X";
2824
+ functions.push(item);
2825
+ } catch {
2826
+ functions.push({ FUNCNAME: fm.name.toUpperCase() });
2827
+ }
2828
+ return functions;
2829
+ }
2830
+ function extractFunctionDescriptors(functions) {
2831
+ if (!functions) return [];
2832
+ return (Array.isArray(functions) ? functions : Array.isArray(functions?.item) ? functions.item : functions?.item ? [functions.item] : []).map((fm) => ({
2833
+ funcName: String(fm.FUNCNAME ?? ""),
2834
+ shortText: fm.SHORT_TEXT ? String(fm.SHORT_TEXT) : void 0,
2835
+ processingType: remoteCallToProcessingType(fm.REMOTE_CALL, fm.UPDATE_TASK),
2836
+ basXMLEnabled: fm.REMOTE_BASXML === "X"
2837
+ }));
2838
+ }
2839
+ /**
2840
+ * Build PROGDIR XML for an include program (best-effort defaults).
2841
+ * PROGDIR is SAP-internal metadata that abapGit stores but ADT doesn't expose.
2842
+ */
2843
+ function buildProgdirXml(programName, subc, fixpt) {
2844
+ return `<?xml version="1.0" encoding="utf-8"?>
2845
+ <abapGit version="v1.0.0">
2846
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
2847
+ <asx:values>
2848
+ <PROGDIR>
2849
+ <NAME>${programName}</NAME>
2850
+ <SUBC>${subc}</SUBC>${subc === "F" ? "\n <RLOAD>E</RLOAD>" : ""}
2851
+ <FIXPT>${fixpt}</FIXPT>
2852
+ <UCCHECK>X</UCCHECK>
2853
+ </PROGDIR>
2854
+ </asx:values>
2855
+ </asx:abap>
2856
+ </abapGit>
2857
+ `;
2858
+ }
2859
+ /**
2860
+ * Build the standard main program source (SAPL{NAME}).
2861
+ * This is system-generated and contains INCLUDE declarations.
2862
+ */
2863
+ function buildMainProgramSource(nameUpper) {
2864
+ return `*******************************************************************
2865
+ * System-defined Include-files. *
2866
+ *******************************************************************
2867
+ INCLUDE L${nameUpper}TOP. " Global Declarations
2868
+ INCLUDE L${nameUpper}UXX. " Function Modules
2869
+
2870
+ *******************************************************************
2871
+ * User-defined Include-files (if necessary). *
2872
+ *******************************************************************
2873
+ * INCLUDE L${nameUpper}F... " Subroutines
2874
+ * INCLUDE L${nameUpper}O... " PBO-Modules
2875
+ * INCLUDE L${nameUpper}I... " PAI-Modules
2876
+ * INCLUDE L${nameUpper}E... " Events
2877
+ * INCLUDE L${nameUpper}P... " Local class implement.
2878
+ * INCLUDE L${nameUpper}T99. " ABAP Unit tests
2879
+ `;
2880
+ }
2881
+
2882
+ //#endregion
2883
+ //#region src/lib/handlers/objects/doma.ts
2884
+ /**
2885
+ * Domain (DOMA) object handler for abapGit format
2886
+ */
2887
+ const domainHandler = createHandler(AdkDomain, {
2888
+ schema: doma,
2889
+ version: "v1.0.0",
2890
+ serializer: "LCL_OBJECT_DOMA",
2891
+ serializer_version: "v1.0.0",
2892
+ toAbapGit: (obj) => {
2893
+ const data = obj.dataSync;
2894
+ const typeInfo = data?.content?.typeInformation;
2895
+ const outInfo = data?.content?.outputInformation;
2896
+ const valueInfo = data?.content?.valueInformation;
2897
+ const fixValues = valueInfo?.fixValues?.fixValue;
2898
+ const DD07V_TAB = fixValues && fixValues.length > 0 ? { DD07V: fixValues.map((fv) => {
2899
+ const entry = {
2900
+ DOMNAME: obj.name ?? "",
2901
+ VALPOS: String(fv.position ?? "").padStart(4, "0"),
2902
+ DDLANGUAGE: isoToSapLang(data?.language),
2903
+ DOMVALUE_L: fv.low ?? "",
2904
+ DDTEXT: fv.text ?? ""
2905
+ };
2906
+ if (fv.high) entry.DOMVALUE_H = fv.high;
2907
+ return entry;
2908
+ }) } : void 0;
2909
+ return {
2910
+ DD01V: {
2911
+ DOMNAME: obj.name ?? "",
2912
+ DDLANGUAGE: isoToSapLang(data?.language),
2913
+ DATATYPE: typeInfo?.datatype ?? "",
2914
+ LENG: String(typeInfo?.length ?? "").padStart(6, "0"),
2915
+ DECIMALS: typeInfo?.decimals ? String(typeInfo.decimals).padStart(6, "0") : void 0,
2916
+ OUTPUTLEN: String(outInfo?.length ?? "").padStart(6, "0"),
2917
+ LOWERCASE: outInfo?.lowercase ? "X" : void 0,
2918
+ SIGNFLAG: outInfo?.signExists ? "X" : void 0,
2919
+ CONVEXIT: outInfo?.conversionExit || void 0,
2920
+ ENTITYTAB: valueInfo?.valueTableRef?.name || void 0,
2921
+ VALEXI: fixValues && fixValues.length > 0 ? "X" : void 0,
2922
+ DDTEXT: obj.description ?? "",
2923
+ DOMMASTER: isoToSapLang(obj.masterLanguage)
2924
+ },
2925
+ DD07V_TAB
2926
+ };
2927
+ },
2928
+ fromAbapGit: ({ DD01V, DD07V_TAB }) => {
2929
+ const fixValues = DD07V_TAB?.DD07V?.map((fv, idx) => ({
2930
+ position: Number(fv.VALPOS ?? idx + 1),
2931
+ low: fv.DOMVALUE_L ?? "",
2932
+ high: fv.DOMVALUE_H ?? "",
2933
+ text: fv.DDTEXT ?? ""
2934
+ })) ?? [];
2935
+ return {
2936
+ name: (DD01V?.DOMNAME ?? "").toUpperCase(),
2937
+ type: "DOMA/DD",
2938
+ description: DD01V?.DDTEXT,
2939
+ language: sapLangToIso(DD01V?.DDLANGUAGE),
2940
+ masterLanguage: sapLangToIso(DD01V?.DDLANGUAGE),
2941
+ content: {
2942
+ typeInformation: {
2943
+ datatype: DD01V?.DATATYPE ?? "",
2944
+ length: Number(DD01V?.LENG ?? 0),
2945
+ decimals: Number(DD01V?.DECIMALS ?? 0)
2946
+ },
2947
+ outputInformation: {
2948
+ length: Number(DD01V?.OUTPUTLEN ?? 0),
2949
+ style: "",
2950
+ conversionExit: DD01V?.CONVEXIT || void 0,
2951
+ signExists: DD01V?.SIGNFLAG === "X",
2952
+ lowercase: DD01V?.LOWERCASE === "X"
2953
+ },
2954
+ valueInformation: {
2955
+ valueTableRef: { name: DD01V?.ENTITYTAB || void 0 },
2956
+ fixValues: { fixValue: fixValues.length > 0 ? fixValues : void 0 }
2957
+ }
2958
+ }
2959
+ };
2960
+ }
2961
+ });
2962
+
2963
+ //#endregion
2964
+ //#region src/lib/handlers/objects/dtel.ts
2965
+ /**
2966
+ * Data Element (DTEL) object handler for abapGit format
2967
+ */
2968
+ /**
2969
+ * Map ADT typeKind → abapGit REFKIND
2970
+ */
2971
+ const TYPEKIND_TO_REFKIND = {
2972
+ domain: "D",
2973
+ predefinedAbapType: "",
2974
+ refToPredefinedAbapType: "R",
2975
+ refToDictionaryType: "R",
2976
+ refToClifType: "R"
2977
+ };
2978
+ /**
2979
+ * Map ADT typeKind → abapGit REFTYPE (only for reference types)
2980
+ */
2981
+ const TYPEKIND_TO_REFTYPE = {
2982
+ refToClifType: "C",
2983
+ refToDictionaryType: "E",
2984
+ refToPredefinedAbapType: "E"
2985
+ };
2986
+ /**
2987
+ * Derive OUTPUTLEN from ABAP data type + length + decimals.
2988
+ *
2989
+ * The ADT REST API for data elements does not return OUTPUTLEN — SAP derives
2990
+ * it internally from the type definition. This function replicates SAP's
2991
+ * output length calculation for standard ABAP dictionary types.
2992
+ */
2993
+ function deriveOutputLength(dataType, length, decimals) {
2994
+ if (!dataType || !length) return void 0;
2995
+ const type = dataType.toUpperCase();
2996
+ const len = length;
2997
+ const dec = decimals ?? 0;
2998
+ switch (type) {
2999
+ case "CHAR":
3000
+ case "NUMC":
3001
+ case "UNIT":
3002
+ case "CUKY":
3003
+ case "LCHR":
3004
+ case "SSTRING": return String(len).padStart(6, "0");
3005
+ case "CLNT": return "000003";
3006
+ case "LANG": return "000001";
3007
+ case "DATS": return "000010";
3008
+ case "TIMS": return "000008";
3009
+ case "INT1": return "000003";
3010
+ case "INT2": return "000005";
3011
+ case "INT4": return "000010";
3012
+ case "INT8": return "000019";
3013
+ case "FLTP": return "000022";
3014
+ case "DEC":
3015
+ case "CURR":
3016
+ case "QUAN": {
3017
+ const intDigits = len - dec;
3018
+ const separators = intDigits > 1 ? Math.floor((intDigits - 1) / 3) : 0;
3019
+ const outputLen = len + 1 + separators;
3020
+ return String(outputLen).padStart(6, "0");
3021
+ }
3022
+ case "RAW":
3023
+ case "LRAW": return String(len * 2).padStart(6, "0");
3024
+ case "STRING":
3025
+ case "RAWSTRING":
3026
+ case "GEOM_EWKB": return;
3027
+ default: return;
3028
+ }
3029
+ }
3030
+ const dataElementHandler = createHandler(AdkDataElement, {
3031
+ schema: dtel,
3032
+ version: "v1.0.0",
3033
+ serializer: "LCL_OBJECT_DTEL",
3034
+ serializer_version: "v1.0.0",
3035
+ toAbapGit: (obj) => {
3036
+ const data = obj.dataSync;
3037
+ const de = data?.dataElement;
3038
+ const typeKind = de?.typeKind ?? "";
3039
+ const isDomain = typeKind === "domain";
3040
+ const dataType = typeKind.startsWith("refTo") ? "REF" : de?.dataType || void 0;
3041
+ const effectiveDataType = isDomain ? void 0 : dataType;
3042
+ const effectiveLeng = isDomain || !de?.dataTypeLength ? void 0 : String(de.dataTypeLength).padStart(6, "0");
3043
+ const effectiveDecimals = isDomain || !de?.dataTypeDecimals ? void 0 : String(de.dataTypeDecimals).padStart(6, "0");
3044
+ const effectiveOutputLen = isDomain ? void 0 : deriveOutputLength(de?.dataType, de?.dataTypeLength, de?.dataTypeDecimals);
3045
+ return { DD04V: {
3046
+ ROLLNAME: obj.name ?? "",
3047
+ DDLANGUAGE: isoToSapLang(obj.language || void 0),
3048
+ DOMNAME: de?.typeName || void 0,
3049
+ HEADLEN: de?.headingFieldLength ? String(de.headingFieldLength) : void 0,
3050
+ SCRLEN1: de?.shortFieldLength ? String(de.shortFieldLength) : void 0,
3051
+ SCRLEN2: de?.mediumFieldLength ? String(de.mediumFieldLength) : void 0,
3052
+ SCRLEN3: de?.longFieldLength ? String(de.longFieldLength) : void 0,
3053
+ DDTEXT: obj.description ?? "",
3054
+ REPTEXT: de?.headingFieldLabel || void 0,
3055
+ SCRTEXT_S: de?.shortFieldLabel || void 0,
3056
+ SCRTEXT_M: de?.mediumFieldLabel || void 0,
3057
+ SCRTEXT_L: de?.longFieldLabel || void 0,
3058
+ DTELMASTER: isoToSapLang(obj.masterLanguage || void 0),
3059
+ DATATYPE: effectiveDataType,
3060
+ LENG: effectiveLeng,
3061
+ DECIMALS: effectiveDecimals,
3062
+ OUTPUTLEN: effectiveOutputLen,
3063
+ REFKIND: TYPEKIND_TO_REFKIND[typeKind] || void 0,
3064
+ REFTYPE: TYPEKIND_TO_REFTYPE[typeKind],
3065
+ ABAP_LANGUAGE_VERSION: abapLangVerFromAdt(data?.abapLanguageVersion)
3066
+ } };
3067
+ },
3068
+ fromAbapGit: ({ DD04V }) => {
3069
+ const refKind = DD04V?.REFKIND ?? "";
3070
+ const refType = DD04V?.REFTYPE ?? "";
3071
+ let typeKind;
3072
+ if (refKind === "D") typeKind = "domain";
3073
+ else if (refKind === "R") typeKind = refType === "C" ? "refToClifType" : "refToDictionaryType";
3074
+ else typeKind = DD04V?.DATATYPE ? "predefinedAbapType" : "domain";
3075
+ return {
3076
+ name: (DD04V?.ROLLNAME ?? "").toUpperCase(),
3077
+ type: "DTEL/DE",
3078
+ description: DD04V?.DDTEXT,
3079
+ language: sapLangToIso(DD04V?.DDLANGUAGE),
3080
+ masterLanguage: sapLangToIso(DD04V?.DDLANGUAGE),
3081
+ abapLanguageVersion: abapLangVerToAdt(DD04V?.ABAP_LANGUAGE_VERSION),
3082
+ dataElement: {
3083
+ typeKind,
3084
+ typeName: DD04V?.DOMNAME || "",
3085
+ dataType: DD04V?.DATATYPE || "",
3086
+ dataTypeLength: DD04V?.LENG ? Number(DD04V.LENG) : 0,
3087
+ dataTypeLengthEnabled: false,
3088
+ dataTypeDecimals: DD04V?.DECIMALS ? Number(DD04V.DECIMALS) : 0,
3089
+ dataTypeDecimalsEnabled: false,
3090
+ shortFieldLabel: DD04V?.SCRTEXT_S || "",
3091
+ shortFieldLength: DD04V?.SCRLEN1 ? Number(DD04V.SCRLEN1) : 0,
3092
+ shortFieldMaxLength: DD04V?.SCRLEN1 ? Number(DD04V.SCRLEN1) : 0,
3093
+ mediumFieldLabel: DD04V?.SCRTEXT_M || "",
3094
+ mediumFieldLength: DD04V?.SCRLEN2 ? Number(DD04V.SCRLEN2) : 0,
3095
+ mediumFieldMaxLength: DD04V?.SCRLEN2 ? Number(DD04V.SCRLEN2) : 0,
3096
+ longFieldLabel: DD04V?.SCRTEXT_L || "",
3097
+ longFieldLength: DD04V?.SCRLEN3 ? Number(DD04V.SCRLEN3) : 0,
3098
+ longFieldMaxLength: DD04V?.SCRLEN3 ? Number(DD04V.SCRLEN3) : 0,
3099
+ headingFieldLabel: DD04V?.REPTEXT || "",
3100
+ headingFieldLength: DD04V?.HEADLEN ? Number(DD04V.HEADLEN) : 0,
3101
+ headingFieldMaxLength: DD04V?.HEADLEN ? Number(DD04V.HEADLEN) : 0,
3102
+ searchHelp: "",
3103
+ searchHelpParameter: "",
3104
+ setGetParameter: "",
3105
+ defaultComponentName: "",
3106
+ deactivateInputHistory: false,
3107
+ changeDocument: false,
3108
+ leftToRightDirection: false,
3109
+ deactivateBIDIFiltering: false,
3110
+ documentationStatus: ""
3111
+ }
3112
+ };
3113
+ }
3114
+ });
3115
+
3116
+ //#endregion
3117
+ //#region src/lib/handlers/cds-to-abapgit.ts
3118
+ /** Extract the string value from an annotation value node */
3119
+ function annotationStringValue(val) {
3120
+ switch (val.kind) {
3121
+ case "string": return val.value;
3122
+ case "enum": return val.value;
3123
+ case "boolean": return val.value ? "X" : "";
3124
+ case "number": return String(val.value);
3125
+ default: return "";
3126
+ }
3127
+ }
3128
+ /** Find annotation by key and return its string value */
3129
+ function getAnnotation(annotations, key) {
3130
+ const ann = annotations.find((a) => a.key === key);
3131
+ return ann ? annotationStringValue(ann.value) : void 0;
3132
+ }
3133
+ const TABLE_CATEGORY_MAP = {
3134
+ TRANSPARENT: "TRANSP",
3135
+ CLUSTER: "CLUSTER",
3136
+ POOL: "POOL",
3137
+ APPEND: "APPEND"
3138
+ };
3139
+ const ENHANCEMENT_CATEGORY_MAP = {
3140
+ NOT_EXTENSIBLE: "1",
3141
+ EXTENSIBLE_CHARACTER_NUMERIC: "2",
3142
+ EXTENSIBLE_CHARACTER: "3",
3143
+ EXTENSIBLE_ANY: "4",
3144
+ NOT_CLASSIFIED: "0"
3145
+ };
3146
+ const DATA_MAINTENANCE_MAP = {
3147
+ RESTRICTED: "X",
3148
+ NOT_ALLOWED: "N",
3149
+ ALLOWED: ""
3150
+ };
3151
+ /**
3152
+ * Build DD02V data from a parsed CDS table/structure definition
3153
+ */
3154
+ function buildDD02V(def, language, description) {
3155
+ let tabclass = def.kind === "structure" ? "INTTAB" : "TRANSP";
3156
+ const tableCategory = getAnnotation(def.annotations, "AbapCatalog.tableCategory");
3157
+ if (tableCategory) tabclass = TABLE_CATEGORY_MAP[tableCategory] || tabclass;
3158
+ const deliveryClass = getAnnotation(def.annotations, "AbapCatalog.deliveryClass");
3159
+ const enhancementCategory = getAnnotation(def.annotations, "AbapCatalog.enhancement.category");
3160
+ const dataMaintenance = getAnnotation(def.annotations, "AbapCatalog.dataMaintenance");
3161
+ const hasLanguageField = def.members.some((m) => {
3162
+ if ("kind" in m && m.kind === "include") return false;
3163
+ const f = m;
3164
+ if (f.type.kind === "named") return f.type.name.toUpperCase() === "SPRAS";
3165
+ if (f.type.kind === "builtin") return f.type.name === "lang";
3166
+ return false;
3167
+ });
3168
+ const hasClientKeyField = def.members.some((m) => {
3169
+ if ("kind" in m && m.kind === "include") return false;
3170
+ const f = m;
3171
+ if (!f.isKey) return false;
3172
+ if (f.type.kind === "named") return f.type.name.toUpperCase() === "MANDT";
3173
+ if (f.type.kind === "builtin") return f.type.name === "clnt";
3174
+ return false;
3175
+ });
3176
+ const result = {};
3177
+ result.TABNAME = def.name.toUpperCase();
3178
+ result.DDLANGUAGE = language;
3179
+ result.TABCLASS = tabclass;
3180
+ if (hasLanguageField) result.LANGDEP = "X";
3181
+ if (hasClientKeyField) result.CLIDEP = "X";
3182
+ result.DDTEXT = description;
3183
+ result.MASTERLANG = language;
3184
+ if (deliveryClass) result.CONTFLAG = deliveryClass;
3185
+ if (enhancementCategory) result.EXCLASS = ENHANCEMENT_CATEGORY_MAP[enhancementCategory];
3186
+ if (dataMaintenance) result.MATEFLAG = DATA_MAINTENANCE_MAP[dataMaintenance] ?? "";
3187
+ return result;
3188
+ }
3189
+ const BUILTIN_TYPES = {
3190
+ char: {
3191
+ datatype: "CHAR",
3192
+ inttype: "C"
3193
+ },
3194
+ clnt: {
3195
+ datatype: "CLNT",
3196
+ inttype: "C",
3197
+ length: 3
3198
+ },
3199
+ numc: {
3200
+ datatype: "NUMC",
3201
+ inttype: "N"
3202
+ },
3203
+ dats: {
3204
+ datatype: "DATS",
3205
+ inttype: "D",
3206
+ length: 8,
3207
+ fixedIntlen: 16,
3208
+ shlporigin: "T"
3209
+ },
3210
+ datn: {
3211
+ datatype: "DATN",
3212
+ inttype: "D",
3213
+ length: 8,
3214
+ fixedIntlen: 16,
3215
+ shlporigin: "T"
3216
+ },
3217
+ tims: {
3218
+ datatype: "TIMS",
3219
+ inttype: "T",
3220
+ length: 6,
3221
+ fixedIntlen: 12,
3222
+ shlporigin: "T"
3223
+ },
3224
+ timn: {
3225
+ datatype: "TIMN",
3226
+ inttype: "T",
3227
+ length: 6,
3228
+ fixedIntlen: 12,
3229
+ shlporigin: "T"
3230
+ },
3231
+ string: {
3232
+ datatype: "STRG",
3233
+ inttype: "g",
3234
+ fixedIntlen: 8,
3235
+ noLeng: true
3236
+ },
3237
+ xstring: {
3238
+ datatype: "RSTR",
3239
+ inttype: "y",
3240
+ fixedIntlen: 8,
3241
+ noLeng: true
3242
+ },
3243
+ int1: {
3244
+ datatype: "INT1",
3245
+ inttype: "X",
3246
+ length: 3,
3247
+ fixedIntlen: 1
3248
+ },
3249
+ int2: {
3250
+ datatype: "INT2",
3251
+ inttype: "X",
3252
+ length: 5,
3253
+ fixedIntlen: 2
3254
+ },
3255
+ int4: {
3256
+ datatype: "INT4",
3257
+ inttype: "X",
3258
+ length: 10,
3259
+ fixedIntlen: 4
3260
+ },
3261
+ int8: {
3262
+ datatype: "INT8",
3263
+ inttype: "8",
3264
+ length: 19,
3265
+ fixedIntlen: 8
3266
+ },
3267
+ fltp: {
3268
+ datatype: "FLTP",
3269
+ inttype: "F",
3270
+ length: 16,
3271
+ decimals: 16,
3272
+ fixedIntlen: 8
3273
+ },
3274
+ dec: {
3275
+ datatype: "DEC",
3276
+ inttype: "P"
3277
+ },
3278
+ curr: {
3279
+ datatype: "CURR",
3280
+ inttype: "P"
3281
+ },
3282
+ quan: {
3283
+ datatype: "QUAN",
3284
+ inttype: "P"
3285
+ },
3286
+ raw: {
3287
+ datatype: "RAW",
3288
+ inttype: "X"
3289
+ },
3290
+ rawstring: {
3291
+ datatype: "RSTR",
3292
+ inttype: "y",
3293
+ fixedIntlen: 8,
3294
+ noLeng: true
3295
+ },
3296
+ lang: {
3297
+ datatype: "LANG",
3298
+ inttype: "C",
3299
+ length: 1
3300
+ },
3301
+ unit: {
3302
+ datatype: "UNIT",
3303
+ inttype: "C",
3304
+ length: 3
3305
+ },
3306
+ cuky: {
3307
+ datatype: "CUKY",
3308
+ inttype: "C",
3309
+ length: 5
3310
+ },
3311
+ d16n: {
3312
+ datatype: "D16N",
3313
+ inttype: "a",
3314
+ fixedIntlen: 8
3315
+ },
3316
+ d34n: {
3317
+ datatype: "D34N",
3318
+ inttype: "e",
3319
+ fixedIntlen: 16
3320
+ },
3321
+ utclong: {
3322
+ datatype: "UTCL",
3323
+ inttype: "p",
3324
+ length: 27,
3325
+ fixedIntlen: 8
3326
+ }
3327
+ };
3328
+ /** Zero-pad number to given width */
3329
+ function zeroPad(n, width) {
3330
+ return String(n).padStart(width, "0");
3331
+ }
3332
+ /** Compute internal length from type info */
3333
+ function computeIntlen(builtin, length) {
3334
+ if (builtin.fixedIntlen !== void 0) return builtin.fixedIntlen;
3335
+ if (builtin.inttype === "P" && length !== void 0) return Math.ceil((length + 1) / 2);
3336
+ if (builtin.inttype === "X" && length !== void 0) return length;
3337
+ if (length !== void 0) return length * 2;
3338
+ if (builtin.length !== void 0) return builtin.length * 2;
3339
+ return 0;
3340
+ }
3341
+ /** Build a DD03P entry from a single field definition */
3342
+ async function buildFieldDD03P(field, tableName, resolver) {
3343
+ const isKey = field.isKey;
3344
+ const notNull = field.notNull;
3345
+ let rollname;
3346
+ let comptype;
3347
+ let inttype;
3348
+ let intlen;
3349
+ let datatype;
3350
+ let leng;
3351
+ let decimals;
3352
+ let mask;
3353
+ let shlporigin;
3354
+ let reftable;
3355
+ let reffield;
3356
+ if (field.type.kind === "builtin") {
3357
+ const bt = field.type;
3358
+ const typeInfo = BUILTIN_TYPES[bt.name];
3359
+ if (typeInfo) {
3360
+ const length = bt.length ?? typeInfo.length;
3361
+ inttype = typeInfo.inttype;
3362
+ intlen = zeroPad(computeIntlen(typeInfo, length), 6);
3363
+ datatype = typeInfo.datatype;
3364
+ if (!typeInfo.noLeng && length !== void 0) leng = zeroPad(length, 6);
3365
+ const dec = bt.decimals ?? typeInfo.decimals;
3366
+ if (dec !== void 0) decimals = zeroPad(dec, 6);
3367
+ mask = ` ${typeInfo.datatype}`;
3368
+ if (typeInfo.shlporigin) shlporigin = typeInfo.shlporigin;
3369
+ if (bt.name === "curr" || bt.name === "quan") {
3370
+ const refAnnotation = getAnnotation(field.annotations, bt.name === "curr" ? "Semantics.amount.currencyCode" : "Semantics.quantity.unitOfMeasure");
3371
+ if (refAnnotation) {
3372
+ reftable = tableName;
3373
+ const parts = refAnnotation.split(".");
3374
+ reffield = parts[parts.length - 1].toUpperCase();
3375
+ }
3376
+ }
3377
+ }
3378
+ } else {
3379
+ rollname = field.type.name.toUpperCase();
3380
+ comptype = "E";
3381
+ if (resolver) {
3382
+ const resolved = await resolver.resolve(field.type.name);
3383
+ comptype = resolved.comptype;
3384
+ if (resolved.shlporigin) shlporigin = resolved.shlporigin;
3385
+ if (resolved.comptype === "S") {
3386
+ datatype = "STRU";
3387
+ mask = " STRUS";
3388
+ }
3389
+ }
3390
+ }
3391
+ const result = {};
3392
+ result.FIELDNAME = field.name.toUpperCase();
3393
+ if (isKey) result.KEYFLAG = "X";
3394
+ if (rollname) result.ROLLNAME = rollname;
3395
+ result.ADMINFIELD = "0";
3396
+ if (inttype) result.INTTYPE = inttype;
3397
+ if (intlen) result.INTLEN = intlen;
3398
+ if (notNull) result.NOTNULL = "X";
3399
+ if (datatype) result.DATATYPE = datatype;
3400
+ if (leng) result.LENG = leng;
3401
+ if (decimals) result.DECIMALS = decimals;
3402
+ if (shlporigin) result.SHLPORIGIN = shlporigin;
3403
+ if (reftable) result.REFTABLE = reftable;
3404
+ if (reffield) result.REFFIELD = reffield;
3405
+ if (mask) result.MASK = mask;
3406
+ if (comptype) result.COMPTYPE = comptype;
3407
+ return result;
3408
+ }
3409
+ /**
3410
+ * Build DD03P entries from table/structure members
3411
+ */
3412
+ async function buildDD03P(members, tableName = "", resolver) {
3413
+ const entries = [];
3414
+ for (const member of members) if ("kind" in member && member.kind === "include") {
3415
+ const inc = member;
3416
+ const includeName = inc.name.toUpperCase();
3417
+ let ddtext;
3418
+ if (resolver) ddtext = (await resolver.resolve(inc.name)).description;
3419
+ if (inc.suffix) {
3420
+ const entry = {
3421
+ FIELDNAME: `.INCLU-${inc.suffix.toUpperCase()}`,
3422
+ ADMINFIELD: "0",
3423
+ PRECFIELD: includeName,
3424
+ MASK: " S",
3425
+ COMPTYPE: "S"
3426
+ };
3427
+ if (ddtext) entry.DDTEXT = ddtext;
3428
+ entries.push(entry);
3429
+ } else {
3430
+ const entry = {
3431
+ FIELDNAME: ".INCLUDE",
3432
+ ADMINFIELD: "0",
3433
+ PRECFIELD: includeName,
3434
+ MASK: " S",
3435
+ COMPTYPE: "S"
3436
+ };
3437
+ if (ddtext) entry.DDTEXT = ddtext;
3438
+ entries.push(entry);
3439
+ }
3440
+ } else {
3441
+ const field = member;
3442
+ entries.push(await buildFieldDD03P(field, tableName, resolver));
3443
+ }
3444
+ return entries;
3445
+ }
3446
+
3447
+ //#endregion
3448
+ //#region src/lib/handlers/objects/tabl.ts
3449
+ /**
3450
+ * Table/Structure (TABL) object handlers for abapGit format
3451
+ *
3452
+ * Serializes SAP tables (TABL/DT) and structures (TABL/DS) to
3453
+ * abapGit-compatible XML format by fetching the CDS-style source code
3454
+ * from SAP, parsing it with @abapify/acds, and mapping the AST into
3455
+ * DD02V/DD03P structures.
3456
+ *
3457
+ * Tables and structures share the same serialization logic but use
3458
+ * different ADT endpoints (ddic/tables vs ddic/structures).
3459
+ *
3460
+ * Data sources:
3461
+ * - blueSource GET: name, type, description, language
3462
+ * - source/main GET: CDS source with annotations and field definitions
3463
+ * → parsed via @abapify/acds into AST
3464
+ * → mapped into DD02V annotations and DD03P field entries
3465
+ * - Per named type: /sap/bc/adt/ddic/dataelements/{name} or /structures/{name}
3466
+ * → resolves COMPTYPE (E vs S), SHLPORIGIN, description (DDTEXT)
3467
+ */
3468
+ /**
3469
+ * Strip undefined/empty-string values from an object
3470
+ * to avoid emitting empty XML elements
3471
+ */
3472
+ function stripEmpty(obj) {
3473
+ const result = {};
3474
+ for (const [key, value] of Object.entries(obj)) if (value !== void 0 && value !== "") result[key] = value;
3475
+ return result;
3476
+ }
3477
+ /**
3478
+ * Create a TypeResolver that resolves named types via ADT endpoints.
3479
+ * Tries data element first, then structure. Caches results.
3480
+ */
3481
+ function createAdtTypeResolver(obj) {
3482
+ const cache = /* @__PURE__ */ new Map();
3483
+ return { async resolve(name) {
3484
+ const key = name.toLowerCase();
3485
+ if (cache.has(key)) return cache.get(key);
3486
+ const dtelXml = await obj.fetchText(`/sap/bc/adt/ddic/dataelements/${encodeURIComponent(key)}`);
3487
+ if (dtelXml) {
3488
+ const result = { comptype: "E" };
3489
+ if (dtelXml.match(/<dtel:searchHelp>[^<]+<\/dtel:searchHelp>/)) result.shlporigin = "D";
3490
+ const descMatch = dtelXml.match(/adtcore:description="([^"]+)"/);
3491
+ if (descMatch) result.description = descMatch[1];
3492
+ cache.set(key, result);
3493
+ return result;
3494
+ }
3495
+ const structXml = await obj.fetchText(`/sap/bc/adt/ddic/structures/${encodeURIComponent(key)}`);
3496
+ if (structXml) {
3497
+ const result = { comptype: "S" };
3498
+ const descMatch = structXml.match(/adtcore:description="([^"]+)"/);
3499
+ if (descMatch) result.description = descMatch[1];
3500
+ cache.set(key, result);
3501
+ return result;
3502
+ }
3503
+ const fallback = { comptype: "E" };
3504
+ cache.set(key, fallback);
3505
+ return fallback;
3506
+ } };
3507
+ }
3508
+ /**
3509
+ * Parse ADT table settings XML into DD09L data for abapGit serialization.
3510
+ *
3511
+ * Uses the typed `tablesettings` schema from @abapify/adt-schemas to parse
3512
+ * the ADT endpoint response (/sap/bc/adt/ddic/db/settings/{name}).
3513
+ *
3514
+ * Mapping:
3515
+ * tableSettings.sizeCategory → DD09L.TABKAT
3516
+ * tableSettings.dataClassCategory → DD09L.TABART
3517
+ * tableSettings.buffering.allowed → DD09L.BUFALLOW
3518
+ * tableSettings.buffering.type → DD09L.PUFFERUNG
3519
+ * tableSettings.buffering.areaKeyFields → DD09L.SCHFELDANZ
3520
+ * tableSettings.loggingEnabled → DD09L.PROTOKOLL
3521
+ */
3522
+ function parseSettingsToDD09L(settingsXml, tableName) {
3523
+ let settings;
3524
+ try {
3525
+ const parsed = tablesettings.parse(settingsXml);
3526
+ if (!("tableSettings" in parsed)) return void 0;
3527
+ settings = parsed.tableSettings;
3528
+ } catch {
3529
+ return;
3530
+ }
3531
+ const dd09l = {};
3532
+ dd09l.TABNAME = tableName;
3533
+ dd09l.AS4LOCAL = "A";
3534
+ if (settings.sizeCategory) dd09l.TABKAT = settings.sizeCategory;
3535
+ if (settings.dataClassCategory) dd09l.TABART = settings.dataClassCategory;
3536
+ if (settings.buffering?.allowed) dd09l.BUFALLOW = settings.buffering.allowed;
3537
+ const bufType = settings.buffering?.type;
3538
+ if (bufType) dd09l.PUFFERUNG = bufType;
3539
+ const areaKeyFields = settings.buffering?.areaKeyFields;
3540
+ if (areaKeyFields && areaKeyFields !== "0") dd09l.SCHFELDANZ = areaKeyFields;
3541
+ if (settings.loggingEnabled) dd09l.PROTOKOLL = "X";
3542
+ return dd09l;
3543
+ }
3544
+ /**
3545
+ * Shared serialize logic for tables and structures.
3546
+ * Both use CDS source → DD02V/DD03P mapping.
3547
+ */
3548
+ async function serializeTabl(obj, ctx) {
3549
+ const objectName = ctx.getObjectName(obj);
3550
+ const lang = isoToSapLang(obj.language || void 0);
3551
+ let cdsSource;
3552
+ try {
3553
+ cdsSource = await obj.getSource();
3554
+ } catch {
3555
+ const xmlContent = ctx.toAbapGitXml(obj);
3556
+ return [ctx.createFile(`${objectName}.tabl.xml`, xmlContent)];
3557
+ }
3558
+ const { ast, errors } = parse(cdsSource);
3559
+ if (errors.length > 0 || ast.definitions.length === 0) {
3560
+ const xmlContent = ctx.toAbapGitXml(obj);
3561
+ return [ctx.createFile(`${objectName}.tabl.xml`, xmlContent)];
3562
+ }
3563
+ const def = ast.definitions[0];
3564
+ const dd02v = buildDD02V(def, lang, obj.description ?? "");
3565
+ const resolver = createAdtTypeResolver(obj);
3566
+ const dd03pEntries = await buildDD03P(def.members, def.name.toUpperCase(), resolver);
3567
+ const values = { DD02V: stripEmpty(dd02v) };
3568
+ if ("getSettings" in obj && typeof obj.getSettings === "function") try {
3569
+ const settingsXml = await obj.getSettings();
3570
+ if (settingsXml) {
3571
+ const dd09l = parseSettingsToDD09L(settingsXml, def.name.toUpperCase());
3572
+ if (dd09l) values.DD09L = stripEmpty(dd09l);
3573
+ }
3574
+ } catch {}
3575
+ if (dd03pEntries.length > 0) values.DD03P_TABLE = { DD03P: dd03pEntries.map((entry) => stripEmpty(entry)) };
3576
+ const fullPayload = {
3577
+ abap: {
3578
+ version: "1.0",
3579
+ values
3580
+ },
3581
+ version: "v1.0.0",
3582
+ serializer: "LCL_OBJECT_TABL",
3583
+ serializer_version: "v1.0.0"
3584
+ };
3585
+ const xml = formatAbapGitXml(tabl.build(fullPayload, { pretty: true }));
3586
+ return [ctx.createFile(`${objectName}.tabl.xml`, xml)];
3587
+ }
3588
+ /** Shared fromAbapGit logic for both tables and structures */
3589
+ function fromAbapGitTabl({ DD02V } = {}) {
3590
+ return {
3591
+ name: (DD02V?.TABNAME ?? "").toUpperCase(),
3592
+ type: DD02V?.TABCLASS === "INTTAB" ? "TABL/DS" : "TABL/DT",
3593
+ description: DD02V?.DDTEXT,
3594
+ language: sapLangToIso(DD02V?.DDLANGUAGE),
3595
+ masterLanguage: sapLangToIso(DD02V?.DDLANGUAGE)
3596
+ };
3597
+ }
3598
+ const tableHandler = createHandler(AdkTable, {
3599
+ schema: tabl,
3600
+ version: "v1.0.0",
3601
+ serializer: "LCL_OBJECT_TABL",
3602
+ serializer_version: "v1.0.0",
3603
+ toAbapGit: (obj) => ({ DD02V: {
3604
+ TABNAME: obj.name ?? "",
3605
+ DDLANGUAGE: isoToSapLang(obj.language || void 0),
3606
+ TABCLASS: "TRANSP",
3607
+ DDTEXT: obj.description ?? ""
3608
+ } }),
3609
+ serialize: (obj, ctx) => serializeTabl(obj, ctx),
3610
+ fromAbapGit: fromAbapGitTabl
3611
+ });
3612
+ const structureHandler = createHandler(AdkStructure, {
3613
+ schema: tabl,
3614
+ version: "v1.0.0",
3615
+ serializer: "LCL_OBJECT_TABL",
3616
+ serializer_version: "v1.0.0",
3617
+ toAbapGit: (obj) => ({ DD02V: {
3618
+ TABNAME: obj.name ?? "",
3619
+ DDLANGUAGE: isoToSapLang(obj.language || void 0),
3620
+ TABCLASS: "INTTAB",
3621
+ DDTEXT: obj.description ?? ""
3622
+ } }),
3623
+ serialize: (obj, ctx) => serializeTabl(obj, ctx),
3624
+ fromAbapGit: fromAbapGitTabl
3625
+ });
3626
+
3627
+ //#endregion
3628
+ //#region src/lib/handlers/objects/ttyp.ts
3629
+ /**
3630
+ * Table Type (TTYP) object handler for abapGit format
3631
+ *
3632
+ * Maps between abapGit DD40V codes and ADT API enum values.
3633
+ */
3634
+ /** DD40V ACCESSMODE → ADT accessType */
3635
+ const ACCESS_MODE_TO_ADT = {
3636
+ T: "standard",
3637
+ S: "sorted",
3638
+ H: "hashed"
3639
+ };
3640
+ const ACCESS_MODE_FROM_ADT = Object.fromEntries(Object.entries(ACCESS_MODE_TO_ADT).map(([k, v]) => [v, k]));
3641
+ /** DD40V KEYDEF → ADT primaryKey.definition */
3642
+ const KEY_DEF_TO_ADT = {
3643
+ D: "standard",
3644
+ K: "keyComponents",
3645
+ T: "rowType"
3646
+ };
3647
+ const KEY_DEF_FROM_ADT = Object.fromEntries(Object.entries(KEY_DEF_TO_ADT).map(([k, v]) => [v, k]));
3648
+ /** DD40V KEYKIND → ADT primaryKey.kind */
3649
+ const KEY_KIND_TO_ADT = {
3650
+ N: "nonUnique",
3651
+ U: "unique",
3652
+ G: "notSpecified"
3653
+ };
3654
+ const KEY_KIND_FROM_ADT = Object.fromEntries(Object.entries(KEY_KIND_TO_ADT).map(([k, v]) => [v, k]));
3655
+ /**
3656
+ * DD40V ROWKIND → ADT rowType.typeKind
3657
+ *
3658
+ * ROWKIND='' (empty) + DATATYPE set → predefinedAbapType (built-in like STRING, INT4)
3659
+ * ROWKIND='S' → dictionaryType (references a structure/table/data element)
3660
+ * ROWKIND='R' → ref type
3661
+ */
3662
+ const ROW_KIND_TO_ADT = {
3663
+ "": "predefinedAbapType",
3664
+ S: "dictionaryType",
3665
+ R: "refToDictionaryType"
3666
+ };
3667
+ const ROW_KIND_FROM_ADT = Object.fromEntries(Object.entries(ROW_KIND_TO_ADT).map(([k, v]) => [v, k]));
3668
+ /**
3669
+ * DD40V DATATYPE (DDIC code) → ADT builtInType.dataType (ABAP type name)
3670
+ *
3671
+ * abapGit stores 4-char DDIC internal codes (e.g. STRG, RSTR).
3672
+ * SAP ADT REST API uses ABAP type names (e.g. STRING, XSTRING).
3673
+ * Most types use the same name in both (CHAR, NUMC, INT4, etc.);
3674
+ * only a few differ.
3675
+ */
3676
+ const DATATYPE_TO_ADT = {
3677
+ STRG: "STRING",
3678
+ SSTR: "SSTRING",
3679
+ RSTR: "XSTRING",
3680
+ UTCL: "UTCLONG"
3681
+ };
3682
+ const DATATYPE_FROM_ADT = Object.fromEntries(Object.entries(DATATYPE_TO_ADT).map(([k, v]) => [v, k]));
3683
+ /**
3684
+ * DD40V TYPELEN — fixed internal byte length for predefined types.
3685
+ *
3686
+ * Variable-length types (STRING, XSTRING) have a fixed pointer size (8 bytes)
3687
+ * that abapGit stores as TYPELEN. This is not the same as LENG (display length).
3688
+ * We only need to emit TYPELEN for types that have noLeng=true (no external LENG).
3689
+ */
3690
+ const FIXED_TYPELEN = {
3691
+ STRG: 8,
3692
+ RSTR: 8
3693
+ };
3694
+ const tableTypeHandler = createHandler(AdkTableType, {
3695
+ schema: ttyp,
3696
+ version: "v1.0.0",
3697
+ serializer: "LCL_OBJECT_TTYP",
3698
+ serializer_version: "v1.0.0",
3699
+ toAbapGit: (obj) => {
3700
+ const data = obj.dataSync;
3701
+ const accessMode = ACCESS_MODE_FROM_ADT[data?.accessType ?? ""] ?? data?.accessType ?? "";
3702
+ const keyDef = KEY_DEF_FROM_ADT[data?.primaryKey?.definition ?? ""] ?? data?.primaryKey?.definition ?? "";
3703
+ const keyKind = KEY_KIND_FROM_ADT[data?.primaryKey?.kind ?? ""] ?? data?.primaryKey?.kind ?? "";
3704
+ const rowKind = ROW_KIND_FROM_ADT[data?.rowType?.typeKind ?? ""] ?? data?.rowType?.typeKind ?? "";
3705
+ const adtDataType = data?.rowType?.builtInType?.dataType ?? "";
3706
+ const ddicDataType = DATATYPE_FROM_ADT[adtDataType] ?? adtDataType;
3707
+ const typeLen = FIXED_TYPELEN[ddicDataType];
3708
+ return { DD40V: {
3709
+ TYPENAME: obj.name ?? "",
3710
+ DDLANGUAGE: isoToSapLang(data?.language || void 0),
3711
+ ROWTYPE: data?.rowType?.typeName || void 0,
3712
+ ROWKIND: rowKind || void 0,
3713
+ DATATYPE: ddicDataType,
3714
+ LENG: data?.rowType?.builtInType?.length ? String(data.rowType.builtInType.length).padStart(6, "0") : void 0,
3715
+ DECIMALS: data?.rowType?.builtInType?.decimals ? String(data.rowType.builtInType.decimals).padStart(6, "0") : void 0,
3716
+ ACCESSMODE: accessMode,
3717
+ KEYDEF: keyDef,
3718
+ KEYKIND: keyKind,
3719
+ DDTEXT: obj.description ?? "",
3720
+ TYPELEN: typeLen ? String(typeLen).padStart(6, "0") : void 0,
3721
+ ABAP_LANGUAGE_VERSION: abapLangVerFromAdt(data?.abapLanguageVersion)
3722
+ } };
3723
+ },
3724
+ fromAbapGit: ({ DD40V }) => {
3725
+ const accessType = ACCESS_MODE_TO_ADT[DD40V?.ACCESSMODE ?? ""] ?? DD40V?.ACCESSMODE;
3726
+ const keyDef = KEY_DEF_TO_ADT[DD40V?.KEYDEF ?? ""] ?? DD40V?.KEYDEF;
3727
+ const keyKind = KEY_KIND_TO_ADT[DD40V?.KEYKIND ?? ""] ?? DD40V?.KEYKIND;
3728
+ const rowKind = ROW_KIND_TO_ADT[DD40V?.ROWKIND ?? ""] ?? DD40V?.ROWKIND;
3729
+ const ddicCode = DD40V?.DATATYPE ?? "";
3730
+ const adtDataType = DATATYPE_TO_ADT[ddicCode] ?? ddicCode;
3731
+ const isPredefined = rowKind === "predefinedAbapType";
3732
+ return {
3733
+ name: (DD40V?.TYPENAME ?? "").toUpperCase(),
3734
+ type: "TTYP/DA",
3735
+ description: DD40V?.DDTEXT,
3736
+ language: sapLangToIso(DD40V?.DDLANGUAGE),
3737
+ masterLanguage: sapLangToIso(DD40V?.DDLANGUAGE),
3738
+ abapLanguageVersion: abapLangVerToAdt(DD40V?.ABAP_LANGUAGE_VERSION),
3739
+ rowType: {
3740
+ typeKind: rowKind,
3741
+ typeName: isPredefined ? "" : DD40V?.ROWTYPE || "",
3742
+ builtInType: {
3743
+ dataType: ddicCode ? adtDataType : "",
3744
+ length: DD40V?.LENG ? Number(DD40V.LENG) : 0,
3745
+ decimals: DD40V?.DECIMALS ? Number(DD40V.DECIMALS) : 0
3746
+ },
3747
+ rangeType: ""
3748
+ },
3749
+ accessType,
3750
+ primaryKey: {
3751
+ definition: keyDef,
3752
+ kind: keyKind,
3753
+ components: { component: [] },
3754
+ alias: ""
3755
+ },
3756
+ secondaryKeys: { allowed: "notSpecified" }
3757
+ };
3758
+ }
3759
+ });
3760
+
3761
+ //#endregion
3762
+ //#region src/lib/handlers/objects/bdef.ts
3763
+ /**
3764
+ * BDEF (RAP Behavior Definition) object handler for abapGit format
3765
+ *
3766
+ * BDEF is source-driven: the semantic content lives in a `.abdl` file
3767
+ * (the RAP behavior definition language) and abapGit stores it alongside
3768
+ * a minimal SKEY metadata block.
3769
+ *
3770
+ * File layout:
3771
+ * src/zbp_foo.bdef.abdl — behavior source (.abdl text)
3772
+ * src/zbp_foo.bdef.xml — minimal metadata wrapper
3773
+ *
3774
+ * The handler uses the string form of `createHandler` ('BDEF') because
3775
+ * the ADK object (`AdkBehaviorDefinition`) is a lightweight class without
3776
+ * the AdkObject save/lock machinery — all lifecycle is source-based.
3777
+ *
3778
+ * We override `serialize` so the source file gets the `.abdl` extension
3779
+ * instead of the default `.abap`.
3780
+ */
3781
+ const behaviorDefinitionHandler = createHandler("BDEF", {
3782
+ schema: bdef,
3783
+ version: "v1.0.0",
3784
+ serializer: "LCL_OBJECT_BDEF",
3785
+ serializer_version: "v1.0.0",
3786
+ toAbapGit: (obj) => ({ SKEY: {
3787
+ TYPE: "BDEF",
3788
+ NAME: String(obj?.name ?? "").toUpperCase()
3789
+ } }),
3790
+ getSource: (obj) => typeof obj?.getSource === "function" ? obj.getSource() : Promise.resolve(""),
3791
+ fromAbapGit: ({ SKEY }) => ({ name: String(SKEY?.NAME ?? "").toUpperCase() }),
3792
+ async serialize(object, ctx) {
3793
+ const files = [];
3794
+ const objectName = ctx.getObjectName(object);
3795
+ const source = await (typeof object?.getSource === "function" ? object.getSource() : Promise.resolve(""));
3796
+ if (source) files.push(ctx.createFile(`${objectName}.${ctx.fileExtension}.abdl`, source));
3797
+ const xmlContent = ctx.toAbapGitXml(object);
3798
+ files.push(ctx.createFile(`${objectName}.${ctx.fileExtension}.xml`, xmlContent));
3799
+ return files;
3800
+ },
3801
+ setSources: (obj, sources) => {
3802
+ if (sources.main) obj._pendingSource = sources.main;
3803
+ }
3804
+ });
3805
+
3806
+ //#endregion
3807
+ //#region src/lib/handlers/objects/srvd.ts
3808
+ /**
3809
+ * SRVD (RAP Service Definition) object handler for abapGit format
3810
+ *
3811
+ * SRVD is source-driven: the semantic content lives in a `.asrvd` file
3812
+ * (CDS-like service definition) and abapGit stores it alongside
3813
+ * a minimal SKEY metadata block.
3814
+ *
3815
+ * File layout:
3816
+ * src/zui_foo.srvd.asrvd — service source (.asrvd text)
3817
+ * src/zui_foo.srvd.xml — minimal metadata wrapper
3818
+ *
3819
+ * The handler uses the string form of `createHandler` ('SRVD') because
3820
+ * the ADK object (`AdkServiceDefinition`) is a lightweight class without
3821
+ * the AdkObject save/lock machinery — all lifecycle is source-based.
3822
+ *
3823
+ * We override `serialize` so the source file gets the `.asrvd` extension
3824
+ * instead of the default `.abap`.
3825
+ */
3826
+ const serviceDefinitionHandler = createHandler("SRVD", {
3827
+ schema: srvd,
3828
+ version: "v1.0.0",
3829
+ serializer: "LCL_OBJECT_SRVD",
3830
+ serializer_version: "v1.0.0",
3831
+ toAbapGit: (obj) => ({ SKEY: {
3832
+ TYPE: "SRVD",
3833
+ NAME: String(obj?.name ?? "").toUpperCase()
3834
+ } }),
3835
+ getSource: (obj) => typeof obj?.getSource === "function" ? obj.getSource() : Promise.resolve(""),
3836
+ fromAbapGit: ({ SKEY }) => ({ name: String(SKEY?.NAME ?? "").toUpperCase() }),
3837
+ async serialize(object, ctx) {
3838
+ const files = [];
3839
+ const objectName = ctx.getObjectName(object);
3840
+ const source = await (typeof object?.getSource === "function" ? object.getSource() : Promise.resolve(""));
3841
+ if (source) files.push(ctx.createFile(`${objectName}.${ctx.fileExtension}.asrvd`, source));
3842
+ const xmlContent = ctx.toAbapGitXml(object);
3843
+ files.push(ctx.createFile(`${objectName}.${ctx.fileExtension}.xml`, xmlContent));
3844
+ return files;
3845
+ },
3846
+ setSources: (obj, sources) => {
3847
+ if (sources.main) obj._pendingSource = sources.main;
3848
+ }
3849
+ });
3850
+
3851
+ //#endregion
3852
+ //#region src/lib/handlers/objects/srvb.ts
3853
+ /**
3854
+ * SRVB (RAP Service Binding) object handler for abapGit format
3855
+ *
3856
+ * Unlike BDEF/SRVD, SRVB is **metadata-only** — there is no `.abdl`/
3857
+ * `.asrvd`-style source text. The handler writes a single
3858
+ * `<name>.srvb.xml` file carrying a minimal SKEY + BINDING block.
3859
+ *
3860
+ * File layout:
3861
+ * src/zui_foo.srvb.xml — metadata only
3862
+ *
3863
+ * Mirrors the minimal-block approach used by
3864
+ * zcl_abapgit_object_srvb (abapGit upstream serialiser).
3865
+ */
3866
+ const serviceBindingHandler = createHandler("SRVB", {
3867
+ schema: srvb,
3868
+ version: "v1.0.0",
3869
+ serializer: "LCL_OBJECT_SRVB",
3870
+ serializer_version: "v1.0.0",
3871
+ toAbapGit: (obj) => ({
3872
+ SKEY: {
3873
+ TYPE: "SRVB",
3874
+ NAME: String(obj?.name ?? "").toUpperCase()
3875
+ },
3876
+ BINDING: {
3877
+ TYPE: "odataV4",
3878
+ VERSION: "4",
3879
+ CATEGORY: "odata_v4_ui"
3880
+ }
3881
+ }),
3882
+ fromAbapGit: ({ SKEY }) => ({ name: String(SKEY?.NAME ?? "").toUpperCase() }),
3883
+ async serialize(object, ctx) {
3884
+ const objectName = ctx.getObjectName(object);
3885
+ const xmlContent = ctx.toAbapGitXml(object);
3886
+ return [ctx.createFile(`${objectName}.${ctx.fileExtension}.xml`, xmlContent)];
3887
+ }
3888
+ });
3889
+
3890
+ //#endregion
3891
+ //#region src/lib/folder-logic.ts
3892
+ function stripSlashes(s) {
3893
+ let start = 0;
3894
+ let end = s.length;
3895
+ while (start < end && s[start] === "/") start++;
3896
+ while (end > start && s[end - 1] === "/") end--;
3897
+ return s.slice(start, end);
3898
+ }
3899
+ /**
3900
+ * Parse FOLDER_LOGIC from .abapgit.xml content
3901
+ */
3902
+ function parseFolderLogicFromAbapGitXml(xmlContent) {
3903
+ const match = /<FOLDER_LOGIC>([^<]+)<\/FOLDER_LOGIC>/i.exec(xmlContent);
3904
+ if (!match) return;
3905
+ const normalized = match[1].trim().toUpperCase();
3906
+ if (normalized === "PREFIX") return "prefix";
3907
+ if (normalized === "FULL") return "full";
3908
+ }
3909
+ /**
3910
+ * Parse STARTING_FOLDER from .abapgit.xml content
3911
+ */
3912
+ function parseStartingFolderFromAbapGitXml(xmlContent) {
3913
+ const match = /<STARTING_FOLDER>([^<]+)<\/STARTING_FOLDER>/i.exec(xmlContent);
3914
+ return match ? match[1].trim() : void 0;
3915
+ }
3916
+ /**
3917
+ * Parse abapGit repository metadata from .abapgit.xml content
3918
+ */
3919
+ function parseAbapGitMetadata(xmlContent) {
3920
+ return {
3921
+ folderLogic: parseFolderLogicFromAbapGitXml(xmlContent) ?? "prefix",
3922
+ startingFolder: parseStartingFolderFromAbapGitXml(xmlContent) ?? "/src/"
3923
+ };
3924
+ }
3925
+ /**
3926
+ * Reverse of calculatePackageDir — compute SAP package name from directory path
3927
+ *
3928
+ * Given a directory path relative to the starting folder, the folder logic,
3929
+ * and the root package name, compute the SAP package name.
3930
+ *
3931
+ * PREFIX mode: root 'ZABAPGIT_EXAMPLES' + dir 'clas' → 'ZABAPGIT_EXAMPLES_CLAS'
3932
+ * FULL mode: dir 'zabapgit_examples_clas' → 'ZABAPGIT_EXAMPLES_CLAS'
3933
+ *
3934
+ * @param dirPath - Directory path relative to starting folder
3935
+ * @param folderLogic - Folder logic mode (prefix or full)
3936
+ * @param rootPackage - Root SAP package name
3937
+ * @returns SAP package name
3938
+ */
3939
+ function resolvePackageFromDir(dirPath, folderLogic, rootPackage) {
3940
+ if (!dirPath || dirPath === "." || dirPath === "/") return rootPackage;
3941
+ const normalized = stripSlashes(dirPath);
3942
+ if (!normalized) return rootPackage;
3943
+ const parts = normalized.split("/").filter(Boolean);
3944
+ if (parts.length === 0) return rootPackage;
3945
+ switch (folderLogic) {
3946
+ case "prefix": {
3947
+ let pkg = rootPackage;
3948
+ for (const part of parts) pkg = pkg + "_" + part.toUpperCase();
3949
+ return pkg;
3950
+ }
3951
+ case "full":
3952
+ case "full-with-root": return parts.at(-1).toUpperCase();
3953
+ default: return rootPackage;
3954
+ }
3955
+ }
3956
+ /**
3957
+ * Reverse of resolvePackageFromDir — given a SAP package name and the
3958
+ * relative directory of an object, back-derive the root package.
3959
+ *
3960
+ * PREFIX mode: sapPackage 'ZABAPGIT_EXAMPLES_FUGR' + dir 'fugr' → 'ZABAPGIT_EXAMPLES'
3961
+ * FULL mode: cannot derive root (returns undefined)
3962
+ *
3963
+ * @param sapPackage - Actual SAP package name (from GET response)
3964
+ * @param relDir - Directory path relative to starting folder
3965
+ * @param folderLogic - Folder logic mode
3966
+ * @returns Root package name, or undefined if it cannot be derived
3967
+ */
3968
+ function reverseResolveRootPackage(sapPackage, relDir, folderLogic) {
3969
+ if (!relDir || relDir === "." || relDir === "/") return sapPackage;
3970
+ const normalized = stripSlashes(relDir);
3971
+ if (!normalized) return sapPackage;
3972
+ const parts = normalized.split("/").filter(Boolean);
3973
+ if (parts.length === 0) return sapPackage;
3974
+ switch (folderLogic) {
3975
+ case "prefix": {
3976
+ const suffix = "_" + parts.map((p) => p.toUpperCase()).join("_");
3977
+ if (sapPackage.toUpperCase().endsWith(suffix)) return sapPackage.slice(0, -suffix.length);
3978
+ return;
3979
+ }
3980
+ case "full":
3981
+ case "full-with-root": return;
3982
+ default: return;
3983
+ }
3984
+ }
3985
+ /**
3986
+ * Parse folder logic from a string value (CLI option or config)
3987
+ */
3988
+ function parseFolderLogic(value) {
3989
+ if (typeof value !== "string") return;
3990
+ const normalized = value.trim().toLowerCase();
3991
+ if (normalized === "prefix" || normalized === "full" || normalized === "full-with-root") return normalized;
3992
+ }
3993
+ /**
3994
+ * Calculate package directory based on folder logic (for import/serialization)
3995
+ *
3996
+ * @param packagePath - Full package hierarchy from root to current
3997
+ * @param folderLogic - Folder logic mode
3998
+ * @returns Package directory relative to src/
3999
+ */
4000
+ function calculatePackageDir(packagePath, folderLogic) {
4001
+ if (packagePath.length === 0) return "";
4002
+ switch (folderLogic) {
4003
+ case "prefix": {
4004
+ if (packagePath.length === 1) return "";
4005
+ const parts = [];
4006
+ for (let i = 1; i < packagePath.length; i++) {
4007
+ const fullName = packagePath[i];
4008
+ const prefix = packagePath[i - 1] + "_";
4009
+ const relativeName = fullName.startsWith(prefix) ? fullName.slice(prefix.length) : fullName;
4010
+ parts.push(relativeName.toLowerCase());
4011
+ }
4012
+ return parts.join("/");
4013
+ }
4014
+ case "full": return packagePath.map((p) => p.toLowerCase()).join("/");
4015
+ case "full-with-root": return packagePath.map((p) => p.toLowerCase()).join("/");
4016
+ default: return "";
4017
+ }
4018
+ }
4019
+ /**
4020
+ * Generate .abapgit.xml repository metadata file
4021
+ */
4022
+ function generateAbapGitXml(folderLogic) {
4023
+ return `<?xml version="1.0" encoding="utf-8"?>
4024
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4025
+ <asx:values>
4026
+ <DATA>
4027
+ <MASTER_LANGUAGE>E</MASTER_LANGUAGE>
4028
+ <STARTING_FOLDER>/src/</STARTING_FOLDER>
4029
+ <FOLDER_LOGIC>${folderLogic === "prefix" ? "PREFIX" : "FULL"}</FOLDER_LOGIC>
4030
+ </DATA>
4031
+ </asx:values>
4032
+ </asx:abap>
4033
+ `;
4034
+ }
4035
+
4036
+ //#endregion
4037
+ //#region src/lib/deserializer.ts
4038
+ /**
4039
+ * abapGit file naming convention:
4040
+ * - XML metadata: {name}.{type}.xml (e.g., zcl_myclass.clas.xml)
4041
+ * - Source code: {name}.{type}.abap (e.g., zcl_myclass.clas.abap)
4042
+ * - Source includes: {name}.{type}.{suffix}.abap (e.g., zcl_myclass.clas.testclasses.abap)
4043
+ */
4044
+ /**
4045
+ * Parse abapGit filename to extract object info
4046
+ */
4047
+ function parseAbapGitFilename(filename) {
4048
+ const match = filename.match(/^([^.]+)\.([^.]+)(?:\.([^.]+))?\.(\w+)$/);
4049
+ if (!match) return null;
4050
+ const [, name, type, suffixOrExt, extension] = match;
4051
+ if (extension === "xml" || extension === "abap") return {
4052
+ name: name.toUpperCase(),
4053
+ type: type.toUpperCase(),
4054
+ suffix: suffixOrExt && suffixOrExt !== extension ? suffixOrExt : void 0,
4055
+ extension
4056
+ };
4057
+ return null;
4058
+ }
4059
+ /**
4060
+ * Deserialize abapGit files to ADK objects
4061
+ *
4062
+ * True generator - yields objects one at a time as they're discovered.
4063
+ * Resolves packageRef using abapGit folder logic when rootPackage is provided.
4064
+ *
4065
+ * @param fileTree - Virtual file system to read from
4066
+ * @param client - ADT client for creating ADK objects
4067
+ * @param options - Export options (root package, language version, etc.)
4068
+ */
4069
+ async function* deserialize(fileTree, client, options) {
4070
+ const adk = createAdk(client);
4071
+ let folderLogic = "prefix";
4072
+ let startDir = "";
4073
+ const hasAbapGitXml = await fileTree.exists(".abapgit.xml");
4074
+ if (hasAbapGitXml) try {
4075
+ const meta = parseAbapGitMetadata(await fileTree.read(".abapgit.xml"));
4076
+ folderLogic = meta.folderLogic;
4077
+ startDir = stripSlashes(meta.startingFolder);
4078
+ } catch {}
4079
+ const xmlFiles = await fileTree.glob("**/*.xml");
4080
+ const objectMap = /* @__PURE__ */ new Map();
4081
+ const supportedTypes = new Set(getSupportedTypes().map((t) => t.toLowerCase()));
4082
+ for (const xmlPath of xmlFiles) {
4083
+ if (xmlPath.endsWith(".abapgit.xml")) continue;
4084
+ if (xmlPath.endsWith("package.devc.xml")) continue;
4085
+ const parsed = parseAbapGitFilename(xmlPath.split("/").pop());
4086
+ if (!parsed) continue;
4087
+ if (!supportedTypes.has(parsed.type.toLowerCase())) continue;
4088
+ if (parsed.suffix) continue;
4089
+ const key = `${parsed.name}:${parsed.type}`;
4090
+ if (!objectMap.has(key)) objectMap.set(key, {
4091
+ name: parsed.name,
4092
+ type: parsed.type,
4093
+ sourceFiles: []
4094
+ });
4095
+ const obj = objectMap.get(key);
4096
+ obj.xmlFile = xmlPath;
4097
+ }
4098
+ const abapFiles = await fileTree.glob("**/*.abap");
4099
+ for (const abapPath of abapFiles) {
4100
+ const parsed = parseAbapGitFilename(abapPath.split("/").pop());
4101
+ if (!parsed) continue;
4102
+ const key = `${parsed.name}:${parsed.type}`;
4103
+ const obj = objectMap.get(key);
4104
+ if (obj) obj.sourceFiles.push({
4105
+ path: abapPath,
4106
+ suffix: parsed.suffix
4107
+ });
4108
+ }
4109
+ for (const [, objFiles] of objectMap) {
4110
+ if (!objFiles.xmlFile) continue;
4111
+ const handler = getHandler(objFiles.type);
4112
+ if (!handler) continue;
4113
+ try {
4114
+ const xmlContent = await fileTree.read(objFiles.xmlFile);
4115
+ const values = handler.schema.parse(xmlContent)?.abapGit?.abap?.values ?? {};
4116
+ const sources = {};
4117
+ for (const { path, suffix } of objFiles.sourceFiles) {
4118
+ const content = await fileTree.read(path);
4119
+ const sourceKey = suffix ? handler.suffixToSourceKey?.[suffix] ?? suffix : "main";
4120
+ sources[sourceKey] = content;
4121
+ }
4122
+ const payload = handler.fromAbapGit ? handler.fromAbapGit(values) : { name: objFiles.name };
4123
+ const objectName = payload.name || objFiles.name;
4124
+ const fullData = {
4125
+ ...payload,
4126
+ name: objectName
4127
+ };
4128
+ const adkType = typeof payload.type === "string" ? payload.type : objFiles.type;
4129
+ const adkObject = adk.getWithData(fullData, adkType);
4130
+ if (Object.keys(sources).length > 0) if (handler.setSources) handler.setSources(adkObject, sources);
4131
+ else {
4132
+ if (sources["main"]) adkObject._pendingSource = sources["main"];
4133
+ if (Object.keys(sources).length > 1) adkObject._pendingSources = sources;
4134
+ }
4135
+ if (payload.description) adkObject._pendingDescription = payload.description;
4136
+ if (hasAbapGitXml) {
4137
+ const sourceDir = objFiles.xmlFile.split("/").slice(0, -1).join("/");
4138
+ adkObject._relDir = sourceDir.startsWith(startDir) ? sourceDir.slice(startDir.length).replace(/^\/+/, "") : sourceDir;
4139
+ adkObject._folderLogic = folderLogic;
4140
+ }
4141
+ if (options?.rootPackage) {
4142
+ const data = adkObject._data;
4143
+ if (data && !data.packageRef) if (hasAbapGitXml) data.packageRef = { name: resolvePackageFromDir(adkObject._relDir ?? "", folderLogic, options.rootPackage) };
4144
+ else data.packageRef = { name: options.rootPackage };
4145
+ }
4146
+ if (options?.abapLanguageVersion) {
4147
+ const data = adkObject._data;
4148
+ if (data && !data.abapLanguageVersion) data.abapLanguageVersion = abapLangVerToAdt(options.abapLanguageVersion) ?? options.abapLanguageVersion;
4149
+ }
4150
+ yield adkObject;
4151
+ if (objFiles.type === "FUGR" && payload._functions) {
4152
+ const fmDescriptors = extractFunctionDescriptors(payload._functions);
4153
+ const fmSources = adkObject._pendingFmSources;
4154
+ for (const fm of fmDescriptors) try {
4155
+ const fmData = {
4156
+ name: fm.funcName,
4157
+ type: "FUGR/FF",
4158
+ _groupName: objectName,
4159
+ description: fm.shortText ?? "",
4160
+ processingType: fm.processingType,
4161
+ basXMLEnabled: fm.basXMLEnabled
4162
+ };
4163
+ const fmObject = adk.getWithData(fmData, "FUGR/FF");
4164
+ const fmSourceKey = fm.funcName.toLowerCase();
4165
+ const fmSource = fmSources?.[fmSourceKey];
4166
+ if (fmSource) fmObject._pendingSource = fmSource;
4167
+ if (options?.abapLanguageVersion) {
4168
+ const fmObjData = fmObject._data;
4169
+ if (fmObjData && !fmObjData.abapLanguageVersion) fmObjData.abapLanguageVersion = abapLangVerToAdt(options.abapLanguageVersion) ?? options.abapLanguageVersion;
4170
+ }
4171
+ yield fmObject;
4172
+ } catch (fmError) {
4173
+ console.error(`Failed to deserialize FM ${fm.funcName} in FUGR ${objectName}:`, fmError);
4174
+ }
4175
+ }
4176
+ } catch (error) {
4177
+ console.error(`Failed to deserialize ${objFiles.type} ${objFiles.name}:`, error);
4178
+ }
4179
+ }
4180
+ }
4181
+
4182
+ //#endregion
4183
+ //#region src/lib/format-plugin.ts
4184
+ const abapgitFormatPlugin = {
4185
+ id: "abapgit",
4186
+ description: "abapGit serialization format",
4187
+ get supportedTypes() {
4188
+ return getSupportedTypes();
4189
+ },
4190
+ getHandler(type) {
4191
+ return getHandler(type);
4192
+ },
4193
+ parseFilename(filename) {
4194
+ return parseAbapGitFilename(filename) ?? void 0;
4195
+ }
4196
+ };
4197
+
4198
+ //#endregion
4199
+ //#region src/lib/serializer.ts
4200
+ /**
4201
+ * Serialize ADK objects to abapGit format
4202
+ *
4203
+ * This class uses the handler registry to delegate serialization
4204
+ * to type-specific handlers.
4205
+ */
4206
+ var AbapGitSerializer = class {
4207
+ /**
4208
+ * Serialize a single object (called by plugin API)
4209
+ */
4210
+ async serializeObjectPublic(obj, targetPath, packageDir) {
4211
+ const fullPackageDir = join(targetPath, "src", packageDir);
4212
+ mkdirSync(fullPackageDir, { recursive: true });
4213
+ const objectType = getTypeForKind(obj.kind) ?? obj.type;
4214
+ const handler = getHandler(objectType);
4215
+ if (!handler) throw new Error(`No handler available for object type: ${objectType} (kind: ${obj.kind})`);
4216
+ const serializedFiles = await handler.serialize(obj);
4217
+ const writtenFiles = [];
4218
+ for (const file of serializedFiles) {
4219
+ const filePath = join(fullPackageDir, file.path);
4220
+ writeFileSync(filePath, file.content, file.encoding ?? "utf8");
4221
+ writtenFiles.push(filePath);
4222
+ }
4223
+ return writtenFiles;
4224
+ }
4225
+ };
4226
+
4227
+ //#endregion
4228
+ //#region src/lib/abapgit.ts
4229
+ const serializer = new AbapGitSerializer();
4230
+ let currentFolderLogic = "prefix";
4231
+ /**
4232
+ * Recursively collect all file paths under a directory.
4233
+ */
4234
+ function walkDir(dir, results = []) {
4235
+ if (!existsSync(dir)) return results;
4236
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
4237
+ const full = join(dir, entry.name);
4238
+ if (entry.isDirectory()) walkDir(full, results);
4239
+ else results.push(full);
4240
+ }
4241
+ return results;
4242
+ }
4243
+ /**
4244
+ * Lazy per-srcDir file index.
4245
+ *
4246
+ * Maps srcDir → (prefix → [absolute file paths]), where prefix is
4247
+ * `${name}.${type}.` in lower-case. Built at most once per srcDir per
4248
+ * process, so the O(repo-size) directory walk is amortised across all
4249
+ * `format.delete()` calls in a single import run instead of repeated for
4250
+ * every deleted object.
4251
+ */
4252
+ const srcDirIndexCache = /* @__PURE__ */ new Map();
4253
+ function getOrBuildSrcIndex(srcDir) {
4254
+ const cached = srcDirIndexCache.get(srcDir);
4255
+ if (cached) return cached;
4256
+ const index = /* @__PURE__ */ new Map();
4257
+ for (const filePath of walkDir(srcDir)) {
4258
+ const fname = basename(filePath).toLowerCase();
4259
+ const first = fname.indexOf(".");
4260
+ if (first === -1) continue;
4261
+ const second = fname.indexOf(".", first + 1);
4262
+ if (second === -1) continue;
4263
+ const key = fname.substring(0, second + 1);
4264
+ const bucket = index.get(key);
4265
+ if (bucket) bucket.push(filePath);
4266
+ else index.set(key, [filePath]);
4267
+ }
4268
+ srcDirIndexCache.set(srcDir, index);
4269
+ return index;
4270
+ }
4271
+ /**
4272
+ * Find all abapGit files for a given object name and type.
4273
+ *
4274
+ * abapGit naming convention: `{name}.{type}[.suffix].{ext}`
4275
+ * e.g. `zcl_foo.clas.xml`, `zcl_foo.clas.locals_def.abap`
4276
+ *
4277
+ * Matching is done on the filename base: `{name}.{type}.`. SAP ABAP object
4278
+ * names and types **never contain a dot**, so the prefix is unambiguous —
4279
+ * `ztabl_del.tabl.` cannot accidentally match `ztabl_del_ext.tabl.xml`
4280
+ * because the separator after `ztabl_del` in the prefix is `.` while the
4281
+ * other file has `_ext.`.
4282
+ *
4283
+ * Uses a lazy per-srcDir index so the directory tree is walked at most once
4284
+ * per deletion batch rather than once per object.
4285
+ */
4286
+ function findObjectFiles(srcDir, name, type) {
4287
+ const prefix = `${name.toLowerCase()}.${type.toLowerCase()}.`;
4288
+ return getOrBuildSrcIndex(srcDir).get(prefix) ?? [];
4289
+ }
4290
+ function readFolderLogicFromExistingRepo(targetPath) {
4291
+ const abapgitXmlPath = join(targetPath, ".abapgit.xml");
4292
+ if (!existsSync(abapgitXmlPath)) return;
4293
+ try {
4294
+ return parseFolderLogicFromAbapGitXml(readFileSync(abapgitXmlPath, "utf-8"));
4295
+ } catch {
4296
+ return;
4297
+ }
4298
+ }
4299
+ function resolveFolderLogic(context, targetPath) {
4300
+ const cliFolderLogic = parseFolderLogic(context.formatOptions?.folderLogic);
4301
+ if (cliFolderLogic) return cliFolderLogic;
4302
+ const existingRepoFolderLogic = readFolderLogicFromExistingRepo(targetPath);
4303
+ if (existingRepoFolderLogic) return existingRepoFolderLogic;
4304
+ const configuredFolderLogic = parseFolderLogic(context.configFormatOptions?.folderLogic);
4305
+ if (configuredFolderLogic) return configuredFolderLogic;
4306
+ return "prefix";
4307
+ }
4308
+ /**
4309
+ * abapGit Plugin
4310
+ *
4311
+ * Provides import/export of ADK objects to abapGit repository format.
4312
+ */
4313
+ const abapGitPlugin = createPlugin({
4314
+ name: "abapGit",
4315
+ version: "1.0.0",
4316
+ description: "abapGit format plugin for ADK objects",
4317
+ registry: {
4318
+ isSupported,
4319
+ getSupportedTypes
4320
+ },
4321
+ format: {
4322
+ async import(object, targetPath, context) {
4323
+ try {
4324
+ const objPackage = object.type?.startsWith("DEVC") ? object.name : object.package || object.name || "ROOT";
4325
+ const packagePath = await context.resolvePackagePath(objPackage);
4326
+ const folderLogic = resolveFolderLogic(context, targetPath);
4327
+ currentFolderLogic = folderLogic;
4328
+ const packageDir = calculatePackageDir(packagePath, folderLogic);
4329
+ return {
4330
+ success: true,
4331
+ filesCreated: await serializer.serializeObjectPublic(object, targetPath, packageDir)
4332
+ };
4333
+ } catch (error) {
4334
+ return {
4335
+ success: false,
4336
+ filesCreated: [],
4337
+ errors: [error instanceof Error ? error.message : String(error)]
4338
+ };
4339
+ }
4340
+ },
4341
+ export: (fileTree, client, options) => deserialize(fileTree, client, options),
4342
+ async delete(objectRef, targetPath, _context) {
4343
+ try {
4344
+ const matchedFiles = findObjectFiles(join(targetPath, "src"), objectRef.name, objectRef.type);
4345
+ const filesRemoved = [];
4346
+ const errors = [];
4347
+ for (const filePath of matchedFiles) try {
4348
+ unlinkSync(filePath);
4349
+ filesRemoved.push(relative(targetPath, filePath));
4350
+ } catch (error) {
4351
+ if (error.code === "ENOENT") {
4352
+ filesRemoved.push(relative(targetPath, filePath));
4353
+ continue;
4354
+ }
4355
+ errors.push(error instanceof Error ? `Failed to delete ${relative(targetPath, filePath)}: ${error.message}` : `Failed to delete ${relative(targetPath, filePath)}: ${String(error)}`);
4356
+ }
4357
+ return {
4358
+ success: errors.length === 0,
4359
+ filesRemoved,
4360
+ ...errors.length > 0 ? { errors } : {}
4361
+ };
4362
+ } catch (error) {
4363
+ return {
4364
+ success: false,
4365
+ filesRemoved: [],
4366
+ errors: [error instanceof Error ? error.message : String(error)]
4367
+ };
4368
+ }
4369
+ }
4370
+ },
4371
+ hooks: { async afterImport(targetPath) {
4372
+ mkdirSync(targetPath, { recursive: true });
4373
+ writeFileSync(join(targetPath, ".abapgit.xml"), generateAbapGitXml(currentFolderLogic), "utf-8");
4374
+ } }
4375
+ });
4376
+
4377
+ //#endregion
4378
+ //#region src/lib/filename/adt-uri-to-path.ts
4379
+ /**
4380
+ * Convert an ADT URI to an on-disk abapGit filename.
4381
+ *
4382
+ * abapGit stores objects as `<name>.<type>.<ext>` inside `src/`.
4383
+ * Classes have additional includes serialised as
4384
+ * `<name>.clas.<suffix>.abap`. Function modules become
4385
+ * `<group>.fugr.<fm_name>.abap`. Namespaces are rendered as
4386
+ * `(namespace)name`.
4387
+ *
4388
+ * Returns `null` for URIs we don't recognise; callers may warn or fall
4389
+ * back to a synthetic path.
4390
+ */
4391
+ /**
4392
+ * Apply abapGit namespace transform: `/MYNS/zcl_foo` → `(myns)zcl_foo`.
4393
+ * Case is lower-cased afterwards; name without namespace returned as-is
4394
+ * (lower-cased).
4395
+ */
4396
+ function applyNamespace(raw) {
4397
+ const nsMatch = /^\/([^/]+)\/(.*)$/.exec(raw);
4398
+ if (nsMatch) {
4399
+ const [, ns, rest] = nsMatch;
4400
+ return `(${ns.toLowerCase()})${rest.toLowerCase()}`;
4401
+ }
4402
+ return raw.toLowerCase();
4403
+ }
4404
+ function stripFragment(uri) {
4405
+ const hashIndex = uri.indexOf("#");
4406
+ return hashIndex >= 0 ? uri.slice(0, hashIndex) : uri;
4407
+ }
4408
+ const CLASS_INCLUDE_TO_SUFFIX = {
4409
+ testclasses: ABAPGIT_SUFFIX.testclasses,
4410
+ definitions: ABAPGIT_SUFFIX.definitions,
4411
+ implementations: ABAPGIT_SUFFIX.implementations,
4412
+ macros: ABAPGIT_SUFFIX.macros,
4413
+ localtypes: ABAPGIT_SUFFIX.localtypes
4414
+ };
4415
+ const RULES = [
4416
+ {
4417
+ test: /^\/sap\/bc\/adt\/oo\/classes\/([^/]+)\/includes\/([^/]+)$/,
4418
+ build: (m) => {
4419
+ const name = applyNamespace(decodeURIComponent(m[1]));
4420
+ const include = m[2].toLowerCase();
4421
+ const suffix = CLASS_INCLUDE_TO_SUFFIX[include];
4422
+ return suffix ? `src/${name}.clas.${suffix}.abap` : `src/${name}.clas.${include}.abap`;
4423
+ }
4424
+ },
4425
+ {
4426
+ test: /^\/sap\/bc\/adt\/oo\/classes\/([^/]+)\/source\/main$/,
4427
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.clas.abap`
4428
+ },
4429
+ {
4430
+ test: /^\/sap\/bc\/adt\/oo\/classes\/([^/]+)$/,
4431
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.clas.abap`
4432
+ },
4433
+ {
4434
+ test: /^\/sap\/bc\/adt\/oo\/interfaces\/([^/]+?)(?:\/source\/main)?$/,
4435
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.intf.abap`
4436
+ },
4437
+ {
4438
+ test: /^\/sap\/bc\/adt\/programs\/programs\/([^/]+?)(?:\/source\/main)?$/,
4439
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.prog.abap`
4440
+ },
4441
+ {
4442
+ test: /^\/sap\/bc\/adt\/functions\/groups\/([^/]+)$/,
4443
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.fugr.xml`
4444
+ },
4445
+ {
4446
+ test: /^\/sap\/bc\/adt\/functions\/groups\/([^/]+)\/fmodules\/([^/]+?)(?:\/source\/main)?$/,
4447
+ build: (m) => {
4448
+ return `src/${applyNamespace(decodeURIComponent(m[1]))}.fugr.${applyNamespace(decodeURIComponent(m[2]))}.abap`;
4449
+ }
4450
+ },
4451
+ {
4452
+ test: /^\/sap\/bc\/adt\/functions\/groups\/([^/]+)\/includes\/([^/]+?)(?:\/source\/main)?$/,
4453
+ build: (m) => {
4454
+ return `src/${applyNamespace(decodeURIComponent(m[1]))}.fugr.${applyNamespace(decodeURIComponent(m[2]))}.abap`;
4455
+ }
4456
+ },
4457
+ {
4458
+ test: /^\/sap\/bc\/adt\/ddic\/ddl\/sources\/([^/]+?)(?:\/source\/main)?$/,
4459
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.ddls.asddls`
4460
+ },
4461
+ {
4462
+ test: /^\/sap\/bc\/adt\/acm\/dcl\/sources\/([^/]+?)(?:\/source\/main)?$/,
4463
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.dcls.asdcls`
4464
+ },
4465
+ {
4466
+ test: /^\/sap\/bc\/adt\/bo\/behaviordefinitions\/([^/]+?)(?:\/source\/main)?$/,
4467
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.bdef.abdl`
4468
+ },
4469
+ {
4470
+ test: /^\/sap\/bc\/adt\/ddic\/srvd\/sources\/([^/]+?)(?:\/source\/main)?$/,
4471
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.srvd.asrvd`
4472
+ },
4473
+ {
4474
+ test: /^\/sap\/bc\/adt\/businessservices\/bindings\/([^/]+?)(?:\/publishedstates)?$/,
4475
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.srvb.xml`
4476
+ },
4477
+ {
4478
+ test: /^\/sap\/bc\/adt\/ddic\/domains\/([^/]+)$/,
4479
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.doma.xml`
4480
+ },
4481
+ {
4482
+ test: /^\/sap\/bc\/adt\/ddic\/dataelements\/([^/]+)$/,
4483
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.dtel.xml`
4484
+ },
4485
+ {
4486
+ test: /^\/sap\/bc\/adt\/ddic\/structures\/([^/]+)$/,
4487
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.tabl.xml`
4488
+ },
4489
+ {
4490
+ test: /^\/sap\/bc\/adt\/ddic\/tables\/([^/]+)$/,
4491
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.tabl.xml`
4492
+ },
4493
+ {
4494
+ test: /^\/sap\/bc\/adt\/packages\/([^/]+)$/,
4495
+ build: (m) => `src/${applyNamespace(decodeURIComponent(m[1]))}.devc.xml`
4496
+ }
4497
+ ];
4498
+ /**
4499
+ * Convert an ADT URI to the abapGit on-disk filename (lower-cased,
4500
+ * namespace-aware). Returns `null` when the URI shape is not recognised.
4501
+ */
4502
+ function adtUriToAbapGitPath(uri) {
4503
+ if (!uri) return null;
4504
+ const clean = stripFragment(uri).trim();
4505
+ for (const rule of RULES) {
4506
+ const m = rule.test.exec(clean);
4507
+ if (m) return rule.build(m);
4508
+ }
4509
+ return null;
4510
+ }
4511
+
4512
+ //#endregion
4513
+ //#region src/index.ts
4514
+ registerFormatPlugin(abapgitFormatPlugin);
4515
+
4516
+ //#endregion
4517
+ export { abapGitPlugin as AbapGitPlugin, abapGitPlugin, abapGitPlugin as default, abapgitFormatPlugin, adtUriToAbapGitPath, createFindingResolver, formatAbapGitXml, formatXmlAttributes, getHandler, getSupportedTypes, isSupported, moveNamespaceToAbap, parseAbapGitFilename, parseAbapGitMetadata, resolvePackageFromDir, reverseResolveRootPackage };
4518
+ //# sourceMappingURL=index.mjs.map