Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ COPY --from=docker/mcp-gateway /docker-mcp /usr/libexec/docker/cli-plugins/docke

# Install necessary libraries for Chromium
RUN apt-get update && apt-get install -y \
build-essential \
ca-certificates \
fonts-liberation \
libasound2 \
Expand Down Expand Up @@ -47,8 +48,12 @@ RUN apt-get update && apt-get install -y \
# RUN npm install -g npm@latest

USER node
# Install uv Python package manager
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
# Install bun
RUN curl -fsSL https://bun.sh/install | bash
# Install Homebrew
RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Make Homebrew available without eval
ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:${PATH}"

# Install toolchain and CLI tools via Homebrew
RUN brew install gcc uv oven-sh/bun/bun

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,7 @@ vite.config.*.timestamp*
vitest.config.*.timestamp*
secrets

.adt
.adt
package-lock.json

.skills
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ npx nx test
npx nx typecheck
```

## Service Key Drop-In

For local BTP authentication, you can drop service key JSON files into `.adt/destinations/` in the workspace or `~/.adt/destinations/` in your home directory.

Example:

```bash
mkdir -p .adt/destinations
cp ./service-key.json .adt/destinations/TRL.json

npx adt auth login --sid TRL
```

If exactly one such destination exists and no default SID has been stored yet, the CLI uses that SID as the default fallback.

### Common Commands

```bash
Expand Down
20 changes: 20 additions & 0 deletions packages/adk/src/base/adt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export type {
InterfaceResponse as InterfaceResponseUnion,
PackageResponse as PackageResponseUnion,
TransportGetResponse,
ProgramResponse as ProgramResponseUnion,
FunctionGroupResponse as FunctionGroupResponseUnion,
} from '@abapify/adt-client';

// CRUD contract types for typed ADK base model
Expand All @@ -54,6 +56,8 @@ import type {
ClassResponse as _ClassResponse,
InterfaceResponse as _InterfaceResponse,
PackageResponse as _PackageResponse,
ProgramResponse as _ProgramResponse,
FunctionGroupResponse as _FunctionGroupResponse,
} from '@abapify/adt-client';

/**
Expand All @@ -78,6 +82,16 @@ export type InterfaceResponse = Extract<
*/
export type PackageResponse = Extract<_PackageResponse, { package: unknown }>;

/**
* Program response type - single root element (no union needed)
*/
export type ProgramResponse = _ProgramResponse;

/**
* Function group response type - single root element (no union needed)
*/
export type FunctionGroupResponse = _FunctionGroupResponse;

// ============================================
// ADK Contract Proxy
// Wraps adt-client contract with ADK-specific interface
Expand Down Expand Up @@ -110,6 +124,10 @@ export interface AdkContract {
readonly core: AdtContracts['core'];
/** Repository contracts (search) */
readonly repository: AdtContracts['repository'];
/** Programs contracts */
readonly programs: AdtContracts['programs'];
/** Functions contracts (function groups) */
readonly functions: AdtContracts['functions'];
}

/**
Expand All @@ -125,5 +143,7 @@ export function createAdkContract(client: AdtClient): AdkContract {
cts: client.adt.cts,
core: client.adt.core,
repository: client.adt.repository,
programs: client.adt.programs,
functions: client.adt.functions,
};
}
18 changes: 12 additions & 6 deletions packages/adk/src/base/kinds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export type AdkKind =
import type { AdkClass } from '../objects/repository/clas/clas.model';
import type { AdkInterface } from '../objects/repository/intf/intf.model';
import type { AdkPackage } from '../objects/repository/devc/devc.model';
import type { AdkProgram } from '../objects/repository/prog/prog.model';
import type { AdkFunctionGroup } from '../objects/repository/fugr/fugr.model';
import type {
AdkTransportRequest,
AdkTransportTask,
Expand All @@ -81,9 +83,13 @@ export type AdkObjectForKind<K extends AdkKind> = K extends typeof Class
? AdkInterface
: K extends typeof Package
? AdkPackage
: K extends typeof TransportRequest
? AdkTransportRequest
: K extends typeof TransportTask
? AdkTransportTask
: // Add more mappings as types are implemented
AdkObject; // fallback
: K extends typeof Program
? AdkProgram
: K extends typeof FunctionGroup
? AdkFunctionGroup
: K extends typeof TransportRequest
? AdkTransportRequest
: K extends typeof TransportTask
? AdkTransportTask
: // Add more mappings as types are implemented
AdkObject; // fallback
16 changes: 16 additions & 0 deletions packages/adk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export type {
ClassResponse,
InterfaceResponse,
PackageResponse,
ProgramResponse,
FunctionGroupResponse,
TransportGetResponse,
} from './base/adt';
export { createAdkContract } from './base/adt';
Expand Down Expand Up @@ -87,6 +89,20 @@ export type {
} from './objects/repository/intf';
export { AdkInterface } from './objects/repository/intf';

// Program types and class
export type {
AbapProgram,
ProgramXml, // Raw API response type
} from './objects/repository/prog';
export { AdkProgram } from './objects/repository/prog';

// Function group types and class
export type {
AbapFunctionGroup,
FunctionGroupXml, // Raw API response type
} from './objects/repository/fugr';
export { AdkFunctionGroup } from './objects/repository/fugr';

// CTS types (legacy complex transport)
export type {
TransportData,
Expand Down
132 changes: 132 additions & 0 deletions packages/adk/src/objects/repository/fugr/fugr.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* FUGR - ABAP Function Group
*
* ADK object for ABAP function groups (FUGR).
*/

