arc-1 0.9.25 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -12
- package/dist/adt/abapgit.d.ts +19 -6
- package/dist/adt/abapgit.d.ts.map +1 -1
- package/dist/adt/abapgit.js +141 -36
- package/dist/adt/abapgit.js.map +1 -1
- package/dist/adt/authorization-trace.d.ts +23 -0
- package/dist/adt/authorization-trace.d.ts.map +1 -0
- package/dist/adt/authorization-trace.js +196 -0
- package/dist/adt/authorization-trace.js.map +1 -0
- package/dist/adt/client.d.ts +21 -8
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +47 -7
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/config.d.ts +15 -0
- package/dist/adt/config.d.ts.map +1 -1
- package/dist/adt/config.js.map +1 -1
- package/dist/adt/crud.d.ts +7 -2
- package/dist/adt/crud.d.ts.map +1 -1
- package/dist/adt/crud.js +12 -4
- package/dist/adt/crud.js.map +1 -1
- package/dist/adt/ddic-xml.d.ts +27 -17
- package/dist/adt/ddic-xml.d.ts.map +1 -1
- package/dist/adt/ddic-xml.js +45 -34
- package/dist/adt/ddic-xml.js.map +1 -1
- package/dist/adt/devtools.d.ts +13 -0
- package/dist/adt/devtools.d.ts.map +1 -1
- package/dist/adt/devtools.js +120 -50
- package/dist/adt/devtools.js.map +1 -1
- package/dist/adt/diagnostics.d.ts +1 -1
- package/dist/adt/diagnostics.d.ts.map +1 -1
- package/dist/adt/diagnostics.js +1 -0
- package/dist/adt/diagnostics.js.map +1 -1
- package/dist/adt/errors.d.ts +8 -8
- package/dist/adt/errors.d.ts.map +1 -1
- package/dist/adt/errors.js +30 -11
- package/dist/adt/errors.js.map +1 -1
- package/dist/adt/http.d.ts +17 -1
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +102 -19
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/oauth.d.ts +2 -2
- package/dist/adt/oauth.d.ts.map +1 -1
- package/dist/adt/oauth.js +5 -3
- package/dist/adt/oauth.js.map +1 -1
- package/dist/adt/package-hierarchy.d.ts.map +1 -1
- package/dist/adt/package-hierarchy.js.map +1 -1
- package/dist/adt/rap-generate.js.map +1 -1
- package/dist/adt/rap-handlers.js.map +1 -1
- package/dist/adt/rap-preflight.js.map +1 -1
- package/dist/adt/safety.d.ts +13 -13
- package/dist/adt/safety.d.ts.map +1 -1
- package/dist/adt/semaphore.d.ts.map +1 -1
- package/dist/adt/server-driven.d.ts +154 -34
- package/dist/adt/server-driven.d.ts.map +1 -1
- package/dist/adt/server-driven.js +178 -53
- package/dist/adt/server-driven.js.map +1 -1
- package/dist/adt/structure-hierarchy.js.map +1 -1
- package/dist/adt/transport.d.ts +6 -6
- package/dist/adt/transport.d.ts.map +1 -1
- package/dist/adt/transport.js +23 -34
- package/dist/adt/transport.js.map +1 -1
- package/dist/adt/types.d.ts +94 -6
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/version-diff.js.map +1 -1
- package/dist/adt/xml-parser.d.ts +52 -12
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +120 -10
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/aff/validator.js.map +1 -1
- package/dist/authz/policy.d.ts +8 -0
- package/dist/authz/policy.d.ts.map +1 -1
- package/dist/authz/policy.js +24 -0
- package/dist/authz/policy.js.map +1 -1
- package/dist/cache/cache.d.ts +4 -36
- package/dist/cache/cache.d.ts.map +1 -1
- package/dist/cache/cache.js +4 -5
- package/dist/cache/cache.js.map +1 -1
- package/dist/cache/caching-layer.d.ts +6 -22
- package/dist/cache/caching-layer.d.ts.map +1 -1
- package/dist/cache/caching-layer.js +5 -29
- package/dist/cache/caching-layer.js.map +1 -1
- package/dist/cache/inactive-list-cache.d.ts.map +1 -1
- package/dist/cache/memory.d.ts +2 -13
- package/dist/cache/memory.d.ts.map +1 -1
- package/dist/cache/memory.js +1 -70
- package/dist/cache/memory.js.map +1 -1
- package/dist/cache/sqlite.d.ts +3 -10
- package/dist/cache/sqlite.d.ts.map +1 -1
- package/dist/cache/sqlite.js +9 -85
- package/dist/cache/sqlite.js.map +1 -1
- package/dist/cli.js +6 -3
- package/dist/cli.js.map +1 -1
- package/dist/context/compressor.js.map +1 -1
- package/dist/context/grep.js.map +1 -1
- package/dist/context/unit-surgery.d.ts +28 -0
- package/dist/context/unit-surgery.d.ts.map +1 -0
- package/dist/context/unit-surgery.js +150 -0
- package/dist/context/unit-surgery.js.map +1 -0
- package/dist/extract-sap-cookies.js.map +1 -1
- package/dist/handlers/activate.d.ts.map +1 -1
- package/dist/handlers/activate.js +44 -6
- package/dist/handlers/activate.js.map +1 -1
- package/dist/handlers/context.d.ts +1 -1
- package/dist/handlers/context.d.ts.map +1 -1
- package/dist/handlers/context.js +98 -28
- package/dist/handlers/context.js.map +1 -1
- package/dist/handlers/diagnose.d.ts.map +1 -1
- package/dist/handlers/diagnose.js +74 -31
- package/dist/handlers/diagnose.js.map +1 -1
- package/dist/handlers/dispatch.d.ts +12 -1
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +160 -25
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/feature-cache.d.ts +27 -14
- package/dist/handlers/feature-cache.d.ts.map +1 -1
- package/dist/handlers/feature-cache.js +63 -25
- package/dist/handlers/feature-cache.js.map +1 -1
- package/dist/handlers/function-processing.d.ts +61 -0
- package/dist/handlers/function-processing.d.ts.map +1 -0
- package/dist/handlers/function-processing.js +45 -0
- package/dist/handlers/function-processing.js.map +1 -0
- package/dist/handlers/git.d.ts.map +1 -1
- package/dist/handlers/git.js +44 -19
- package/dist/handlers/git.js.map +1 -1
- package/dist/handlers/hyperfocused.d.ts.map +1 -1
- package/dist/handlers/hyperfocused.js +2 -3
- package/dist/handlers/hyperfocused.js.map +1 -1
- package/dist/handlers/lint.d.ts.map +1 -1
- package/dist/handlers/lint.js +7 -7
- package/dist/handlers/lint.js.map +1 -1
- package/dist/handlers/manage.d.ts.map +1 -1
- package/dist/handlers/manage.js +47 -28
- package/dist/handlers/manage.js.map +1 -1
- package/dist/handlers/navigate.d.ts.map +1 -1
- package/dist/handlers/navigate.js +27 -90
- package/dist/handlers/navigate.js.map +1 -1
- package/dist/handlers/object-types.d.ts +2 -0
- package/dist/handlers/object-types.d.ts.map +1 -1
- package/dist/handlers/object-types.js +10 -0
- package/dist/handlers/object-types.js.map +1 -1
- package/dist/handlers/query-errors.d.ts +11 -0
- package/dist/handlers/query-errors.d.ts.map +1 -0
- package/dist/handlers/query-errors.js +216 -0
- package/dist/handlers/query-errors.js.map +1 -0
- package/dist/handlers/query.d.ts.map +1 -1
- package/dist/handlers/query.js +62 -67
- package/dist/handlers/query.js.map +1 -1
- package/dist/handlers/read.d.ts.map +1 -1
- package/dist/handlers/read.js +64 -41
- package/dist/handlers/read.js.map +1 -1
- package/dist/handlers/schemas.d.ts +285 -234
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +126 -32
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/search.d.ts.map +1 -1
- package/dist/handlers/search.js +8 -7
- package/dist/handlers/search.js.map +1 -1
- package/dist/handlers/shared.d.ts +13 -0
- package/dist/handlers/shared.d.ts.map +1 -1
- package/dist/handlers/shared.js +15 -0
- package/dist/handlers/shared.js.map +1 -1
- package/dist/handlers/tool-descriptions.d.ts +4 -0
- package/dist/handlers/tool-descriptions.d.ts.map +1 -0
- package/dist/handlers/tool-descriptions.js +52 -0
- package/dist/handlers/tool-descriptions.js.map +1 -0
- package/dist/handlers/tool-registry.d.ts +20 -6
- package/dist/handlers/tool-registry.d.ts.map +1 -1
- package/dist/handlers/tool-registry.js +18 -0
- package/dist/handlers/tool-registry.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +124 -92
- package/dist/handlers/tools.js.map +1 -1
- package/dist/handlers/transport.d.ts +1 -1
- package/dist/handlers/transport.d.ts.map +1 -1
- package/dist/handlers/transport.js +37 -10
- package/dist/handlers/transport.js.map +1 -1
- package/dist/handlers/where-used.d.ts +25 -0
- package/dist/handlers/where-used.d.ts.map +1 -0
- package/dist/handlers/where-used.js +94 -0
- package/dist/handlers/where-used.js.map +1 -0
- package/dist/handlers/write/class-surgery.d.ts.map +1 -1
- package/dist/handlers/write/class-surgery.js +11 -12
- package/dist/handlers/write/class-surgery.js.map +1 -1
- package/dist/handlers/write/create.d.ts.map +1 -1
- package/dist/handlers/write/create.js +194 -84
- package/dist/handlers/write/create.js.map +1 -1
- package/dist/handlers/write/rap.d.ts.map +1 -1
- package/dist/handlers/write/rap.js +9 -9
- package/dist/handlers/write/rap.js.map +1 -1
- package/dist/handlers/write/unit-surgery.d.ts +5 -0
- package/dist/handlers/write/unit-surgery.d.ts.map +1 -0
- package/dist/handlers/write/unit-surgery.js +47 -0
- package/dist/handlers/write/unit-surgery.js.map +1 -0
- package/dist/handlers/write/update-delete.js +8 -8
- package/dist/handlers/write/update-delete.js.map +1 -1
- package/dist/handlers/write-helpers.d.ts +7 -4
- package/dist/handlers/write-helpers.d.ts.map +1 -1
- package/dist/handlers/write-helpers.js +118 -63
- package/dist/handlers/write-helpers.js.map +1 -1
- package/dist/handlers/write.d.ts.map +1 -1
- package/dist/handlers/write.js +35 -13
- package/dist/handlers/write.js.map +1 -1
- package/dist/lint/config-builder.js.map +1 -1
- package/dist/lint/lint.d.ts.map +1 -1
- package/dist/lint/lint.js +4 -2
- package/dist/lint/lint.js.map +1 -1
- package/dist/probe/catalog.js +1 -1
- package/dist/probe/catalog.js.map +1 -1
- package/dist/public/testing.js.map +1 -1
- package/dist/public/ui/app.js +1 -14
- package/dist/registry/tool-registry.d.ts.map +1 -1
- package/dist/server/audit.d.ts +27 -15
- package/dist/server/audit.d.ts.map +1 -1
- package/dist/server/audit.js.map +1 -1
- package/dist/server/auth-rate-limit.d.ts +18 -9
- package/dist/server/auth-rate-limit.d.ts.map +1 -1
- package/dist/server/auth-rate-limit.js +31 -6
- package/dist/server/auth-rate-limit.js.map +1 -1
- package/dist/server/auth-summary.d.ts +4 -0
- package/dist/server/auth-summary.d.ts.map +1 -0
- package/dist/server/auth-summary.js +67 -0
- package/dist/server/auth-summary.js.map +1 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +110 -7
- package/dist/server/config.js.map +1 -1
- package/dist/server/context.d.ts +12 -0
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js.map +1 -1
- package/dist/server/destination-discovery.d.ts +36 -0
- package/dist/server/destination-discovery.d.ts.map +1 -0
- package/dist/server/destination-discovery.js +130 -0
- package/dist/server/destination-discovery.js.map +1 -0
- package/dist/server/destination-registry.d.ts +111 -0
- package/dist/server/destination-registry.d.ts.map +1 -0
- package/dist/server/destination-registry.js +449 -0
- package/dist/server/destination-registry.js.map +1 -0
- package/dist/server/http.d.ts +43 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +283 -73
- package/dist/server/http.js.map +1 -1
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/logger.js +58 -13
- package/dist/server/logger.js.map +1 -1
- package/dist/server/mcp-rate-limit.d.ts +6 -4
- package/dist/server/mcp-rate-limit.d.ts.map +1 -1
- package/dist/server/mcp-rate-limit.js +6 -4
- package/dist/server/mcp-rate-limit.js.map +1 -1
- package/dist/server/multi-target-basic-auth.d.ts +49 -0
- package/dist/server/multi-target-basic-auth.d.ts.map +1 -0
- package/dist/server/multi-target-basic-auth.js +246 -0
- package/dist/server/multi-target-basic-auth.js.map +1 -0
- package/dist/server/multi-target-catalog.d.ts +33 -0
- package/dist/server/multi-target-catalog.d.ts.map +1 -0
- package/dist/server/multi-target-catalog.js +130 -0
- package/dist/server/multi-target-catalog.js.map +1 -0
- package/dist/server/multi-target-destination-config.d.ts +12 -0
- package/dist/server/multi-target-destination-config.d.ts.map +1 -0
- package/dist/server/multi-target-destination-config.js +37 -0
- package/dist/server/multi-target-destination-config.js.map +1 -0
- package/dist/server/multi-target-destination-runtime.d.ts +20 -0
- package/dist/server/multi-target-destination-runtime.d.ts.map +1 -0
- package/dist/server/multi-target-destination-runtime.js +191 -0
- package/dist/server/multi-target-destination-runtime.js.map +1 -0
- package/dist/server/multi-target-feature-state.d.ts +6 -0
- package/dist/server/multi-target-feature-state.d.ts.map +1 -0
- package/dist/server/multi-target-feature-state.js +41 -0
- package/dist/server/multi-target-feature-state.js.map +1 -0
- package/dist/server/multi-target-identity.d.ts +10 -0
- package/dist/server/multi-target-identity.d.ts.map +1 -0
- package/dist/server/multi-target-identity.js +18 -0
- package/dist/server/multi-target-identity.js.map +1 -0
- package/dist/server/multi-target-runtime.d.ts +27 -0
- package/dist/server/multi-target-runtime.d.ts.map +1 -0
- package/dist/server/multi-target-runtime.js +110 -0
- package/dist/server/multi-target-runtime.js.map +1 -0
- package/dist/server/multi-target-server.d.ts +53 -0
- package/dist/server/multi-target-server.d.ts.map +1 -0
- package/dist/server/multi-target-server.js +434 -0
- package/dist/server/multi-target-server.js.map +1 -0
- package/dist/server/multi-target-shared-auth-state.d.ts +82 -0
- package/dist/server/multi-target-shared-auth-state.d.ts.map +1 -0
- package/dist/server/multi-target-shared-auth-state.js +226 -0
- package/dist/server/multi-target-shared-auth-state.js.map +1 -0
- package/dist/server/multi-target-tools.d.ts +20 -0
- package/dist/server/multi-target-tools.d.ts.map +1 -0
- package/dist/server/multi-target-tools.js +191 -0
- package/dist/server/multi-target-tools.js.map +1 -0
- package/dist/server/oauth-session-recovery.d.ts +22 -0
- package/dist/server/oauth-session-recovery.d.ts.map +1 -0
- package/dist/server/oauth-session-recovery.js +69 -0
- package/dist/server/oauth-session-recovery.js.map +1 -0
- package/dist/server/server.d.ts +47 -25
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +490 -301
- package/dist/server/server.js.map +1 -1
- package/dist/server/sinks/btp-auditlog.d.ts.map +1 -1
- package/dist/server/sinks/btp-auditlog.js +83 -11
- package/dist/server/sinks/btp-auditlog.js.map +1 -1
- package/dist/server/sinks/file.d.ts.map +1 -1
- package/dist/server/sinks/file.js.map +1 -1
- package/dist/server/sinks/stderr.d.ts.map +1 -1
- package/dist/server/sinks/stderr.js.map +1 -1
- package/dist/server/tool-auth.d.ts +10 -0
- package/dist/server/tool-auth.d.ts.map +1 -0
- package/dist/server/tool-auth.js +75 -0
- package/dist/server/tool-auth.js.map +1 -0
- package/dist/server/trace-context.d.ts +51 -0
- package/dist/server/trace-context.d.ts.map +1 -0
- package/dist/server/trace-context.js +100 -0
- package/dist/server/trace-context.js.map +1 -0
- package/dist/server/types.d.ts +28 -7
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +5 -2
- package/dist/server/types.js.map +1 -1
- package/dist/server/ui-log-buffer.d.ts.map +1 -1
- package/dist/server/ui-log-buffer.js.map +1 -1
- package/dist/server/ui-state.d.ts +0 -2
- package/dist/server/ui-state.d.ts.map +1 -1
- package/dist/server/ui-state.js +2 -6
- package/dist/server/ui-state.js.map +1 -1
- package/dist/server/ui.d.ts.map +1 -1
- package/dist/server/ui.js +8 -9
- package/dist/server/ui.js.map +1 -1
- package/package.json +21 -18
- package/dist/cache/warmup.d.ts +0 -41
- package/dist/cache/warmup.d.ts.map +0 -1
- package/dist/cache/warmup.js +0 -337
- package/dist/cache/warmup.js.map +0 -1
- package/dist/server/elicit.d.ts +0 -43
- package/dist/server/elicit.d.ts.map +0 -1
- package/dist/server/elicit.js +0 -183
- package/dist/server/elicit.js.map +0 -1
|
@@ -13,56 +13,149 @@ export interface SdoRegistryEntry {
|
|
|
13
13
|
*/
|
|
14
14
|
createType: string;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Metadata content-type for BOTH the metadata GET (Accept) and the create POST (Content-Type).
|
|
17
|
+
* Most types use `application/vnd.sap.adt.blues.vN+xml` (EVTO is v2, the rest v1); DTDC uses its
|
|
18
|
+
* own `application/vnd.sap.adt.ddic.dtdc.v1+xml`. Matched by `discoveryMarker` in the gate.
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
metadataContentType: string;
|
|
21
|
+
/**
|
|
22
|
+
* Local name of the metadata root element AFTER the parser strips namespace prefixes
|
|
23
|
+
* (`removeNSPrefix: true`): `blueSource` for the blue family, `dtdcSource` for DTDC. Drives the
|
|
24
|
+
* parse path (`parseServerDrivenMetadata`).
|
|
25
|
+
*/
|
|
26
|
+
metadataRootLocalName: string;
|
|
27
|
+
/**
|
|
28
|
+
* Qualified root element name + its namespace URI for the create body. Blue family:
|
|
29
|
+
* `blue:blueSource` / `http://www.sap.com/wbobj/blue`. DTDC: `dtdc:dtdcSource` /
|
|
30
|
+
* `http://www.sap.com/adt/ddic/dtdcsources`. Drives the build path.
|
|
31
|
+
*/
|
|
32
|
+
metadataRootQName: string;
|
|
33
|
+
metadataNamespace: string;
|
|
34
|
+
/**
|
|
35
|
+
* Substring the discovery gate matches against the collection's advertised Accept type: `blues`
|
|
36
|
+
* for the blue family, `dtdc` for DTDC. Version-agnostic (matches v1/v2).
|
|
37
|
+
*/
|
|
38
|
+
discoveryMarker: string;
|
|
39
|
+
/**
|
|
40
|
+
* Source flavor — drives BOTH the client-side validation and the PUT Content-Type. NOT uniform:
|
|
41
|
+
* the AFF-JSON types 415 on text/plain, and the DDL-text types (DTSC, DSFD, DTDC) 415 on
|
|
42
|
+
* application/json. Live-verified per type on 816.
|
|
43
|
+
*/
|
|
44
|
+
sourceFormat: SdoSourceFormat;
|
|
21
45
|
}
|
|
46
|
+
/** AFF JSON body vs plain DDL text. Required per entry — a wrong guess is a hard 415 from SAP. */
|
|
47
|
+
export type SdoSourceFormat = 'json' | 'text';
|
|
48
|
+
/** Content-Type for the source PUT, derived from the type's declared source flavor. */
|
|
49
|
+
export declare function serverDrivenSourceContentType(code: string): string;
|
|
50
|
+
/** Declared source flavor for a registered type (drives the client-side JSON parse gate). */
|
|
51
|
+
export declare function serverDrivenSourceFormat(code: string): SdoSourceFormat;
|
|
22
52
|
/**
|
|
23
53
|
* The registered server-driven type codes, in registry (= LLM tool-surface) order. The SAPRead/
|
|
24
54
|
* SAPWrite rows in src/handlers/tool-registry.ts derive from this tuple, so registering a type
|
|
25
|
-
* here is the ONLY step needed to expose it — `btp: true` by construction (
|
|
26
|
-
*
|
|
55
|
+
* here is the ONLY step needed to expose it — `btp: true` by construction (runtime availability is
|
|
56
|
+
* discovery-gated per system, so a type absent on a release degrades cleanly).
|
|
27
57
|
*/
|
|
28
|
-
export declare const SDO_TYPES: readonly [
|
|
29
|
-
/** Curated registry of high-value
|
|
58
|
+
export declare const SDO_TYPES: readonly ['DESD', 'DTSC', 'CSNM', 'EVTB', 'EVTO', 'COTA', 'DSFD', 'DTDC', 'UIAD'];
|
|
59
|
+
/** Curated registry of high-value server-driven object types — keys are exactly SDO_TYPES. */
|
|
30
60
|
export declare const SDO_REGISTRY: {
|
|
31
61
|
DESD: {
|
|
62
|
+
metadataRootLocalName: 'blueSource';
|
|
63
|
+
metadataRootQName: 'blue:blueSource';
|
|
64
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
65
|
+
discoveryMarker: 'blues';
|
|
32
66
|
href: string;
|
|
33
67
|
label: string;
|
|
34
68
|
createType: string;
|
|
35
|
-
|
|
69
|
+
metadataContentType: string;
|
|
70
|
+
sourceFormat: "json";
|
|
36
71
|
};
|
|
37
72
|
DTSC: {
|
|
73
|
+
metadataRootLocalName: 'blueSource';
|
|
74
|
+
metadataRootQName: 'blue:blueSource';
|
|
75
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
76
|
+
discoveryMarker: 'blues';
|
|
38
77
|
href: string;
|
|
39
78
|
label: string;
|
|
40
79
|
createType: string;
|
|
41
|
-
|
|
80
|
+
metadataContentType: string;
|
|
81
|
+
sourceFormat: "text";
|
|
42
82
|
};
|
|
43
83
|
CSNM: {
|
|
84
|
+
metadataRootLocalName: 'blueSource';
|
|
85
|
+
metadataRootQName: 'blue:blueSource';
|
|
86
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
87
|
+
discoveryMarker: 'blues';
|
|
44
88
|
href: string;
|
|
45
89
|
label: string;
|
|
46
90
|
createType: string;
|
|
47
|
-
|
|
91
|
+
metadataContentType: string;
|
|
92
|
+
sourceFormat: "json";
|
|
48
93
|
};
|
|
49
94
|
EVTB: {
|
|
95
|
+
metadataRootLocalName: 'blueSource';
|
|
96
|
+
metadataRootQName: 'blue:blueSource';
|
|
97
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
98
|
+
discoveryMarker: 'blues';
|
|
50
99
|
href: string;
|
|
51
100
|
label: string;
|
|
52
101
|
createType: string;
|
|
53
|
-
|
|
102
|
+
metadataContentType: string;
|
|
103
|
+
sourceFormat: "json";
|
|
54
104
|
};
|
|
55
105
|
EVTO: {
|
|
106
|
+
metadataRootLocalName: 'blueSource';
|
|
107
|
+
metadataRootQName: 'blue:blueSource';
|
|
108
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
109
|
+
discoveryMarker: 'blues';
|
|
56
110
|
href: string;
|
|
57
111
|
label: string;
|
|
58
112
|
createType: string;
|
|
59
|
-
|
|
113
|
+
metadataContentType: string;
|
|
114
|
+
sourceFormat: "json";
|
|
60
115
|
};
|
|
61
116
|
COTA: {
|
|
117
|
+
metadataRootLocalName: 'blueSource';
|
|
118
|
+
metadataRootQName: 'blue:blueSource';
|
|
119
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
120
|
+
discoveryMarker: 'blues';
|
|
121
|
+
href: string;
|
|
122
|
+
label: string;
|
|
123
|
+
createType: string;
|
|
124
|
+
metadataContentType: string;
|
|
125
|
+
sourceFormat: "json";
|
|
126
|
+
};
|
|
127
|
+
DSFD: {
|
|
128
|
+
metadataRootLocalName: 'blueSource';
|
|
129
|
+
metadataRootQName: 'blue:blueSource';
|
|
130
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
131
|
+
discoveryMarker: 'blues';
|
|
62
132
|
href: string;
|
|
63
133
|
label: string;
|
|
64
134
|
createType: string;
|
|
65
|
-
|
|
135
|
+
metadataContentType: string;
|
|
136
|
+
sourceFormat: "text";
|
|
137
|
+
};
|
|
138
|
+
DTDC: {
|
|
139
|
+
href: string;
|
|
140
|
+
label: string;
|
|
141
|
+
createType: string;
|
|
142
|
+
metadataContentType: string;
|
|
143
|
+
metadataRootLocalName: string;
|
|
144
|
+
metadataRootQName: string;
|
|
145
|
+
metadataNamespace: string;
|
|
146
|
+
discoveryMarker: string;
|
|
147
|
+
sourceFormat: "text";
|
|
148
|
+
};
|
|
149
|
+
UIAD: {
|
|
150
|
+
metadataRootLocalName: 'blueSource';
|
|
151
|
+
metadataRootQName: 'blue:blueSource';
|
|
152
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue';
|
|
153
|
+
discoveryMarker: 'blues';
|
|
154
|
+
href: string;
|
|
155
|
+
label: string;
|
|
156
|
+
createType: string;
|
|
157
|
+
metadataContentType: string;
|
|
158
|
+
sourceFormat: "json";
|
|
66
159
|
};
|
|
67
160
|
};
|
|
68
161
|
/** True when `code` is one of the registered server-driven object types. */
|
|
@@ -70,36 +163,61 @@ export declare function isServerDrivenObjectType(code: string): boolean;
|
|
|
70
163
|
/** ADT object URL for a server-driven object: collection href + url-encoded name. */
|
|
71
164
|
export declare function serverDrivenObjectUrl(code: string, name: string): string;
|
|
72
165
|
/**
|
|
73
|
-
* The
|
|
74
|
-
* where the
|
|
75
|
-
* (EVTO → v2). Throws
|
|
166
|
+
* The metadata content-type for a type — used as the metadata GET Accept (incl. package resolution,
|
|
167
|
+
* where the metadata root's packageRef only renders under this Accept) and the create POST
|
|
168
|
+
* Content-Type. Per type (EVTO → blues v2, DTDC → its own dtdc type). Throws for an unknown code.
|
|
76
169
|
*/
|
|
77
|
-
export declare function
|
|
170
|
+
export declare function serverDrivenMetadataContentType(code: string): string;
|
|
78
171
|
/**
|
|
79
|
-
* Capability gate — true iff ADT discovery advertises the type's collection with
|
|
80
|
-
*
|
|
81
|
-
* when discovery has not been loaded (caller may attempt
|
|
82
|
-
* supportsExplicitTransportTarget() / supportsCdsTestCases().
|
|
172
|
+
* Capability gate — true iff ADT discovery advertises the type's collection with its per-type
|
|
173
|
+
* metadata accept (the blue family's `blues`, DTDC's `dtdc`; present on the releases that ship the
|
|
174
|
+
* type, absent otherwise). Returns undefined when discovery has not been loaded (caller may attempt
|
|
175
|
+
* and let a 404 surface). Mirrors supportsExplicitTransportTarget() / supportsCdsTestCases().
|
|
176
|
+
* Version-agnostic: `discoveryMarker` is a substring, so it matches v1 and v2.
|
|
83
177
|
*/
|
|
84
178
|
export declare function supportsServerDrivenObject(http: AdtHttpClient, code: string): boolean | undefined;
|
|
85
179
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
180
|
+
* Resolve SDO availability, fetching ADT discovery when it has not been loaded yet.
|
|
181
|
+
*
|
|
182
|
+
* The sync check returns `undefined` on a cold discovery map — which the CLI always is
|
|
183
|
+
* (`handleToolCall` runs without the startup probe). Callers that treated only an explicit `false`
|
|
184
|
+
* as "unavailable" therefore fell through to the request and surfaced a raw 404 with a "verify the
|
|
185
|
+
* name exists" hint, when in truth the object type does not exist on that release.
|
|
186
|
+
*
|
|
187
|
+
* `safety` is REQUIRED: fetchDiscoveryDocument issues an unguarded GET, and this runs inside a tool
|
|
188
|
+
* call, so it must pass the safety ceiling. Read is always permitted at that layer today, so this is
|
|
189
|
+
* a convention guard (and a real gate if a Read restriction is ever added), not an active control.
|
|
190
|
+
* The fetched map is used locally and deliberately NOT stored: server.ts re-injects the cached map
|
|
191
|
+
* before every tool call, and writing to the shared client would leak one user's capability view
|
|
192
|
+
* under the non-strict principal-propagation fallback.
|
|
193
|
+
*
|
|
194
|
+
* Still-unknown resolves to `true` (proceed): `hasDiscoveryData()` cannot tell "discovery
|
|
195
|
+
* unreachable" from "discovery empty", and failing closed would break every SDO read on a system
|
|
196
|
+
* where /sap/bc/adt/discovery is 403'd. This gate only improves the error message — the real
|
|
197
|
+
* controls are checkOperation and the package allowlist.
|
|
198
|
+
*/
|
|
199
|
+
export declare function ensureServerDrivenSupport(http: AdtHttpClient, safety: SafetyConfig, code: string): Promise<boolean>;
|
|
200
|
+
/** Shared "this release does not have this type" message for the three SDO entry points. */
|
|
201
|
+
export declare function serverDrivenUnavailableMessage(tool: string, code: string): string;
|
|
202
|
+
/**
|
|
203
|
+
* Read a server-driven object: its metadata (blue:blueSource or dtdc:dtdcSource) + source (AFF JSON
|
|
204
|
+
* or DDL text). The source is JSON-parsed when possible (raw text otherwise). Throws AdtApiError 404
|
|
205
|
+
* for a nonexistent object. Gate availability with supportsServerDrivenObject() on unknown systems.
|
|
89
206
|
*/
|
|
90
207
|
export declare function getServerDrivenObject(http: AdtHttpClient, safety: SafetyConfig, code: string, name: string): Promise<ServerDrivenObjectResult>;
|
|
91
208
|
/**
|
|
92
|
-
* Build the minimal
|
|
93
|
-
* verified `createType` for `adtcore:type`
|
|
209
|
+
* Build the minimal metadata create body for a server-driven object — the per-type root element
|
|
210
|
+
* (blue:blueSource or dtdc:dtdcSource) with the verified `createType` for `adtcore:type`
|
|
211
|
+
* (e.g. DESD/TYP, EVTB/EVB, DTDC/DF) + the package ref.
|
|
94
212
|
*
|
|
95
213
|
* NOTE — no `adtcore:masterLanguage`: live-verified on a4h-2025 (816) that ADT *silently ignores*
|
|
96
214
|
* that attribute for these objects (create with masterLanguage="DE" → object still read back as the
|
|
97
215
|
* session language). The object's master language comes from the `sap-language` request param (the
|
|
98
216
|
* session = `config.language` / SAP_LANGUAGE), as with other source-based objects (cf. #343). Emitting
|
|
99
|
-
* it would be an ADT-ignored attribute
|
|
100
|
-
*
|
|
217
|
+
* it would be an ADT-ignored attribute — so the body here is exactly the form proven to create every
|
|
218
|
+
* registered type.
|
|
101
219
|
*/
|
|
102
|
-
export declare function
|
|
220
|
+
export declare function buildServerDrivenMetadataXml(code: string, name: string, pkg: string, description: string): string;
|
|
103
221
|
/** Options shared by the SDO write operations. */
|
|
104
222
|
export interface ServerDrivenWriteOptions {
|
|
105
223
|
transport?: string;
|
|
@@ -115,11 +233,13 @@ export declare function createServerDrivenObject(http: AdtHttpClient, safety: Sa
|
|
|
115
233
|
transport?: string;
|
|
116
234
|
}): Promise<string>;
|
|
117
235
|
/**
|
|
118
|
-
* Write the
|
|
119
|
-
*
|
|
120
|
-
*
|
|
236
|
+
* Write the source of a server-driven object: lock → PUT …/source/main → unlock (guaranteed via
|
|
237
|
+
* try-finally). The Content-Type comes from the type's declared sourceFormat — AFF-JSON types take
|
|
238
|
+
* application/json, DDL-text types (DTSC, DSFD) take text/plain; sending the wrong one is a 415.
|
|
239
|
+
* Auto-propagates the lock's corrNr when no explicit transport is supplied (same contract as
|
|
240
|
+
* crud.ts safeUpdateSource).
|
|
121
241
|
*/
|
|
122
|
-
export declare function updateServerDrivenObjectSource(http: AdtHttpClient, safety: SafetyConfig, code: string, name: string,
|
|
242
|
+
export declare function updateServerDrivenObjectSource(http: AdtHttpClient, safety: SafetyConfig, code: string, name: string, source: string, opts?: ServerDrivenWriteOptions): Promise<void>;
|
|
123
243
|
/**
|
|
124
244
|
* Delete a server-driven object: lock → http.delete(…?lockHandle=…) → best-effort unlock.
|
|
125
245
|
* The unlock is swallowed on failure (the object is already gone after the delete).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-driven.d.ts","sourceRoot":"","sources":["../../src/adt/server-driven.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-driven.d.ts","sourceRoot":"","sources":["../../src/adt/server-driven.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,77 +1,156 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generic "server-driven object" (SDO) read/write path
|
|
2
|
+
* Generic "server-driven object" (SDO) read/write path. Most SDO types need ABAP Platform 2025
|
|
3
|
+
* (SAP_BASIS 8.16+), but some (DTDC, DSFD, EVTB) also ship on S/4HANA 2023 (758) — availability is
|
|
4
|
+
* discovery-gated per type, never a hardcoded release.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
* - metadata: GET …/{name}
|
|
6
|
-
* - content : GET …/{name}/source/main → AFF JSON
|
|
6
|
+
* These repository object types share ONE AFF generic-object contract:
|
|
7
|
+
* - metadata: GET …/{name} (Accept = per-type metadataContentType) → <blue:blueSource> or <dtdc:dtdcSource>
|
|
8
|
+
* - content : GET …/{name}/source/main → AFF JSON *or* DDL text
|
|
7
9
|
* Rather than per-type plumbing, this module exposes a curated registry of high-value types
|
|
8
10
|
* and ONE generic engine, discovery-gated so pre-8.16 systems degrade cleanly.
|
|
9
11
|
*
|
|
10
12
|
* WRITE (create/update-source/delete) is supported and reuses the verified machinery:
|
|
11
|
-
* - CREATE = POST <collection-href> (Content-Type = the type's
|
|
12
|
-
*
|
|
13
|
-
* - SOURCE = lock (crud.ts) → PUT <url>/source/main?lockHandle=…
|
|
14
|
-
* the AFF
|
|
13
|
+
* - CREATE = POST <collection-href> (Content-Type = the type's metadataContentType) with a minimal
|
|
14
|
+
* metadata body (blue:blueSource / dtdc:dtdcSource; adtcore:type/name/description + packageRef) → 201.
|
|
15
|
+
* - SOURCE = lock (crud.ts) → PUT <url>/source/main?lockHandle=… → unlock. The Content-Type is
|
|
16
|
+
* per-type (registry `sourceFormat`): application/json for the AFF-JSON types,
|
|
17
|
+
* text/plain for the DDL-text ones (DTSC, DSFD, DTDC). The wrong one is a hard 415.
|
|
15
18
|
* - DELETE = lock → http.delete(<url>?lockHandle=…) → unlock.
|
|
16
19
|
* - ACTIVATE is the generic devtools activate() against the object URL (callers use SAPActivate).
|
|
17
20
|
* Create leaves the object inactive — callers follow with SAPActivate (never auto-activated).
|
|
18
21
|
*
|
|
19
|
-
* The create `adtcore:type` subtype is NOT uniformly "<code>/TYP" (EVTB
|
|
20
|
-
*
|
|
21
|
-
* verified live on
|
|
22
|
+
* The create `adtcore:type` subtype is NOT uniformly "<code>/TYP" (EVTB=EVTB/EVB, DTDC=DTDC/DF) and
|
|
23
|
+
* the metadata content-type varies (blues v1, EVTO=blues v2, DTDC=ddic.dtdc.v1) — all stored per
|
|
24
|
+
* registry entry, verified live: the blue family on 816, DTDC create→activate on 758 + 816.
|
|
22
25
|
*/
|
|
23
26
|
import { lockObject, unlockObject } from './crud.js';
|
|
27
|
+
import { fetchDiscoveryDocument, resolveAcceptType } from './discovery.js';
|
|
24
28
|
import { AdtApiError } from './errors.js';
|
|
25
29
|
import { checkOperation, OperationType } from './safety.js';
|
|
26
|
-
import { escapeXmlAttr,
|
|
30
|
+
import { escapeXmlAttr, parseServerDrivenMetadata } from './xml-parser.js';
|
|
31
|
+
/**
|
|
32
|
+
* Shared metadata-format fields for the "blue" family (DESD/DTSC/CSNM/EVTB/EVTO/COTA/DSFD) — every
|
|
33
|
+
* blue type has the identical root element/namespace/discovery marker; only its content-type version
|
|
34
|
+
* (v1/v2) and source flavor differ. Spread into each blue entry so the shape can't drift.
|
|
35
|
+
*/
|
|
36
|
+
const BLUE_METADATA = {
|
|
37
|
+
metadataRootLocalName: 'blueSource',
|
|
38
|
+
metadataRootQName: 'blue:blueSource',
|
|
39
|
+
metadataNamespace: 'http://www.sap.com/wbobj/blue',
|
|
40
|
+
discoveryMarker: 'blues',
|
|
41
|
+
};
|
|
27
42
|
const BLUES_V1 = 'application/vnd.sap.adt.blues.v1+xml';
|
|
28
43
|
const BLUES_V2 = 'application/vnd.sap.adt.blues.v2+xml';
|
|
29
|
-
/**
|
|
30
|
-
|
|
44
|
+
/** Content-Type for the source PUT, derived from the type's declared source flavor. */
|
|
45
|
+
export function serverDrivenSourceContentType(code) {
|
|
46
|
+
const format = sdoEntry(code).sourceFormat;
|
|
47
|
+
switch (format) {
|
|
48
|
+
case 'json':
|
|
49
|
+
return 'application/json';
|
|
50
|
+
case 'text':
|
|
51
|
+
return 'text/plain';
|
|
52
|
+
default: {
|
|
53
|
+
// A new SdoSourceFormat must map to a content type here — falling through would only
|
|
54
|
+
// surface as a live 415. Exhaustiveness is a compile error, not a runtime surprise.
|
|
55
|
+
const unhandled = format;
|
|
56
|
+
throw new AdtApiError(`Unhandled server-driven source format "${String(unhandled)}".`, 500, '');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Declared source flavor for a registered type (drives the client-side JSON parse gate). */
|
|
61
|
+
export function serverDrivenSourceFormat(code) {
|
|
62
|
+
return sdoEntry(code).sourceFormat;
|
|
63
|
+
}
|
|
31
64
|
/**
|
|
32
65
|
* The registered server-driven type codes, in registry (= LLM tool-surface) order. The SAPRead/
|
|
33
66
|
* SAPWrite rows in src/handlers/tool-registry.ts derive from this tuple, so registering a type
|
|
34
|
-
* here is the ONLY step needed to expose it — `btp: true` by construction (
|
|
35
|
-
*
|
|
67
|
+
* here is the ONLY step needed to expose it — `btp: true` by construction (runtime availability is
|
|
68
|
+
* discovery-gated per system, so a type absent on a release degrades cleanly).
|
|
36
69
|
*/
|
|
37
|
-
export const SDO_TYPES = ['DESD', 'DTSC', 'CSNM', 'EVTB', 'EVTO', 'COTA'];
|
|
38
|
-
/** Curated registry of high-value
|
|
70
|
+
export const SDO_TYPES = ['DESD', 'DTSC', 'CSNM', 'EVTB', 'EVTO', 'COTA', 'DSFD', 'DTDC', 'UIAD'];
|
|
71
|
+
/** Curated registry of high-value server-driven object types — keys are exactly SDO_TYPES. */
|
|
39
72
|
export const SDO_REGISTRY = {
|
|
40
73
|
DESD: {
|
|
41
74
|
href: '/sap/bc/adt/ddic/desd',
|
|
42
75
|
label: 'CDS Logical External Schema',
|
|
43
76
|
createType: 'DESD/TYP',
|
|
44
|
-
|
|
77
|
+
metadataContentType: BLUES_V1,
|
|
78
|
+
...BLUE_METADATA,
|
|
79
|
+
sourceFormat: 'json',
|
|
45
80
|
},
|
|
46
81
|
DTSC: {
|
|
47
82
|
href: '/sap/bc/adt/ddic/dtsc/sources',
|
|
48
83
|
label: 'CDS Static Cache (table-entity buffer)',
|
|
49
84
|
createType: 'DTSC/TYP',
|
|
50
|
-
|
|
85
|
+
metadataContentType: BLUES_V1,
|
|
86
|
+
...BLUE_METADATA,
|
|
87
|
+
sourceFormat: 'text',
|
|
51
88
|
},
|
|
52
89
|
CSNM: {
|
|
53
90
|
href: '/sap/bc/adt/csn/csnm',
|
|
54
91
|
label: 'Core Schema Notation Model (CSN)',
|
|
55
92
|
createType: 'CSNM/TYP',
|
|
56
|
-
|
|
93
|
+
metadataContentType: BLUES_V1,
|
|
94
|
+
...BLUE_METADATA,
|
|
95
|
+
sourceFormat: 'json',
|
|
57
96
|
},
|
|
58
97
|
EVTB: {
|
|
59
98
|
href: '/sap/bc/adt/businessservices/evtbevb',
|
|
60
99
|
label: 'RAP Event Binding',
|
|
61
100
|
createType: 'EVTB/EVB',
|
|
62
|
-
|
|
101
|
+
metadataContentType: BLUES_V1,
|
|
102
|
+
...BLUE_METADATA,
|
|
103
|
+
sourceFormat: 'json',
|
|
63
104
|
},
|
|
64
105
|
EVTO: {
|
|
65
106
|
href: '/sap/bc/adt/businessservices/evtoevo',
|
|
66
107
|
label: 'RAP Event Object',
|
|
67
108
|
createType: 'EVTO/EVO',
|
|
68
|
-
|
|
109
|
+
metadataContentType: BLUES_V2,
|
|
110
|
+
...BLUE_METADATA,
|
|
111
|
+
sourceFormat: 'json',
|
|
69
112
|
},
|
|
70
113
|
COTA: {
|
|
71
114
|
href: '/sap/bc/adt/conn/commtargets',
|
|
72
115
|
label: 'Communication Target',
|
|
73
116
|
createType: 'COTA/TYP',
|
|
74
|
-
|
|
117
|
+
metadataContentType: BLUES_V1,
|
|
118
|
+
...BLUE_METADATA,
|
|
119
|
+
sourceFormat: 'json',
|
|
120
|
+
},
|
|
121
|
+
DSFD: {
|
|
122
|
+
href: '/sap/bc/adt/ddic/dsfd/sources',
|
|
123
|
+
label: 'CDS Scalar Function Definition',
|
|
124
|
+
createType: 'DSFD/SCF',
|
|
125
|
+
metadataContentType: BLUES_V1,
|
|
126
|
+
...BLUE_METADATA,
|
|
127
|
+
sourceFormat: 'text',
|
|
128
|
+
},
|
|
129
|
+
// DTDC is the first NON-blue server-driven type: its own metadata format (<dtdc:dtdcSource> +
|
|
130
|
+
// application/vnd.sap.adt.ddic.dtdc.v1+xml), DDL-text source. Available on 758 + 816.
|
|
131
|
+
DTDC: {
|
|
132
|
+
href: '/sap/bc/adt/ddic/dtdc/sources',
|
|
133
|
+
label: 'CDS Dynamic Cache',
|
|
134
|
+
createType: 'DTDC/DF',
|
|
135
|
+
metadataContentType: 'application/vnd.sap.adt.ddic.dtdc.v1+xml',
|
|
136
|
+
metadataRootLocalName: 'dtdcSource',
|
|
137
|
+
metadataRootQName: 'dtdc:dtdcSource',
|
|
138
|
+
metadataNamespace: 'http://www.sap.com/adt/ddic/dtdcsources',
|
|
139
|
+
discoveryMarker: 'dtdc',
|
|
140
|
+
sourceFormat: 'text',
|
|
141
|
+
},
|
|
142
|
+
// Launchpad content: the LADI replaces the deprecated tile/target-mapping model and is the
|
|
143
|
+
// developer-owned unit on ABAP Cloud. blues.v2 (v1 -> 406, verified on 816).
|
|
144
|
+
// Read-only in practice on on-prem: create -> 400 'Editing of LADIs with ALV "Standard" not
|
|
145
|
+
// allowed in workbench tools' (LADI edits need the ABAP Cloud language version). SAP's refusal is
|
|
146
|
+
// clear and also covers read-only manifest-generated items, so no client-side guard.
|
|
147
|
+
UIAD: {
|
|
148
|
+
href: '/sap/bc/adt/fiori/uiad',
|
|
149
|
+
label: 'Launchpad App Descriptor Item (LADI)',
|
|
150
|
+
createType: 'UIAD/TYP',
|
|
151
|
+
metadataContentType: BLUES_V2,
|
|
152
|
+
...BLUE_METADATA,
|
|
153
|
+
sourceFormat: 'json',
|
|
75
154
|
},
|
|
76
155
|
};
|
|
77
156
|
// String-indexed view of the registry for the unknown-code lookups below (the satisfies-typed
|
|
@@ -93,18 +172,19 @@ export function serverDrivenObjectUrl(code, name) {
|
|
|
93
172
|
return `${sdoEntry(code).href}/${encodeURIComponent(name)}`;
|
|
94
173
|
}
|
|
95
174
|
/**
|
|
96
|
-
* The
|
|
97
|
-
* where the
|
|
98
|
-
* (EVTO → v2). Throws
|
|
175
|
+
* The metadata content-type for a type — used as the metadata GET Accept (incl. package resolution,
|
|
176
|
+
* where the metadata root's packageRef only renders under this Accept) and the create POST
|
|
177
|
+
* Content-Type. Per type (EVTO → blues v2, DTDC → its own dtdc type). Throws for an unknown code.
|
|
99
178
|
*/
|
|
100
|
-
export function
|
|
101
|
-
return sdoEntry(code).
|
|
179
|
+
export function serverDrivenMetadataContentType(code) {
|
|
180
|
+
return sdoEntry(code).metadataContentType;
|
|
102
181
|
}
|
|
103
182
|
/**
|
|
104
|
-
* Capability gate — true iff ADT discovery advertises the type's collection with
|
|
105
|
-
*
|
|
106
|
-
* when discovery has not been loaded (caller may attempt
|
|
107
|
-
* supportsExplicitTransportTarget() / supportsCdsTestCases().
|
|
183
|
+
* Capability gate — true iff ADT discovery advertises the type's collection with its per-type
|
|
184
|
+
* metadata accept (the blue family's `blues`, DTDC's `dtdc`; present on the releases that ship the
|
|
185
|
+
* type, absent otherwise). Returns undefined when discovery has not been loaded (caller may attempt
|
|
186
|
+
* and let a 404 surface). Mirrors supportsExplicitTransportTarget() / supportsCdsTestCases().
|
|
187
|
+
* Version-agnostic: `discoveryMarker` is a substring, so it matches v1 and v2.
|
|
108
188
|
*/
|
|
109
189
|
export function supportsServerDrivenObject(http, code) {
|
|
110
190
|
const entry = REGISTRY_BY_CODE[code];
|
|
@@ -112,19 +192,60 @@ export function supportsServerDrivenObject(http, code) {
|
|
|
112
192
|
return false;
|
|
113
193
|
if (!http.hasDiscoveryData())
|
|
114
194
|
return undefined;
|
|
115
|
-
return (http.discoveryAcceptFor(entry.href) ?? '').includes(
|
|
195
|
+
return (http.discoveryAcceptFor(entry.href) ?? '').includes(entry.discoveryMarker);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Resolve SDO availability, fetching ADT discovery when it has not been loaded yet.
|
|
199
|
+
*
|
|
200
|
+
* The sync check returns `undefined` on a cold discovery map — which the CLI always is
|
|
201
|
+
* (`handleToolCall` runs without the startup probe). Callers that treated only an explicit `false`
|
|
202
|
+
* as "unavailable" therefore fell through to the request and surfaced a raw 404 with a "verify the
|
|
203
|
+
* name exists" hint, when in truth the object type does not exist on that release.
|
|
204
|
+
*
|
|
205
|
+
* `safety` is REQUIRED: fetchDiscoveryDocument issues an unguarded GET, and this runs inside a tool
|
|
206
|
+
* call, so it must pass the safety ceiling. Read is always permitted at that layer today, so this is
|
|
207
|
+
* a convention guard (and a real gate if a Read restriction is ever added), not an active control.
|
|
208
|
+
* The fetched map is used locally and deliberately NOT stored: server.ts re-injects the cached map
|
|
209
|
+
* before every tool call, and writing to the shared client would leak one user's capability view
|
|
210
|
+
* under the non-strict principal-propagation fallback.
|
|
211
|
+
*
|
|
212
|
+
* Still-unknown resolves to `true` (proceed): `hasDiscoveryData()` cannot tell "discovery
|
|
213
|
+
* unreachable" from "discovery empty", and failing closed would break every SDO read on a system
|
|
214
|
+
* where /sap/bc/adt/discovery is 403'd. This gate only improves the error message — the real
|
|
215
|
+
* controls are checkOperation and the package allowlist.
|
|
216
|
+
*/
|
|
217
|
+
export async function ensureServerDrivenSupport(http, safety, code) {
|
|
218
|
+
const known = supportsServerDrivenObject(http, code);
|
|
219
|
+
if (known !== undefined)
|
|
220
|
+
return known;
|
|
221
|
+
const entry = REGISTRY_BY_CODE[code];
|
|
222
|
+
if (!entry)
|
|
223
|
+
return false;
|
|
224
|
+
checkOperation(safety, OperationType.Read, 'FetchDiscovery');
|
|
225
|
+
const { map } = await fetchDiscoveryDocument(http); // never throws
|
|
226
|
+
// Empty map = discovery unreachable, NOT "collection absent" — those must not collapse together,
|
|
227
|
+
// or a 403'd discovery would block every SDO read. A populated map lacking the href IS unsupported.
|
|
228
|
+
if (map.size === 0)
|
|
229
|
+
return true;
|
|
230
|
+
return (resolveAcceptType(map, entry.href) ?? '').includes(entry.discoveryMarker);
|
|
231
|
+
}
|
|
232
|
+
/** Shared "this release does not have this type" message for the three SDO entry points. */
|
|
233
|
+
export function serverDrivenUnavailableMessage(tool, code) {
|
|
234
|
+
return (`${tool} type=${code} (server-driven object): this system does not advertise ADT support for it. ` +
|
|
235
|
+
'These types are discovery-gated and depend on the SAP release / support package ' +
|
|
236
|
+
'(e.g. DTSC/CSNM/EVTO/UIAD need ABAP Platform 2025 / SAP_BASIS 8.16+, while DTDC/DSFD/EVTB also ship on S/4HANA 2023 / 758).');
|
|
116
237
|
}
|
|
117
238
|
/**
|
|
118
|
-
* Read a server-driven object: its
|
|
119
|
-
* The source is JSON-parsed when possible (raw text otherwise). Throws AdtApiError 404
|
|
120
|
-
* nonexistent object. Gate availability with supportsServerDrivenObject() on unknown systems.
|
|
239
|
+
* Read a server-driven object: its metadata (blue:blueSource or dtdc:dtdcSource) + source (AFF JSON
|
|
240
|
+
* or DDL text). The source is JSON-parsed when possible (raw text otherwise). Throws AdtApiError 404
|
|
241
|
+
* for a nonexistent object. Gate availability with supportsServerDrivenObject() on unknown systems.
|
|
121
242
|
*/
|
|
122
243
|
export async function getServerDrivenObject(http, safety, code, name) {
|
|
123
244
|
checkOperation(safety, OperationType.Read, 'GetServerDrivenObject');
|
|
124
245
|
const entry = sdoEntry(code);
|
|
125
246
|
const objUrl = serverDrivenObjectUrl(code, name);
|
|
126
|
-
const metaResp = await http.get(objUrl, { Accept: entry.
|
|
127
|
-
const metadata =
|
|
247
|
+
const metaResp = await http.get(objUrl, { Accept: entry.metadataContentType });
|
|
248
|
+
const metadata = parseServerDrivenMetadata(metaResp.body, entry.metadataRootLocalName);
|
|
128
249
|
const srcResp = await http.get(`${objUrl}/source/main`, { Accept: 'application/json, */*' });
|
|
129
250
|
let source = srcResp.body;
|
|
130
251
|
try {
|
|
@@ -136,22 +257,24 @@ export async function getServerDrivenObject(http, safety, code, name) {
|
|
|
136
257
|
return { ...metadata, source };
|
|
137
258
|
}
|
|
138
259
|
/**
|
|
139
|
-
* Build the minimal
|
|
140
|
-
* verified `createType` for `adtcore:type`
|
|
260
|
+
* Build the minimal metadata create body for a server-driven object — the per-type root element
|
|
261
|
+
* (blue:blueSource or dtdc:dtdcSource) with the verified `createType` for `adtcore:type`
|
|
262
|
+
* (e.g. DESD/TYP, EVTB/EVB, DTDC/DF) + the package ref.
|
|
141
263
|
*
|
|
142
264
|
* NOTE — no `adtcore:masterLanguage`: live-verified on a4h-2025 (816) that ADT *silently ignores*
|
|
143
265
|
* that attribute for these objects (create with masterLanguage="DE" → object still read back as the
|
|
144
266
|
* session language). The object's master language comes from the `sap-language` request param (the
|
|
145
267
|
* session = `config.language` / SAP_LANGUAGE), as with other source-based objects (cf. #343). Emitting
|
|
146
|
-
* it would be an ADT-ignored attribute
|
|
147
|
-
*
|
|
268
|
+
* it would be an ADT-ignored attribute — so the body here is exactly the form proven to create every
|
|
269
|
+
* registered type.
|
|
148
270
|
*/
|
|
149
|
-
export function
|
|
271
|
+
export function buildServerDrivenMetadataXml(code, name, pkg, description) {
|
|
150
272
|
const entry = sdoEntry(code);
|
|
273
|
+
const [prefix] = entry.metadataRootQName.split(':');
|
|
151
274
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
152
|
-
|
|
275
|
+
<${entry.metadataRootQName} xmlns:${prefix}="${entry.metadataNamespace}" xmlns:adtcore="http://www.sap.com/adt/core" adtcore:type="${escapeXmlAttr(entry.createType)}" adtcore:name="${escapeXmlAttr(name)}" adtcore:description="${escapeXmlAttr(description)}">
|
|
153
276
|
<adtcore:packageRef adtcore:name="${escapeXmlAttr(pkg)}"/>
|
|
154
|
-
|
|
277
|
+
</${entry.metadataRootQName}>`;
|
|
155
278
|
}
|
|
156
279
|
/**
|
|
157
280
|
* Create a server-driven object (metadata only — POST the <blue:blueSource> body to the collection
|
|
@@ -161,17 +284,19 @@ export function buildBlueSourceXml(code, name, pkg, description) {
|
|
|
161
284
|
export async function createServerDrivenObject(http, safety, code, name, opts) {
|
|
162
285
|
checkOperation(safety, OperationType.Create, 'CreateServerDrivenObject');
|
|
163
286
|
const entry = sdoEntry(code);
|
|
164
|
-
const body =
|
|
287
|
+
const body = buildServerDrivenMetadataXml(code, name, opts.package, opts.description);
|
|
165
288
|
const url = opts.transport ? `${entry.href}?corrNr=${encodeURIComponent(opts.transport)}` : entry.href;
|
|
166
|
-
const resp = await http.post(url, body, entry.
|
|
289
|
+
const resp = await http.post(url, body, entry.metadataContentType);
|
|
167
290
|
return resp.body;
|
|
168
291
|
}
|
|
169
292
|
/**
|
|
170
|
-
* Write the
|
|
171
|
-
*
|
|
172
|
-
*
|
|
293
|
+
* Write the source of a server-driven object: lock → PUT …/source/main → unlock (guaranteed via
|
|
294
|
+
* try-finally). The Content-Type comes from the type's declared sourceFormat — AFF-JSON types take
|
|
295
|
+
* application/json, DDL-text types (DTSC, DSFD) take text/plain; sending the wrong one is a 415.
|
|
296
|
+
* Auto-propagates the lock's corrNr when no explicit transport is supplied (same contract as
|
|
297
|
+
* crud.ts safeUpdateSource).
|
|
173
298
|
*/
|
|
174
|
-
export async function updateServerDrivenObjectSource(http, safety, code, name,
|
|
299
|
+
export async function updateServerDrivenObjectSource(http, safety, code, name, source, opts = {}) {
|
|
175
300
|
checkOperation(safety, OperationType.Update, 'UpdateServerDrivenObjectSource');
|
|
176
301
|
const objUrl = serverDrivenObjectUrl(code, name);
|
|
177
302
|
await http.withStatefulSession(async (session) => {
|
|
@@ -181,7 +306,7 @@ export async function updateServerDrivenObjectSource(http, safety, code, name, s
|
|
|
181
306
|
const params = [`lockHandle=${encodeURIComponent(lock.lockHandle)}`];
|
|
182
307
|
if (transport)
|
|
183
308
|
params.push(`corrNr=${encodeURIComponent(transport)}`);
|
|
184
|
-
await session.put(`${objUrl}/source/main?${params.join('&')}`,
|
|
309
|
+
await session.put(`${objUrl}/source/main?${params.join('&')}`, source, serverDrivenSourceContentType(code));
|
|
185
310
|
}
|
|
186
311
|
finally {
|
|
187
312
|
await unlockObject(session, objUrl, lock.lockHandle);
|