@abapify/adk 0.3.6 → 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.
@@ -0,0 +1,394 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (!no_symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ //#region src/base/kinds.ts
19
+ /**
20
+ * ADK Object Kinds
21
+ *
22
+ * Central registry of all ADK object types.
23
+ * Import specific kinds for type-safe usage:
24
+ *
25
+ * @example
26
+ * import { TransportRequest } from '../base/kinds';
27
+ * class AdkTransportRequest extends AdkObject<typeof TransportRequest> { ... }
28
+ */
29
+ const TransportRequest = "TransportRequest";
30
+ const TransportTask = "TransportTask";
31
+ const Package = "Package";
32
+ const Class = "Class";
33
+ const Interface = "Interface";
34
+ const FunctionGroup = "FunctionGroup";
35
+ const FunctionModule = "FunctionModule";
36
+ const Program = "Program";
37
+ const Include = "Include";
38
+ const Table = "Table";
39
+ const Structure = "Structure";
40
+ const DataElement = "DataElement";
41
+ const Domain = "Domain";
42
+ const TableType = "TableType";
43
+ const MessageClass = "MessageClass";
44
+ const EnhancementSpot = "EnhancementSpot";
45
+
46
+ //#endregion
47
+ //#region src/base/registry.ts
48
+ /**
49
+ * Parse ADT type into components
50
+ *
51
+ * @example
52
+ * parseAdtType("DEVC/K") // { full: "DEVC/K", main: "DEVC", sub: "K" }
53
+ * parseAdtType("DEVC") // { full: "DEVC", main: "DEVC", sub: undefined }
54
+ */
55
+ function parseAdtType(adtType) {
56
+ const [main, sub] = adtType.split("/");
57
+ return {
58
+ full: adtType,
59
+ main: main.toUpperCase(),
60
+ sub: sub?.toUpperCase()
61
+ };
62
+ }
63
+ /**
64
+ * Get main type from ADT type
65
+ *
66
+ * @example
67
+ * getMainType("DEVC/K") // "DEVC"
68
+ * getMainType("CLAS") // "CLAS"
69
+ */
70
+ function getMainType(adtType) {
71
+ return parseAdtType(adtType).main;
72
+ }
73
+ /** Internal registry storage */
74
+ const registry = /* @__PURE__ */ new Map();
75
+ /** ADT main type to ADK kind mapping */
76
+ const adtToKind = /* @__PURE__ */ new Map();
77
+ /** ADK kind to ADT main type mapping (reverse) */
78
+ const kindToAdt = /* @__PURE__ */ new Map();
79
+ /**
80
+ * Register an ADK object type
81
+ *
82
+ * @param adtType - ADT type, either main (e.g., "CLAS") or full (e.g., "TABL/DS")
83
+ * @param kind - ADK kind constant
84
+ * @param constructor - Object constructor
85
+ * @param options - Optional endpoint and name transform settings
86
+ */
87
+ function registerObjectType(adtType, kind, constructor, options) {
88
+ const normalizedType = adtType.toUpperCase();
89
+ registry.set(normalizedType, {
90
+ kind,
91
+ constructor,
92
+ endpoint: options?.endpoint,
93
+ nameTransform: options?.nameTransform,
94
+ normalizeName: options?.normalizeName
95
+ });
96
+ adtToKind.set(normalizedType, kind);
97
+ kindToAdt.set(kind, normalizedType);
98
+ }
99
+ /**
100
+ * Resolve ADT type to registry entry
101
+ *
102
+ * Tries full type first (e.g., "TABL/DS"), then falls back to main type (e.g., "TABL").
103
+ * This allows registering subtypes with different constructors/endpoints.
104
+ *
105
+ * @param adtType - Full or main ADT type (e.g., "DEVC/K" or "DEVC")
106
+ * @returns Registry entry or undefined if not found
107
+ */
108
+ function resolveType(adtType) {
109
+ const normalized = adtType.toUpperCase();
110
+ const fullMatch = registry.get(normalized);
111
+ if (fullMatch) return fullMatch;
112
+ const mainType = getMainType(adtType);
113
+ return registry.get(mainType);
114
+ }
115
+ /**
116
+ * Resolve ADK kind to registry entry
117
+ *
118
+ * @param kind - ADK kind constant
119
+ * @returns Registry entry or undefined if not found
120
+ */
121
+ function resolveKind(kind) {
122
+ const adtType = kindToAdt.get(kind);
123
+ if (!adtType) return void 0;
124
+ return registry.get(adtType);
125
+ }
126
+ /**
127
+ * Get ADK kind for ADT type
128
+ */
129
+ function getKindForType(adtType) {
130
+ return adtToKind.get(getMainType(adtType));
131
+ }
132
+ /**
133
+ * Get ADT main type for ADK kind
134
+ */
135
+ function getTypeForKind(kind) {
136
+ return kindToAdt.get(kind);
137
+ }
138
+ /**
139
+ * Check if ADT type is registered
140
+ */
141
+ function isTypeRegistered(adtType) {
142
+ return registry.has(getMainType(adtType));
143
+ }
144
+ /**
145
+ * Get all registered ADT types
146
+ */
147
+ function getRegisteredTypes() {
148
+ return Array.from(registry.keys());
149
+ }
150
+ /**
151
+ * Get all registered ADK kinds
152
+ */
153
+ function getRegisteredKinds() {
154
+ return Array.from(kindToAdt.keys());
155
+ }
156
+ /**
157
+ * Get ADT REST endpoint for a type (e.g., 'oo/classes', 'ddic/tabletypes')
158
+ * Checks exact type first (e.g., 'TABL/DS') before falling back to main type.
159
+ */
160
+ function getEndpointForType(adtType) {
161
+ return resolveType(adtType)?.endpoint;
162
+ }
163
+ /**
164
+ * Build the full ADT object URI for a given type and name.
165
+ *
166
+ * @example
167
+ * getObjectUri('CLAS', 'ZCL_MY_CLASS') // '/sap/bc/adt/oo/classes/zcl_my_class'
168
+ * getObjectUri('DEVC', 'ZPACKAGE') // '/sap/bc/adt/packages/ZPACKAGE'
169
+ * getObjectUri('TTYP', 'ZAGE_TTYP_STRTAB') // '/sap/bc/adt/ddic/tabletypes/zage_ttyp_strtab'
170
+ */
171
+ function getObjectUri(adtType, name) {
172
+ const entry = resolveType(adtType);
173
+ if (!entry?.endpoint) return void 0;
174
+ const normalized = entry.normalizeName ? entry.normalizeName(name) : name;
175
+ const transformedName = entry.nameTransform === "preserve" ? encodeURIComponent(normalized) : encodeURIComponent(normalized.toLowerCase());
176
+ return `/sap/bc/adt/${entry.endpoint}/${transformedName}`;
177
+ }
178
+ /**
179
+ * Normalize an object name using type-specific rules.
180
+ *
181
+ * If `adtType` is provided, applies that type's normalizer only.
182
+ * Otherwise, collects all possible normalized forms from every registered type.
183
+ *
184
+ * @returns Array of candidate names (always includes the original).
185
+ *
186
+ * @example
187
+ * normalizeObjectName('SAPLZAGE_FUGR') // ['SAPLZAGE_FUGR', 'ZAGE_FUGR']
188
+ * normalizeObjectName('SAPLZAGE_FUGR', 'FUGR') // ['ZAGE_FUGR']
189
+ * normalizeObjectName('ZCLAS_TEST') // ['ZCLAS_TEST'] (no normalizer matches)
190
+ */
191
+ function normalizeObjectName(name, adtType) {
192
+ if (adtType) return [resolveType(adtType)?.normalizeName?.(name) ?? name];
193
+ const candidates = new Set([name]);
194
+ for (const entry of registry.values()) if (entry.normalizeName) candidates.add(entry.normalizeName(name));
195
+ return Array.from(candidates);
196
+ }
197
+ /**
198
+ * Extract the root object URI from a full (possibly sub-resource) URI.
199
+ *
200
+ * SAP locks must target the object root, not sub-resources like `/source/main`.
201
+ * This function matches against registered endpoint prefixes and strips
202
+ * everything after the object name segment.
203
+ *
204
+ * @returns The root object URI, or the original URI unchanged if no endpoint matches.
205
+ *
206
+ * @example
207
+ * getObjectRootUri('/sap/bc/adt/functions/groups/zage_fugr/source/main')
208
+ * // → '/sap/bc/adt/functions/groups/zage_fugr'
209
+ * getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test/includes/testclasses')
210
+ * // → '/sap/bc/adt/oo/classes/zcl_test'
211
+ * getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test')
212
+ * // → '/sap/bc/adt/oo/classes/zcl_test' (already root)
213
+ */
214
+ function getObjectRootUri(uri) {
215
+ const ADT_PREFIX = "/sap/bc/adt/";
216
+ const endpoints = [];
217
+ for (const entry of registry.values()) if (entry.endpoint) endpoints.push(entry.endpoint);
218
+ endpoints.sort((a, b) => b.length - a.length);
219
+ for (const endpoint of endpoints) {
220
+ const prefix = `${ADT_PREFIX}${endpoint}/`;
221
+ if (uri.startsWith(prefix)) return `${prefix}${uri.slice(prefix.length).split("/")[0]}`;
222
+ }
223
+ return uri;
224
+ }
225
+ /**
226
+ * Known ADT type to ADK kind mappings
227
+ *
228
+ * Repository Objects:
229
+ * - DEVC → Package
230
+ * - CLAS → Class
231
+ * - INTF → Interface
232
+ * - FUGR → FunctionGroup
233
+ * - FUNC → FunctionModule
234
+ * - PROG → Program
235
+ * - INCL → Include
236
+ *
237
+ * Data Dictionary:
238
+ * - TABL → Table
239
+ * - STRU → Structure (actually TABL with different category)
240
+ * - DTEL → DataElement
241
+ * - DOMA → Domain
242
+ * - TTYP → TableType
243
+ *
244
+ * Other:
245
+ * - MSAG → MessageClass
246
+ * - ENHS → EnhancementSpot
247
+ *
248
+ * CTS:
249
+ * - (Transport requests/tasks use different identification)
250
+ */
251
+ const ADT_TYPE_MAPPINGS = {
252
+ DEVC: Package,
253
+ CLAS: Class,
254
+ INTF: Interface,
255
+ FUGR: FunctionGroup,
256
+ FUNC: FunctionModule,
257
+ PROG: Program,
258
+ INCL: Include,
259
+ TABL: Table,
260
+ DTEL: DataElement,
261
+ DOMA: Domain,
262
+ TTYP: TableType,
263
+ MSAG: MessageClass,
264
+ ENHS: EnhancementSpot
265
+ };
266
+
267
+ //#endregion
268
+ //#region src/factory.ts
269
+ var factory_exports = /* @__PURE__ */ __exportAll({
270
+ AdkGenericObject: () => AdkGenericObject,
271
+ createAdk: () => createAdk,
272
+ createAdkFactory: () => createAdkFactory,
273
+ parseXmlIdentity: () => parseXmlIdentity
274
+ });
275
+ /** Pattern to extract adtcore:type from XML */
276
+ const TYPE_PATTERN = /adtcore:type="([^"]+)"/;
277
+ /** Pattern to extract adtcore:name from XML */
278
+ const NAME_PATTERN = /adtcore:name="([^"]+)"/;
279
+ /**
280
+ * Extract ADT type and name from XML
281
+ *
282
+ * Relies on adtcore:type and adtcore:name attributes which are
283
+ * the standard identifiers in ADT XML responses.
284
+ *
285
+ * @param xml - XML string from ADT response
286
+ * @returns Extracted type and name, or undefined if not found
287
+ */
288
+ function parseXmlIdentity(xml) {
289
+ const typeMatch = xml.match(TYPE_PATTERN);
290
+ const nameMatch = xml.match(NAME_PATTERN);
291
+ if (typeMatch && nameMatch) return {
292
+ type: typeMatch[1],
293
+ name: nameMatch[1]
294
+ };
295
+ }
296
+ /**
297
+ * Generic ADK object for unregistered types
298
+ *
299
+ * Provides core functionality (adtcore attributes, links)
300
+ * without type-specific features.
301
+ */
302
+ var AdkGenericObject = class {
303
+ adtType;
304
+ adtMainType;
305
+ adtSubType;
306
+ ctx;
307
+ _name;
308
+ _data;
309
+ constructor(ctx, name, adtType) {
310
+ this.ctx = ctx;
311
+ this._name = name;
312
+ const parsed = parseAdtType(adtType);
313
+ this.adtType = parsed.full;
314
+ this.adtMainType = parsed.main;
315
+ this.adtSubType = parsed.sub;
316
+ }
317
+ get name() {
318
+ return this._name;
319
+ }
320
+ get type() {
321
+ return this.adtType;
322
+ }
323
+ /** Check if data is loaded */
324
+ get isLoaded() {
325
+ return this._data !== void 0;
326
+ }
327
+ /** Get raw data (if loaded) */
328
+ get data() {
329
+ return this._data;
330
+ }
331
+ /** Set data (for manual population) */
332
+ setData(data) {
333
+ this._data = data;
334
+ }
335
+ };
336
+ /**
337
+ * Create ADK factory
338
+ *
339
+ * @param ctx - ADK context with services
340
+ * @returns Factory instance
341
+ */
342
+ function createAdkFactory(ctx) {
343
+ return {
344
+ ctx,
345
+ get(name, adtType) {
346
+ const entry = resolveType(adtType);
347
+ if (entry) return new entry.constructor(ctx, name);
348
+ return new AdkGenericObject(ctx, name, adtType);
349
+ },
350
+ getWithData(data, adtType) {
351
+ const entry = resolveType(adtType);
352
+ if (entry) return new entry.constructor(ctx, data);
353
+ const obj = new AdkGenericObject(ctx, data.name ?? "", adtType);
354
+ obj.setData(data);
355
+ return obj;
356
+ },
357
+ byKind(kind, name) {
358
+ const entry = resolveKind(kind);
359
+ if (!entry) throw new Error(`No constructor registered for kind: ${kind}`);
360
+ return new entry.constructor(ctx, name);
361
+ },
362
+ fromXml(xml) {
363
+ const identity = parseXmlIdentity(xml);
364
+ if (!identity) return;
365
+ return this.get(identity.name, identity.type);
366
+ },
367
+ create(adtType) {
368
+ return this.get("", adtType);
369
+ }
370
+ };
371
+ }
372
+ /**
373
+ * Create ADK factory from ADT client
374
+ *
375
+ * Builds context from client and returns factory.
376
+ * This is the main entry point for most users.
377
+ *
378
+ * @example
379
+ * import { createAdtClient } from '@abapify/adt-client';
380
+ * import { createAdk } from '@abapify/adk';
381
+ *
382
+ * const client = createAdtClient({ ... });
383
+ * const adk = createAdk(client);
384
+ *
385
+ * const cls = adk.get('ZCL_TEST', 'CLAS');
386
+ * await cls.load();
387
+ */
388
+ function createAdk(client) {
389
+ return createAdkFactory({ client });
390
+ }
391
+
392
+ //#endregion
393
+ export { Package as A, Domain as C, Include as D, FunctionModule as E, TransportRequest as F, TransportTask as I, Structure as M, Table as N, Interface as O, TableType as P, DataElement as S, FunctionGroup as T, parseAdtType as _, parseXmlIdentity as a, resolveType as b, getKindForType as c, getObjectUri as d, getRegisteredKinds as f, normalizeObjectName as g, isTypeRegistered as h, factory_exports as i, Program as j, MessageClass as k, getMainType as l, getTypeForKind as m, createAdk as n, ADT_TYPE_MAPPINGS as o, getRegisteredTypes as p, createAdkFactory as r, getEndpointForType as s, AdkGenericObject as t, getObjectRootUri as u, registerObjectType as v, EnhancementSpot as w, Class as x, resolveKind as y };
394
+ //# sourceMappingURL=factory-DtyrTGlN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory-DtyrTGlN.mjs","names":["kinds.Package","kinds.Class","kinds.Interface","kinds.FunctionGroup","kinds.FunctionModule","kinds.Program","kinds.Include","kinds.Table","kinds.DataElement","kinds.Domain","kinds.TableType","kinds.MessageClass","kinds.EnhancementSpot"],"sources":["../src/base/kinds.ts","../src/base/registry.ts","../src/factory.ts"],"sourcesContent":["/**\n * ADK Object Kinds\n *\n * Central registry of all ADK object types.\n * Import specific kinds for type-safe usage:\n *\n * @example\n * import { TransportRequest } from '../base/kinds';\n * class AdkTransportRequest extends AdkObject<typeof TransportRequest> { ... }\n */\n\n// CTS\nexport const TransportRequest = 'TransportRequest' as const;\nexport const TransportTask = 'TransportTask' as const;\n\n// Repository Objects\nexport const Package = 'Package' as const;\nexport const Class = 'Class' as const;\nexport const Interface = 'Interface' as const;\nexport const FunctionGroup = 'FunctionGroup' as const;\nexport const FunctionModule = 'FunctionModule' as const;\nexport const Program = 'Program' as const;\nexport const Include = 'Include' as const;\n\n// Data Dictionary\nexport const Table = 'Table' as const;\nexport const Structure = 'Structure' as const;\nexport const DataElement = 'DataElement' as const;\nexport const Domain = 'Domain' as const;\nexport const TableType = 'TableType' as const;\n\n// Other\nexport const MessageClass = 'MessageClass' as const;\nexport const EnhancementSpot = 'EnhancementSpot' as const;\n\n/** Union type of all ADK kinds */\nexport type AdkKind =\n | typeof TransportRequest\n | typeof TransportTask\n | typeof Package\n | typeof Class\n | typeof Interface\n | typeof FunctionGroup\n | typeof FunctionModule\n | typeof Program\n | typeof Include\n | typeof Table\n | typeof Structure\n | typeof DataElement\n | typeof Domain\n | typeof TableType\n | typeof MessageClass\n | typeof EnhancementSpot;\n\n// ============================================\n// Type-safe Kind → Object mapping\n// ============================================\n\n// Import concrete types for mapping (type-only to avoid circular deps)\nimport type { AdkClass } from '../objects/repository/clas/clas.model';\nimport type { AdkInterface } from '../objects/repository/intf/intf.model';\nimport type { AdkPackage } from '../objects/repository/devc/devc.model';\nimport type { AdkProgram } from '../objects/repository/prog/prog.model';\nimport type { AdkInclude } from '../objects/repository/incl/incl.model';\nimport type { AdkFunctionGroup } from '../objects/repository/fugr/fugr.model';\nimport type { AdkFunctionModule } from '../objects/repository/fugr/func/func.model';\nimport type {\n AdkTransportRequest,\n AdkTransportTask,\n} from '../objects/cts/transport/transport';\nimport type { AdkObject } from './model';\nimport type { AdkDomain } from '../objects/ddic/doma/doma.model';\nimport type { AdkDataElement } from '../objects/ddic/dtel/dtel.model';\nimport type { AdkTable, AdkStructure } from '../objects/ddic/tabl/tabl.model';\nimport type { AdkTableType } from '../objects/ddic/ttyp/ttyp.model';\n\n/**\n * Maps ADK kind to concrete object type\n *\n * Enables type-safe factory methods:\n * ```ts\n * const cls = factory.byKind(Class, 'ZCL_TEST'); // → AdkClass\n * const intf = factory.byKind(Interface, 'ZIF'); // → AdkInterface\n * ```\n */\nexport type AdkObjectForKind<K extends AdkKind> = K extends typeof Class\n ? AdkClass\n : K extends typeof Interface\n ? AdkInterface\n : K extends typeof Package\n ? AdkPackage\n : K extends typeof Program\n ? AdkProgram\n : K extends typeof Include\n ? AdkInclude\n : K extends typeof FunctionGroup\n ? AdkFunctionGroup\n : K extends typeof FunctionModule\n ? AdkFunctionModule\n : K extends typeof TransportRequest\n ? AdkTransportRequest\n : K extends typeof TransportTask\n ? AdkTransportTask\n : K extends typeof Domain\n ? AdkDomain\n : K extends typeof DataElement\n ? AdkDataElement\n : K extends typeof Table\n ? AdkTable\n : K extends typeof Structure\n ? AdkStructure\n : K extends typeof TableType\n ? AdkTableType\n : AdkObject; // fallback\n","/**\n * ADK Object Registry\n *\n * Maps ADT types to ADK object constructors.\n * Supports both full types (DEVC/K) and main types (DEVC).\n *\n * Architecture:\n * - ADT type (external): \"DEVC/K\", \"CLAS/OC\" - from SAP\n * - ADK kind (internal): Package, Class - our abstraction\n * - Constructor: AdkPackage, AdkClass - implementation\n */\n\nimport type { AdkContext } from './context';\nimport type { AdkObject } from './model';\nimport type { AdkKind } from './kinds';\nimport * as kinds from './kinds';\n\n// ============================================\n// Types\n// ============================================\n\n/** Constructor signature for ADK objects */\n\nexport type AdkObjectConstructor<\n T extends AdkObject<AdkKind, any> = AdkObject<AdkKind, any>,\n> = new (ctx: AdkContext, nameOrData: string | any) => T;\n\n/** How to transform object name for the URI path segment */\nexport type NameTransform = 'lowercase' | 'preserve';\n\n/** Registry entry with constructor and kind */\nexport interface RegistryEntry {\n readonly kind: AdkKind;\n readonly constructor: AdkObjectConstructor;\n /** ADT REST endpoint path segment (e.g., 'oo/classes', 'ddic/tabletypes') */\n readonly endpoint?: string;\n /** How to transform the object name in URIs (default: lowercase) */\n readonly nameTransform?: NameTransform;\n /** Optional name normalizer — e.g., strip SAPL prefix for FUGR */\n readonly normalizeName?: (name: string) => string;\n}\n\n// ============================================\n// ADT Type Utilities\n// ============================================\n\n/**\n * Parse ADT type into components\n *\n * @example\n * parseAdtType(\"DEVC/K\") // { full: \"DEVC/K\", main: \"DEVC\", sub: \"K\" }\n * parseAdtType(\"DEVC\") // { full: \"DEVC\", main: \"DEVC\", sub: undefined }\n */\nexport function parseAdtType(adtType: string): {\n full: string;\n main: string;\n sub?: string;\n} {\n const [main, sub] = adtType.split('/');\n return {\n full: adtType,\n main: main.toUpperCase(),\n sub: sub?.toUpperCase(),\n };\n}\n\n/**\n * Get main type from ADT type\n *\n * @example\n * getMainType(\"DEVC/K\") // \"DEVC\"\n * getMainType(\"CLAS\") // \"CLAS\"\n */\nexport function getMainType(adtType: string): string {\n return parseAdtType(adtType).main;\n}\n\n// ============================================\n// Registry\n// ============================================\n\n/** Internal registry storage */\nconst registry = new Map<string, RegistryEntry>();\n\n/** ADT main type to ADK kind mapping */\nconst adtToKind = new Map<string, AdkKind>();\n\n/** ADK kind to ADT main type mapping (reverse) */\nconst kindToAdt = new Map<AdkKind, string>();\n\n/**\n * Test-only: clear all registry state.\n *\n * The registry is module-level singleton state populated by side-effectful\n * `registerObjectType()` calls in `src/objects/repository/**`. Tests that\n * exercise registration need a clean slate, but production code must never\n * call this — it would break every ADK object type resolution.\n *\n * Name intentionally uses the `__` prefix to signal \"not part of the public\n * API\". Do not import this from runtime code.\n */\nexport function __resetRegistryForTests(): void {\n registry.clear();\n adtToKind.clear();\n kindToAdt.clear();\n}\n\n/** Options for registerObjectType */\nexport interface RegisterObjectTypeOptions {\n /** ADT REST endpoint path segment (e.g., 'oo/classes', 'ddic/tabletypes') */\n endpoint?: string;\n /** How to transform the object name in URIs (default: 'lowercase') */\n nameTransform?: NameTransform;\n /** Optional name normalizer — e.g., strip SAPL prefix for FUGR */\n normalizeName?: (name: string) => string;\n}\n\n/**\n * Register an ADK object type\n *\n * @param adtType - ADT type, either main (e.g., \"CLAS\") or full (e.g., \"TABL/DS\")\n * @param kind - ADK kind constant\n * @param constructor - Object constructor\n * @param options - Optional endpoint and name transform settings\n */\nexport function registerObjectType(\n adtType: string,\n kind: AdkKind,\n constructor: AdkObjectConstructor,\n options?: RegisterObjectTypeOptions,\n): void {\n const normalizedType = adtType.toUpperCase();\n\n registry.set(normalizedType, {\n kind,\n constructor,\n endpoint: options?.endpoint,\n nameTransform: options?.nameTransform,\n normalizeName: options?.normalizeName,\n });\n adtToKind.set(normalizedType, kind);\n kindToAdt.set(kind, normalizedType);\n}\n\n/**\n * Resolve ADT type to registry entry\n *\n * Tries full type first (e.g., \"TABL/DS\"), then falls back to main type (e.g., \"TABL\").\n * This allows registering subtypes with different constructors/endpoints.\n *\n * @param adtType - Full or main ADT type (e.g., \"DEVC/K\" or \"DEVC\")\n * @returns Registry entry or undefined if not found\n */\nexport function resolveType(adtType: string): RegistryEntry | undefined {\n const normalized = adtType.toUpperCase();\n // Try full type first (e.g., \"TABL/DS\")\n const fullMatch = registry.get(normalized);\n if (fullMatch) return fullMatch;\n // Fall back to main type (e.g., \"TABL\")\n const mainType = getMainType(adtType);\n return registry.get(mainType);\n}\n\n/**\n * Resolve ADK kind to registry entry\n *\n * @param kind - ADK kind constant\n * @returns Registry entry or undefined if not found\n */\nexport function resolveKind(kind: AdkKind): RegistryEntry | undefined {\n const adtType = kindToAdt.get(kind);\n if (!adtType) return undefined;\n return registry.get(adtType);\n}\n\n/**\n * Get ADK kind for ADT type\n */\nexport function getKindForType(adtType: string): AdkKind | undefined {\n return adtToKind.get(getMainType(adtType));\n}\n\n/**\n * Get ADT main type for ADK kind\n */\nexport function getTypeForKind(kind: AdkKind): string | undefined {\n return kindToAdt.get(kind);\n}\n\n/**\n * Check if ADT type is registered\n */\nexport function isTypeRegistered(adtType: string): boolean {\n return registry.has(getMainType(adtType));\n}\n\n/**\n * Get all registered ADT types\n */\nexport function getRegisteredTypes(): string[] {\n return Array.from(registry.keys());\n}\n\n/**\n * Get all registered ADK kinds\n */\nexport function getRegisteredKinds(): AdkKind[] {\n return Array.from(kindToAdt.keys());\n}\n\n/**\n * Get ADT REST endpoint for a type (e.g., 'oo/classes', 'ddic/tabletypes')\n * Checks exact type first (e.g., 'TABL/DS') before falling back to main type.\n */\nexport function getEndpointForType(adtType: string): string | undefined {\n return resolveType(adtType)?.endpoint;\n}\n\n/**\n * Build the full ADT object URI for a given type and name.\n *\n * @example\n * getObjectUri('CLAS', 'ZCL_MY_CLASS') // '/sap/bc/adt/oo/classes/zcl_my_class'\n * getObjectUri('DEVC', 'ZPACKAGE') // '/sap/bc/adt/packages/ZPACKAGE'\n * getObjectUri('TTYP', 'ZAGE_TTYP_STRTAB') // '/sap/bc/adt/ddic/tabletypes/zage_ttyp_strtab'\n */\nexport function getObjectUri(\n adtType: string,\n name: string,\n): string | undefined {\n const entry = resolveType(adtType);\n if (!entry?.endpoint) return undefined;\n\n const normalized = entry.normalizeName ? entry.normalizeName(name) : name;\n const transformedName =\n entry.nameTransform === 'preserve'\n ? encodeURIComponent(normalized)\n : encodeURIComponent(normalized.toLowerCase());\n\n return `/sap/bc/adt/${entry.endpoint}/${transformedName}`;\n}\n\n/**\n * Normalize an object name using type-specific rules.\n *\n * If `adtType` is provided, applies that type's normalizer only.\n * Otherwise, collects all possible normalized forms from every registered type.\n *\n * @returns Array of candidate names (always includes the original).\n *\n * @example\n * normalizeObjectName('SAPLZAGE_FUGR') // ['SAPLZAGE_FUGR', 'ZAGE_FUGR']\n * normalizeObjectName('SAPLZAGE_FUGR', 'FUGR') // ['ZAGE_FUGR']\n * normalizeObjectName('ZCLAS_TEST') // ['ZCLAS_TEST'] (no normalizer matches)\n */\nexport function normalizeObjectName(name: string, adtType?: string): string[] {\n if (adtType) {\n const entry = resolveType(adtType);\n const normalized = entry?.normalizeName?.(name) ?? name;\n return [normalized];\n }\n\n // No type hint — collect all distinct candidates from every registered normalizer\n const candidates = new Set<string>([name]);\n for (const entry of registry.values()) {\n if (entry.normalizeName) {\n candidates.add(entry.normalizeName(name));\n }\n }\n return Array.from(candidates);\n}\n\n/**\n * Extract the root object URI from a full (possibly sub-resource) URI.\n *\n * SAP locks must target the object root, not sub-resources like `/source/main`.\n * This function matches against registered endpoint prefixes and strips\n * everything after the object name segment.\n *\n * @returns The root object URI, or the original URI unchanged if no endpoint matches.\n *\n * @example\n * getObjectRootUri('/sap/bc/adt/functions/groups/zage_fugr/source/main')\n * // → '/sap/bc/adt/functions/groups/zage_fugr'\n * getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test/includes/testclasses')\n * // → '/sap/bc/adt/oo/classes/zcl_test'\n * getObjectRootUri('/sap/bc/adt/oo/classes/zcl_test')\n * // → '/sap/bc/adt/oo/classes/zcl_test' (already root)\n */\nexport function getObjectRootUri(uri: string): string {\n const ADT_PREFIX = '/sap/bc/adt/';\n\n // Collect all registered endpoints, sorted longest-first to avoid partial matches\n const endpoints: string[] = [];\n for (const entry of registry.values()) {\n if (entry.endpoint) endpoints.push(entry.endpoint);\n }\n endpoints.sort((a, b) => b.length - a.length);\n\n for (const endpoint of endpoints) {\n const prefix = `${ADT_PREFIX}${endpoint}/`;\n if (uri.startsWith(prefix)) {\n // Next segment after the endpoint prefix is the object name\n const rest = uri.slice(prefix.length);\n const objectName = rest.split('/')[0];\n return `${prefix}${objectName}`;\n }\n }\n\n return uri;\n}\n\n// ============================================\n// Built-in Registrations\n// ============================================\n\n// These will be populated by object modules when they're imported\n// Each object module calls registerObjectType() in its module scope\n\n// Example (done in clas.model.ts):\n// registerObjectType('CLAS', kinds.Class, AdkClass);\n\n// For now, we export the registration function and let objects self-register\n// This avoids circular dependencies\n\n// ============================================\n// Type Mappings (for reference/documentation)\n// ============================================\n\n/**\n * Known ADT type to ADK kind mappings\n *\n * Repository Objects:\n * - DEVC → Package\n * - CLAS → Class\n * - INTF → Interface\n * - FUGR → FunctionGroup\n * - FUNC → FunctionModule\n * - PROG → Program\n * - INCL → Include\n *\n * Data Dictionary:\n * - TABL → Table\n * - STRU → Structure (actually TABL with different category)\n * - DTEL → DataElement\n * - DOMA → Domain\n * - TTYP → TableType\n *\n * Other:\n * - MSAG → MessageClass\n * - ENHS → EnhancementSpot\n *\n * CTS:\n * - (Transport requests/tasks use different identification)\n */\nexport const ADT_TYPE_MAPPINGS = {\n // Repository\n DEVC: kinds.Package,\n CLAS: kinds.Class,\n INTF: kinds.Interface,\n FUGR: kinds.FunctionGroup,\n FUNC: kinds.FunctionModule,\n PROG: kinds.Program,\n INCL: kinds.Include,\n\n // Data Dictionary\n TABL: kinds.Table,\n DTEL: kinds.DataElement,\n DOMA: kinds.Domain,\n TTYP: kinds.TableType,\n\n // Other\n MSAG: kinds.MessageClass,\n ENHS: kinds.EnhancementSpot,\n} as const;\n","/**\n * ADK v2 - Generic Factory\n *\n * Single entry point for creating ADK objects.\n * Resolves ADT types to correct ADK object implementations.\n *\n * Resolution methods:\n * - get(name, adtType) - By name and ADT type (unique identifier)\n * - byKind(kind, name) - By ADK kind (type-safe)\n * - fromXml(xml) - Parse from XML response\n * - create(adtType) - Create new object (deferred)\n */\n\nimport type { AdkContext } from './base/context';\nimport type { AdkObject } from './base/model';\nimport type { AdkKind, AdkObjectForKind } from './base/kinds';\nimport { resolveType, resolveKind, parseAdtType } from './base/registry';\n\n// ============================================\n// XML Parsing Utilities\n// ============================================\n\n/** Pattern to extract adtcore:type from XML */\nconst TYPE_PATTERN = /adtcore:type=\"([^\"]+)\"/;\n\n/** Pattern to extract adtcore:name from XML */\nconst NAME_PATTERN = /adtcore:name=\"([^\"]+)\"/;\n\n/**\n * Extract ADT type and name from XML\n *\n * Relies on adtcore:type and adtcore:name attributes which are\n * the standard identifiers in ADT XML responses.\n *\n * @param xml - XML string from ADT response\n * @returns Extracted type and name, or undefined if not found\n */\nexport function parseXmlIdentity(\n xml: string,\n): { type: string; name: string } | undefined {\n const typeMatch = xml.match(TYPE_PATTERN);\n const nameMatch = xml.match(NAME_PATTERN);\n\n if (typeMatch && nameMatch) {\n return {\n type: typeMatch[1],\n name: nameMatch[1],\n };\n }\n\n return undefined;\n}\n\n// ============================================\n// Generic Object (Fallback)\n// ============================================\n\n/**\n * Generic ADK object for unregistered types\n *\n * Provides core functionality (adtcore attributes, links)\n * without type-specific features.\n */\nexport class AdkGenericObject {\n readonly adtType: string;\n readonly adtMainType: string;\n readonly adtSubType?: string;\n\n protected readonly ctx: AdkContext;\n protected _name: string;\n protected _data?: unknown;\n\n constructor(ctx: AdkContext, name: string, adtType: string) {\n this.ctx = ctx;\n this._name = name;\n\n const parsed = parseAdtType(adtType);\n this.adtType = parsed.full;\n this.adtMainType = parsed.main;\n this.adtSubType = parsed.sub;\n }\n\n get name(): string {\n return this._name;\n }\n get type(): string {\n return this.adtType;\n }\n\n /** Check if data is loaded */\n get isLoaded(): boolean {\n return this._data !== undefined;\n }\n\n /** Get raw data (if loaded) */\n get data(): unknown {\n return this._data;\n }\n\n /** Set data (for manual population) */\n setData(data: unknown): void {\n this._data = data;\n }\n}\n\n// ============================================\n// Factory Interface\n// ============================================\n\n/**\n * ADK Factory - Generic object creation\n */\nexport interface AdkFactory {\n /** Context used by this factory */\n readonly ctx: AdkContext;\n\n /**\n * Get object by name and ADT type\n *\n * Supports both full types (DEVC/K) and main types (DEVC).\n * Returns deferred object - call load() to fetch data.\n *\n * @example\n * const pkg = factory.get('ZPACKAGE', 'DEVC/K');\n * await pkg.load();\n *\n * const cls = factory.get('ZCL_TEST', 'CLAS');\n * await cls.load();\n */\n get(name: string, adtType: string): AdkObject | AdkGenericObject;\n\n /**\n * Get object with initial data (for deserialization)\n *\n * Creates object pre-populated with data - no load() needed.\n * Used when deserializing from files rather than loading from SAP.\n *\n * @example\n * const cls = factory.getWithData({ name: 'ZCL_TEST', description: 'Test' }, 'CLAS');\n * // cls.isLoaded is true, no need to call load()\n */\n getWithData(\n data: Record<string, unknown>,\n adtType: string,\n ): AdkObject | AdkGenericObject;\n\n /**\n * Get object by ADK kind (type-safe)\n *\n * Returns correctly typed object based on kind.\n * TypeScript infers the concrete return type from the kind parameter.\n *\n * @example\n * import { Class, Interface } from '@abapify/adk';\n * const cls = factory.byKind(Class, 'ZCL_TEST'); // → AdkClass\n * const intf = factory.byKind(Interface, 'ZIF_TEST'); // → AdkInterface\n */\n byKind<K extends AdkKind>(kind: K, name: string): AdkObjectForKind<K>;\n\n /**\n * Create object from XML response\n *\n * Parses XML to extract type and name, then constructs\n * the correct object type.\n *\n * @example\n * const xml = await client.fetch('/sap/bc/adt/oo/classes/ZCL_TEST');\n * const cls = factory.fromXml(xml);\n */\n fromXml(xml: string): AdkObject | AdkGenericObject | undefined;\n\n /**\n * Create new object (for creation workflows)\n *\n * Returns deferred object without name - used when\n * creating new objects in SAP.\n */\n create(adtType: string): AdkObject | AdkGenericObject;\n}\n\n// ============================================\n// Factory Implementation\n// ============================================\n\n/**\n * Create ADK factory\n *\n * @param ctx - ADK context with services\n * @returns Factory instance\n */\nexport function createAdkFactory(ctx: AdkContext): AdkFactory {\n return {\n ctx,\n\n get(name: string, adtType: string): AdkObject | AdkGenericObject {\n const entry = resolveType(adtType);\n\n if (entry) {\n return new entry.constructor(ctx, name);\n }\n\n // Fallback to generic object\n return new AdkGenericObject(ctx, name, adtType);\n },\n\n getWithData(\n data: Record<string, unknown>,\n adtType: string,\n ): AdkObject | AdkGenericObject {\n const entry = resolveType(adtType);\n\n if (entry) {\n // Pass data directly to constructor - it will extract name from data.name\n return new entry.constructor(ctx, data);\n }\n\n // Fallback to generic object with name from data\n const obj = new AdkGenericObject(\n ctx,\n (data as { name?: string }).name ?? '',\n adtType,\n );\n obj.setData(data);\n return obj;\n },\n\n byKind<K extends AdkKind>(kind: K, name: string): AdkObjectForKind<K> {\n const entry = resolveKind(kind);\n\n if (!entry) {\n throw new Error(`No constructor registered for kind: ${kind}`);\n }\n\n // Type assertion: registry guarantees correct constructor for kind\n return new entry.constructor(ctx, name) as AdkObjectForKind<K>;\n },\n\n fromXml(xml: string): AdkObject | AdkGenericObject | undefined {\n const identity = parseXmlIdentity(xml);\n\n if (!identity) {\n return undefined;\n }\n\n return this.get(identity.name, identity.type);\n },\n\n create(adtType: string): AdkObject | AdkGenericObject {\n // Create with empty name - will be set during creation workflow\n return this.get('', adtType);\n },\n };\n}\n\n// ============================================\n// Convenience: Create factory from ADT client\n// ============================================\n\n// Factory is the boundary - imports AdtClient directly from adt-client\nimport type { AdtClient } from '@abapify/adt-client';\n\n/**\n * Create ADK factory from ADT client\n *\n * Builds context from client and returns factory.\n * This is the main entry point for most users.\n *\n * @example\n * import { createAdtClient } from '@abapify/adt-client';\n * import { createAdk } from '@abapify/adk';\n *\n * const client = createAdtClient({ ... });\n * const adk = createAdk(client);\n *\n * const cls = adk.get('ZCL_TEST', 'CLAS');\n * await cls.load();\n */\nexport function createAdk(client: AdtClient): AdkFactory {\n // Build context with client reference\n // Objects access client via ctx.client\n const ctx: AdkContext = {\n client,\n };\n\n return createAdkFactory(ctx);\n}\n"],"mappings":"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"}