import { AdkMainObject } from '../../../base/model';
import { FunctionGroup as FunctionGroupKind } from '../../../base/kinds';
import { getGlobalContext } from '../../../base/global-context';
import type { AdkContext } from '../../../base/context';

// Import response type from ADT integration layer
import type { FunctionGroupResponse } from '../../../base/adt';

/**
* Function group data type - unwrap from root element
*
* The schema wraps everything in an 'abapFunctionGroup' element, so we unwrap it here
* to provide a flat structure for ADK consumers.
*/
export type FunctionGroupXml = FunctionGroupResponse['abapFunctionGroup'];

/**
* ADK Function Group object
*
* Inherits from AdkMainObject which provides:
* - AdkObject: name, type, description, version, language, changedBy/At, createdBy/At, links
* - AdkMainObject: package, packageRef, responsible, masterLanguage, masterSystem, abapLanguageVersion
*
* Access function group-specific properties via `data`:
* - data.sourceUri, data.fixPointArithmetic, data.activeUnicodeCheck
*/
export class AdkFunctionGroup extends AdkMainObject<
typeof FunctionGroupKind,
FunctionGroupXml
> {
static readonly kind = FunctionGroupKind;
readonly kind = AdkFunctionGroup.kind;

// ADT object URI (computed - not in data)
get objectUri(): string {
return `/sap/bc/adt/functions/groups/${encodeURIComponent(this.name.toLowerCase())}`;
}

// Lazy segments - source code

async getSource(): Promise<string> {
return this.lazy('source', async () => {
return this.ctx.client.adt.functions.groups.source.main.get(this.name);
});
}

// ============================================
// Source Code Save Methods
// ============================================

/**
* Save main source code (top-include)
* Requires object to be locked first
*/
async saveMainSource(
source: string,
options?: { lockHandle?: string; transport?: string },
): Promise<void> {
const params = new URLSearchParams();
if (options?.lockHandle) params.set('lockHandle', options.lockHandle);
if (options?.transport) params.set('corrNr', options.transport);

await this.ctx.client.fetch(
`/sap/bc/adt/functions/groups/${this.name.toLowerCase()}/source/main${params.toString() ? '?' + params.toString() : ''}`,
{
method: 'PUT',
headers: { 'Content-Type': 'text/plain' },
body: source,
},
);
}

/**
* Save pending source (set via _pendingSource)
* Used by export workflow after deserialization from abapGit
* Overrides base class method
*/
protected override async savePendingSources(options?: {
lockHandle?: string;
transport?: string;
}): Promise<void> {
const pendingSource = (this as unknown as { _pendingSource?: string })
._pendingSource;
if (!pendingSource) return;

await this.saveMainSource(pendingSource, options);

// Clear pending source after save
delete (this as unknown as { _pendingSource?: string })._pendingSource;
}

/**
* Check if object has pending sources to save
* Overrides base class method
*/
protected override hasPendingSources(): boolean {
return !!(this as unknown as { _pendingSource?: string })._pendingSource;
}

// ============================================
// CRUD contract config - enables save()
// ============================================

protected override get wrapperKey() {
return 'abapFunctionGroup';
}
// Note: `any` return type is intentional here — this is an established pattern
// in the ADK codebase (see intf.model.ts). The base class defines
// crudContract as `any` to support different contract structures per object type.
protected override get crudContract(): any {
return this.ctx.client.adt.functions.groups;
}

// ============================================
// Static Factory Method
// ============================================

static async get(name: string, ctx?: AdkContext): Promise<AdkFunctionGroup> {
const context = ctx ?? getGlobalContext();
return new AdkFunctionGroup(context, name).load();
}
}

// Self-register with ADK registry
import { registerObjectType } from '../../../base/registry';
registerObjectType('FUGR', FunctionGroupKind, AdkFunctionGroup);
44 changes: 44 additions & 0 deletions packages/adk/src/objects/repository/fugr/fugr.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* FUGR - ABAP Function Group
*
* Public interface for ABAP Function Group objects.
* Based on ADT fugr:abapFunctionGroup XML structure.
*/

import type { AbapObject } from '../../../base/types';
import type { AdtObjectReference } from '../../../base/model';

/**
* ABAP Function Group interface
*
* Plugins work with this interface - implementation is internal.
* Mirrors ADT fugr:abapFunctionGroup structure.
*/
export interface AbapFunctionGroup extends AbapObject {
readonly kind: 'FunctionGroup';

// Core attributes (from adtcore:*)
readonly responsible: string;
readonly masterLanguage: string;
readonly language: string;
readonly version: string;
readonly createdAt: Date;
readonly createdBy: string;
readonly changedAt: Date;
readonly changedBy: string;

// Source attributes (from abapsource:*)
readonly sourceUri: string;
readonly fixPointArithmetic: boolean;
readonly activeUnicodeCheck: boolean;

// References
readonly packageRef?: AdtObjectReference;

// Lazy segments - fetched on demand

/**
* Get function group top-include source code
*/
getSource(): Promise<string>;
}
12 changes: 12 additions & 0 deletions packages/adk/src/objects/repository/fugr/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* FUGR - ABAP Function Group
*/

// Public types
export type { AbapFunctionGroup } from './fugr.types';

// ADK object (internal implementation)
export { AdkFunctionGroup } from './fugr.model';

// Schema-inferred type for raw API response
export type { FunctionGroupXml } from './fugr.model';
12 changes: 12 additions & 0 deletions packages/adk/src/objects/repository/prog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* PROG - ABAP Program
*/

// Public types
export type { AbapProgram } from './prog.types';

// ADK object (internal implementation)
export { AdkProgram } from './prog.model';

// Schema-inferred type for raw API response
export type { ProgramXml } from './prog.model';
Loading