@abapify/adt-tui 0.4.17 → 0.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import React$1, { ReactNode } from "react";
2
- //#region src/lib/types.d.ts
3
2
  /**
4
3
  * Core types for ADT TUI
5
4
  */
@@ -103,8 +102,6 @@ interface Route {
103
102
  /** Optional name for debugging */
104
103
  name?: string;
105
104
  }
106
- //#endregion
107
- //#region src/lib/router.d.ts
108
105
  /**
109
106
  * Router class for URL pattern matching
110
107
  */
@@ -134,8 +131,6 @@ declare class Router {
134
131
  name?: string;
135
132
  }>;
136
133
  }
137
- //#endregion
138
- //#region src/run.d.ts
139
134
  interface RunOptions {
140
135
  /** Optional starting URL - if not provided, shows prompt */
141
136
  startUrl?: string;
@@ -154,8 +149,6 @@ interface RunOptions {
154
149
  * @returns Promise that resolves when the app exits
155
150
  */
156
151
  declare function run(options: RunOptions): Promise<void>;
157
- //#endregion
158
- //#region src/App.d.ts
159
152
  interface AppProps {
160
153
  /** Optional starting URL - if not provided, shows prompt */
161
154
  startUrl?: string;
@@ -170,8 +163,6 @@ interface AppProps {
170
163
  * Main TUI Application
171
164
  */
172
165
  declare function App({ startUrl, fetch, router: _router, systemName }: AppProps): React.ReactNode;
173
- //#endregion
174
- //#region src/Navigator.d.ts
175
166
  interface NavigatorProps {
176
167
  /** Optional starting URL - if not provided, shows prompt */
177
168
  startUrl?: string;
@@ -184,8 +175,6 @@ interface NavigatorProps {
184
175
  * Main Navigator component
185
176
  */
186
177
  declare function Navigator({ startUrl, fetch, systemName }: NavigatorProps): React.ReactNode;
187
- //#endregion
188
- //#region src/lib/PageRenderer.d.ts
189
178
  interface PageRendererProps {
190
179
  result: PageResult;
191
180
  onNavigate: (url: string) => void;
@@ -196,8 +185,6 @@ interface PageRendererProps {
196
185
  * PageRenderer component
197
186
  */
198
187
  declare function PageRenderer({ result, onNavigate, onBack, onAction }: PageRendererProps): React.ReactNode;
199
- //#endregion
200
- //#region src/lib/context.d.ts
201
188
  interface NavigationContextValue {
202
189
  /** Current navigation entry */
203
190
  current: NavigationEntry | null;
@@ -228,8 +215,6 @@ declare function NavigationProvider({ children, fetch, parseResponse, initialUrl
228
215
  * Hook to access navigation context
229
216
  */
230
217
  declare function useNavigation(): NavigationContextValue;
231
- //#endregion
232
- //#region src/lib/parser.d.ts
233
218
  /**
234
219
  * Parse ADT XML response
235
220
  */
@@ -246,12 +231,9 @@ declare function categorizeLinks(links: HypermediaLink[]): {
246
231
  actions: HypermediaLink[];
247
232
  self: HypermediaLink[];
248
233
  };
249
- //#endregion
250
- //#region src/pages/GenericPage.d.ts
251
234
  /**
252
235
  * Generic page - returns PageResult for framework rendering
253
236
  */
254
237
  declare function genericPage({ url, response }: PageProps): PageResult;
255
- //#endregion
256
238
  export { App, type AppProps, type FetchFn, type HypermediaLink, type MenuItem, type NavigationEntry, NavigationProvider, Navigator, type PageComponent, type PageProps, PageRenderer, type PageResult, type ParsedResponse, type Route, type RunOptions, categorizeLinks, genericPage, getActionName, parseResponse$1 as parseResponse, run, useNavigation };
257
239
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/types.ts","../src/lib/router.ts","../src/run.tsx","../src/App.tsx","../src/Navigator.tsx","../src/lib/PageRenderer.tsx","../src/lib/context.tsx","../src/lib/parser.ts","../src/pages/GenericPage.tsx"],"mappings":";;;;;;;;UASiB;EACf;EACA;EACA;EACA;;;;;UAMe;EACf;EACA,MAAM;EACN,OAAO;EACP;EACA;;;;;UAMe;EACf;EACA,UAAU;EACV,WAAW;;;;;KAMD,WACV,aACA;EACE;EACA,UAAU;EACV;MAEC;;;;UAKY;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;IAAW;IAAc;;;;;;UAMV;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA,SAAS,MAAM;;EAEf,MAAM;;EAEN;;;;;UAMe;;EAEf;;EAEA,UAAU;;;;;KAMA,iBAAiB,OAAO,cAAc;;;;UAKjC;;EAEf,SAAS;;EAET,MAAM;;EAEN;;;;;;;cCrGW;mBACM;UACT;;;;EAKR,SAAS,OAAO;;;;EAQhB,YAAY,MAAM;;;;EAQlB,MAAM;IAAgB,MAAM;IAAe;;;;;EAqB3C,cAAc;IAAQ;IAAiB;;;;;UC3CxB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;EAET;;EAEA;;;;;;;iBAQoB,IAAI,SAAS,aAAa;;;UCnB/B;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;EAET;;;;;iBAMc,MACd,UACA,OACA,QAAQ,SACR,cACC,WAAW,MAAM;;;UCRV;;EAER;;EAEA,OAAO;;EAEP;;;;;iBAwIc,YACd,UACA,OACA,cACC,iBAAiB,MAAM;;;UC1JhB;EACR,QAAQ;EACR,aAAa;EACb;EACA,YAAY;;;;;iBAkCE,eACd,QACA,YACA,QACA,YACC,oBAAoB,MAAM;;;UC1CnB;;EAER,SAAS;;EAET,SAAS;;EAET,WAAW,gBAAgB;;EAE3B;;EAEA;;EAEA;;EAEA,OAAO;;UAKC;EACR,UAAU;;EAEV,OAAO;;EAEP,gBAAgB,gBAAgB;;EAEhC;;iBAGc,qBACd,UACA,OACA,eACA,cACC,0BAA0B,QAAM;;;;iBA0EnB,iBAAiB;;;;;;iBC5BjB,gBAAc,cAAc;;;;iBAiB5B,cAAc;;;;iBAQd,gBAAgB,OAAO;EACrC,YAAY;EACZ,SAAS;EACT,MAAM;;;;;;;iBCvGQ,cAAc,KAAK,YAAY,YAAY"}
1
+ {"version":3,"file":"index.d.mts","names":["React","parseResponse"],"sources":["../src/lib/types.ts","../src/lib/router.ts","../src/run.tsx","../src/App.tsx","../src/Navigator.tsx","../src/lib/PageRenderer.tsx","../src/lib/context.tsx","../src/lib/parser.ts","../src/pages/GenericPage.tsx"],"mappings":";;;;;;;UASiB;EACf;EACA;EACA;EACA;;;;;UAMe;EACf;EACA,MAAM;EACN,OAAO;EACP;EACA;;;;;UAMe;EACf;EACA,UAAU;EACV,WAAW;;;;;KAMD,WACV,aACA;EACE;EACA,UAAU;EACV;MAEC;;;;UAKY;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;IAAW;IAAc;;;;;;UAMV;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA,SAAS,MAAM;;EAEf,MAAM;;EAEN;;;;;UAMe;;EAEf;;EAEA,UAAU;;;;;KAMA,iBAAiB,OAAO,cAAc;;;;UAKjC;;EAEf,SAAS;;EAET,MAAM;;EAEN;;;;;cCrGW;mBACM;UACT;;;;EAKR,SAAS,OAAO;;;;EAQhB,YAAY,MAAM;;;;EAQlB,MAAM;IAAgB,MAAM;IAAe;;;;;EAqB3C,cAAc;IAAQ;IAAiB;;;UC3CxB;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;EAET;;EAEA;;;;;;;iBAQoB,IAAI,SAAS,aAAa;UCnB/B;;EAEf;;EAEA,OAAO;;EAEP,SAAS;;EAET;;;;;iBAMc,MACd,UACA,OACA,QAAQ,SACR,cACC,WAAW,MAAM;UCRV;;EAER;;EAEA,OAAO;;EAEP;;;;;iBAwIc,YACd,UACA,OACA,cACC,iBAAiB,MAAM;UC1JhB;EACR,QAAQ;EACR,aAAa;EACb;EACA,YAAY;;;;;iBAkCE,eACd,QACA,YACA,QACA,YACC,oBAAoB,MAAM;UC1CnB;;EAER,SAAS;;EAET,SAAS;;EAET,WAAW,gBAAgB;;EAE3B;;EAEA;;EAEA;;EAEA,OAAO;;UAKC;EACR,UAAU;;EAEV,OAAO;;EAEP,gBAAgB,gBAAgB;;EAEhC;;iBAGc,qBACd,UACA,OACA,eACA,cACC,0BAA0BA,QAAM;;;;iBA0EnB,iBAAiB;;;;iBC5BjBC,gBAAc,cAAc;;;;iBAiB5B,cAAc;;;;iBAQd,gBAAgB,OAAO;EACrC,YAAY;EACZ,SAAS;EACT,MAAM;;;;;iBCvGQ,cAAc,KAAK,YAAY,YAAY"}
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
10
10
  import { XMLParser } from "fast-xml-parser";
11
11
  import { transportmanagmentSingle } from "@abapify/adt-contracts";
12
12
 
13
- //#region src/lib/context.tsx
13
+ // src/lib/context.tsx
14
14
  /**
15
15
  * Navigation Context
16
16
  *
@@ -81,8 +81,7 @@ function useNavigation() {
81
81
  return context;
82
82
  }
83
83
 
84
- //#endregion
85
- //#region src/lib/parser.ts
84
+ // src/lib/parser.ts
86
85
  /**
87
86
  * XML Response Parser
88
87
  *
@@ -176,8 +175,7 @@ function categorizeLinks(links) {
176
175
  };
177
176
  }
178
177
 
179
- //#endregion
180
- //#region src/lib/PageRenderer.tsx
178
+ // src/lib/PageRenderer.tsx
181
179
  /**
182
180
  * PageRenderer - Framework component that renders PageResult
183
181
  *
@@ -275,8 +273,7 @@ function PageRenderer({ result, onNavigate, onBack, onAction }) {
275
273
  });
276
274
  }
277
275
 
278
- //#endregion
279
- //#region src/pages/sap/bc/adt/cts/transportrequests/[slug].loader.ts
276
+ // src/pages/sap/bc/adt/cts/transportrequests/[slug].loader.ts
280
277
  /**
281
278
  * Transport Request/Task Loader
282
279
  *
@@ -339,8 +336,7 @@ function transformToTransportData(data) {
339
336
  };
340
337
  }
341
338
 
342
- //#endregion
343
- //#region src/pages/sap/bc/adt/cts/transportrequests/[slug].tsx
339
+ // src/pages/sap/bc/adt/cts/transportrequests/[slug].tsx
344
340
  /**
345
341
  * Transport Request/Task Page
346
342
  *
@@ -517,8 +513,7 @@ function transportPage({ url: _url, response }) {
517
513
  };
518
514
  }
519
515
 
520
- //#endregion
521
- //#region src/pages/_routes.ts
516
+ // src/pages/_routes.ts
522
517
  /**
523
518
  * Auto-generated route manifest
524
519
  * DO NOT EDIT - Generated by scripts/generate-routes.ts
@@ -536,8 +531,7 @@ function matchRoute(url) {
536
531
  return null;
537
532
  }
538
533
 
539
- //#endregion
540
- //#region src/pages/GenericPage.tsx
534
+ // src/pages/GenericPage.tsx
541
535
  /**
542
536
  * Generic Page Component
543
537
  *
@@ -641,8 +635,7 @@ function extractSummary(data) {
641
635
  return summary.slice(0, 8);
642
636
  }
643
637
 
644
- //#endregion
645
- //#region src/Navigator.tsx
638
+ // src/Navigator.tsx
646
639
  /**
647
640
  * Navigator Component
648
641
  *
@@ -782,8 +775,7 @@ function UrlPrompt({ onSubmit }) {
782
775
  });
783
776
  }
784
777
 
785
- //#endregion
786
- //#region src/App.tsx
778
+ // src/App.tsx
787
779
  /**
788
780
  * Main App Component
789
781
  *
@@ -810,8 +802,7 @@ function App({ startUrl, fetch, router: _router, systemName }) {
810
802
  });
811
803
  }
812
804
 
813
- //#endregion
814
- //#region src/run.tsx
805
+ // src/run.tsx
815
806
  /**
816
807
  * Run TUI Application
817
808
  *
@@ -831,6 +822,5 @@ async function run(options) {
831
822
  onExit?.();
832
823
  }
833
824
 
834
- //#endregion
835
825
  export { App, NavigationProvider, Navigator, PageRenderer, categorizeLinks, genericPage, getActionName, parseResponse, run, useNavigation };
836
826
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Page0"],"sources":["../src/lib/context.tsx","../src/lib/parser.ts","../src/lib/PageRenderer.tsx","../src/pages/sap/bc/adt/cts/transportrequests/[slug].loader.ts","../src/pages/sap/bc/adt/cts/transportrequests/[slug].tsx","../src/pages/_routes.ts","../src/pages/GenericPage.tsx","../src/Navigator.tsx","../src/App.tsx","../src/run.tsx"],"sourcesContent":["/**\n * Navigation Context\n *\n * React context for sharing navigation state across components.\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n type ReactNode,\n} from 'react';\nimport type { NavigationEntry, ParsedResponse, FetchFn } from './types';\n\ninterface NavigationContextValue {\n /** Current navigation entry */\n current: NavigationEntry | null;\n /** Navigation history */\n history: NavigationEntry[];\n /** Navigate to URL */\n navigate: (url: string) => Promise<void>;\n /** Go back */\n back: () => void;\n /** Is loading */\n loading: boolean;\n /** Error message */\n error: string | null;\n /** Fetch function */\n fetch: FetchFn;\n}\n\nconst NavigationContext = createContext<NavigationContextValue | null>(null);\n\ninterface NavigationProviderProps {\n children: ReactNode;\n /** Fetch function for making requests */\n fetch: FetchFn;\n /** Parse response function */\n parseResponse: (xml: string) => ParsedResponse;\n /** Initial URL to load */\n initialUrl?: string;\n}\n\nexport function NavigationProvider({\n children,\n fetch,\n parseResponse,\n initialUrl,\n}: NavigationProviderProps): React.ReactNode {\n const [current, setCurrent] = useState<NavigationEntry | null>(null);\n const [history, setHistory] = useState<NavigationEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const navigate = useCallback(\n async (url: string) => {\n setLoading(true);\n setError(null);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: '*/*' },\n });\n\n const parsed = parseResponse(response);\n const entry: NavigationEntry = {\n url,\n response: parsed,\n timestamp: new Date(),\n };\n\n // Push current to history if exists\n if (current) {\n setHistory((prev: NavigationEntry[]) => [...prev, current]);\n }\n\n setCurrent(entry);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setLoading(false);\n }\n },\n [current, fetch, parseResponse],\n );\n\n const back = useCallback(() => {\n if (history.length === 0) return;\n\n const prev = history[history.length - 1];\n setHistory((h: NavigationEntry[]) => h.slice(0, -1));\n setCurrent(prev);\n }, [history]);\n\n // Load initial URL on mount\n React.useEffect(() => {\n if (initialUrl && !current) {\n navigate(initialUrl);\n }\n }, [initialUrl, current, navigate]);\n\n return (\n <NavigationContext.Provider\n value={{\n current,\n history,\n navigate,\n back,\n loading,\n error,\n fetch,\n }}\n >\n {children}\n </NavigationContext.Provider>\n );\n}\n\n/**\n * Hook to access navigation context\n */\nexport function useNavigation(): NavigationContextValue {\n const context = useContext(NavigationContext);\n if (!context) {\n throw new Error('useNavigation must be used within NavigationProvider');\n }\n return context;\n}\n","/**\n * XML Response Parser\n *\n * Parses ADT XML responses and extracts hypermedia links.\n */\n\nimport { XMLParser } from 'fast-xml-parser';\nimport type { ParsedResponse, HypermediaLink } from './types';\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n removeNSPrefix: false,\n parseAttributeValue: true,\n trimValues: true,\n});\n\n/**\n * Extract all atom:link elements from parsed XML object\n */\nfunction extractLinks(\n obj: unknown,\n links: HypermediaLink[] = [],\n): HypermediaLink[] {\n if (!obj || typeof obj !== 'object') return links;\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n extractLinks(item, links);\n }\n } else {\n const record = obj as Record<string, unknown>;\n\n const linkKey = Object.keys(record).find(\n (k) => k === 'atom:link' || k === 'link' || k.endsWith(':link'),\n );\n\n if (linkKey) {\n const linkData = record[linkKey];\n const linkArray = Array.isArray(linkData) ? linkData : [linkData];\n\n for (const link of linkArray) {\n if (link && typeof link === 'object') {\n const linkObj = link as Record<string, unknown>;\n const href = linkObj['@_href'] as string;\n const rel = linkObj['@_rel'] as string;\n\n if (href && rel) {\n links.push({\n href,\n rel,\n type: linkObj['@_type'] as string | undefined,\n title: linkObj['@_title'] as string | undefined,\n });\n }\n }\n }\n }\n\n for (const key of Object.keys(record)) {\n if (key !== linkKey) {\n extractLinks(record[key], links);\n }\n }\n }\n\n return links;\n}\n\n/**\n * Detect root element and namespace from parsed XML\n */\nfunction detectRootInfo(data: Record<string, unknown>): {\n namespace?: string;\n rootElement?: string;\n} {\n const keys = Object.keys(data).filter((k) => k !== '?xml');\n if (keys.length === 0) return {};\n\n const rootKey = keys[0];\n const colonIndex = rootKey.indexOf(':');\n\n if (colonIndex > 0) {\n return {\n namespace: rootKey.substring(0, colonIndex),\n rootElement: rootKey.substring(colonIndex + 1),\n };\n }\n\n return { rootElement: rootKey };\n}\n\n/**\n * Parse ADT XML response\n */\nexport function parseResponse(xml: string): ParsedResponse {\n const data = parser.parse(xml) as Record<string, unknown>;\n const links = extractLinks(data);\n const { namespace, rootElement } = detectRootInfo(data);\n\n return {\n raw: xml,\n data,\n links,\n namespace,\n rootElement,\n };\n}\n\n/**\n * Get action name from relation URL\n */\nexport function getActionName(rel: string): string {\n const lastSlash = rel.lastIndexOf('/');\n return lastSlash >= 0 ? rel.substring(lastSlash + 1) : rel;\n}\n\n/**\n * Categorize links by type\n */\nexport function categorizeLinks(links: HypermediaLink[]): {\n navigation: HypermediaLink[];\n actions: HypermediaLink[];\n self: HypermediaLink[];\n} {\n const navigation: HypermediaLink[] = [];\n const actions: HypermediaLink[] = [];\n const self: HypermediaLink[] = [];\n\n for (const link of links) {\n if (link.rel === 'self') {\n self.push(link);\n } else if (\n link.rel.includes('/relations/') ||\n link.rel.includes('adturi')\n ) {\n actions.push(link);\n } else {\n navigation.push(link);\n }\n }\n\n return { navigation, actions, self };\n}\n","/**\n * PageRenderer - Framework component that renders PageResult\n *\n * Handles:\n * - Header with title/icon\n * - Page content\n * - Menu navigation with keyboard\n * - Footer\n */\n\nimport { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { PageResult, MenuItem } from './types';\n\ninterface PageRendererProps {\n result: PageResult;\n onNavigate: (url: string) => void;\n onBack: () => void;\n onAction?: (key: string) => void;\n}\n\n/**\n * Render a single menu item\n */\nfunction MenuItemRow({\n item,\n isSelected,\n}: {\n item: MenuItem;\n isSelected: boolean;\n}) {\n const prefix = isSelected ? '❯ ' : ' ';\n\n return (\n <Text color={isSelected ? 'cyan' : undefined}>\n {prefix}\n {item.icon && `${item.icon} `}\n {item.label}\n {item.status && (\n <Text color={item.status.color} dimColor={!isSelected}>\n {' '}\n [{item.status.text}]\n </Text>\n )}\n {item.info && <Text dimColor> {item.info}</Text>}\n </Text>\n );\n}\n\n/**\n * PageRenderer component\n */\nexport function PageRenderer({\n result,\n onNavigate,\n onBack,\n onAction,\n}: PageRendererProps): React.ReactNode {\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n // Handle keyboard input\n useInput((input, key) => {\n if (key.upArrow) {\n setSelectedIndex((i) => Math.max(0, i - 1));\n } else if (key.downArrow) {\n setSelectedIndex((i) => Math.min(result.menu.length - 1, i + 1));\n } else if (key.return) {\n const item = result.menu[selectedIndex];\n if (item.isBack) {\n onBack();\n } else if (item.href) {\n onNavigate(item.href);\n } else if (onAction) {\n onAction(item.key);\n }\n } else if (input === 'o' || input === 'O') {\n // Open XML in VS Code\n onAction?.('openXml');\n } else if (input === 'e' || input === 'E') {\n // Open in Eclipse ADT\n onAction?.('openAdt');\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header */}\n <Box\n borderStyle=\"round\"\n borderColor={result.color || 'cyan'}\n paddingX={2}\n marginBottom={1}\n >\n <Text bold color={result.color || 'cyan'}>\n {result.icon && `${result.icon} `}\n {result.title}\n </Text>\n {result.subtitle && <Text dimColor> ({result.subtitle})</Text>}\n </Box>\n\n {/* Content */}\n <Box flexDirection=\"column\" marginBottom={1}>\n {result.content}\n </Box>\n\n {/* Menu */}\n <Box flexDirection=\"column\">\n {result.menu.map((item, i) => (\n <MenuItemRow\n key={item.key}\n item={item}\n isSelected={i === selectedIndex}\n />\n ))}\n </Box>\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text dimColor>\n {result.footer || '[↑↓] navigate | [Enter] select'}\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Transport Request/Task Loader\n *\n * Uses adt-contracts for type-safe XML parsing.\n */\n\nimport {\n transportmanagmentSingle,\n type TransportResponse,\n} from '@abapify/adt-contracts';\n\n// Re-export the schema for type inference\nexport { transportmanagmentSingle as schema };\n\n// Use type from contracts package\ntype TransportRoot = TransportResponse;\n\n// Extract nested types - TransportResponse has root.request structure\nexport type Request = NonNullable<\n NonNullable<TransportRoot['root']>['request']\n>;\nexport type Task = NonNullable<Request['task']>[number];\nexport type AbapObject = NonNullable<Task['abap_object']>[number];\n\n/**\n * Parsed transport data with computed properties\n */\nexport interface TransportData {\n /** Whether this is a task (vs request) */\n isTask: boolean;\n /** Transport/Task number */\n number: string;\n /** Parent request number (for tasks) */\n parent?: string;\n /** Owner user ID */\n owner: string;\n /** Description */\n desc: string;\n /** Transport type */\n type: string;\n /** Status code (D=Modifiable, R=Released, O=Protected) */\n status: string;\n /** Status text */\n statusText: string;\n /** Target system */\n target: string;\n /** Target description */\n targetDesc: string;\n /** Child tasks (for requests) */\n tasks: TaskInfo[];\n /** Objects (for tasks) */\n objects: ObjectInfo[];\n /** Raw parsed data */\n raw: TransportRoot;\n}\n\nexport interface TaskInfo {\n number: string;\n owner: string;\n desc: string;\n status: string;\n statusText: string;\n uri: string;\n}\n\nexport interface ObjectInfo {\n pgmid: string;\n type: string;\n name: string;\n info: string;\n lockStatus: string;\n uri?: string;\n}\n\n/**\n * Load and parse transport request/task XML\n */\nexport function load(xml: string): TransportData {\n const parsed = transportmanagmentSingle.parse(xml);\n return transformToTransportData(parsed);\n}\n\n/**\n * Transform parsed XSD data to TransportData\n */\nfunction transformToTransportData(data: TransportRoot): TransportData {\n const request = data.root?.request;\n\n if (!request) {\n throw new Error('No request element found in transport data');\n }\n\n // Check if this is a task view (has parent) or request view\n const isTask = !!request.parent;\n\n // Extract tasks\n const tasks: TaskInfo[] = [];\n if (request.task && !isTask) {\n const taskArray = Array.isArray(request.task)\n ? request.task\n : [request.task];\n for (const task of taskArray) {\n tasks.push({\n number: task.number ?? '',\n owner: task.owner ?? '',\n desc: task.desc ?? '',\n status: task.status ?? '',\n statusText: task.status_text ?? '',\n uri: task.uri ?? '',\n });\n }\n }\n\n // Extract objects (from task's abap_object)\n const objects: ObjectInfo[] = [];\n if (request.task && isTask) {\n // When viewing a task, the task element contains objects\n const taskArray = Array.isArray(request.task)\n ? request.task\n : [request.task];\n for (const task of taskArray) {\n if (task.abap_object) {\n const objArray = Array.isArray(task.abap_object)\n ? task.abap_object\n : [task.abap_object];\n for (const obj of objArray) {\n objects.push({\n pgmid: obj.pgmid ?? '',\n type: obj.type ?? '',\n name: obj.name ?? '',\n info: obj.obj_info ?? obj.obj_desc ?? '',\n lockStatus: obj.lock_status ?? '',\n uri: obj.uri,\n });\n }\n }\n }\n }\n\n return {\n isTask,\n number: request.number ?? '',\n parent: request.parent,\n owner: request.owner ?? '',\n desc: request.desc ?? '',\n type: request.type ?? '',\n status: request.status ?? '',\n statusText: request.status_text ?? '',\n target: request.target ?? '',\n targetDesc: request.target_desc ?? '',\n tasks,\n objects,\n raw: data,\n };\n}\n","/**\n * Transport Request/Task Page\n *\n * Returns PageResult for framework-driven rendering.\n * Uses schema-driven parsing via [slug].loader.ts\n */\n\nimport { Box, Text } from 'ink';\nimport type {\n PageProps,\n PageResult,\n MenuItem,\n} from '../../../../../../lib/types';\nimport { load } from './[slug].loader';\n\n/**\n * Get status color\n */\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'D':\n return 'yellow'; // Modifiable\n case 'R':\n return 'green'; // Released\n case 'O':\n return 'cyan'; // Protected\n default:\n return 'white';\n }\n}\n\n/**\n * Transport Page - returns PageResult for framework rendering\n */\nexport function transportPage({\n url: _url,\n response,\n}: PageProps): PageResult | null {\n // Parse transport data\n let transport;\n try {\n transport = load(response.raw);\n } catch (_e) {\n return null;\n }\n\n // Build menu items\n const menu: MenuItem[] = [\n { key: 'back', label: 'Back', icon: '←', isBack: true },\n ];\n\n // Add parent link for tasks\n if (transport.isTask && transport.parent) {\n menu.push({\n key: 'parent',\n label: 'Go to Parent Request',\n icon: '⬆️',\n href: `/sap/bc/adt/cts/transportrequests/${transport.parent}`,\n });\n }\n\n // Add tasks (for requests)\n for (const task of transport.tasks) {\n menu.push({\n key: task.number,\n label: `${task.number} - ${task.desc || '(no desc)'}`,\n icon: '📝',\n href: task.uri,\n info: `@${task.owner}`,\n status: { text: task.statusText, color: getStatusColor(task.status) },\n });\n }\n\n // Add objects (for tasks)\n for (const obj of transport.objects) {\n const lockIcon = obj.lockStatus === 'X' ? '🔒' : '📦';\n menu.push({\n key: `${obj.pgmid}-${obj.name}`,\n label: `${obj.type} ${obj.name}`,\n icon: lockIcon,\n href: obj.uri,\n info: obj.uri ? undefined : '(no link)',\n });\n }\n\n // Add actions from links\n const actions = [\n { rel: 'consistencycheck', label: 'Consistency Check', icon: '🔍' },\n { rel: 'newreleasejobs', label: 'Release', icon: '🚀' },\n { rel: 'transportchecks', label: 'Transport Checks', icon: '✅' },\n ];\n\n for (const action of actions) {\n const link = response.links.find((l) => l.rel.includes(action.rel));\n if (link) {\n menu.push({\n key: action.rel,\n label: action.label,\n icon: action.icon,\n href: link.href,\n });\n }\n }\n\n // Build content\n const content = (\n <Box flexDirection=\"column\">\n <Text>\n <Text bold>Description:</Text> {transport.desc || '(no description)'}\n </Text>\n <Text>\n <Text bold>Owner:</Text> {transport.owner}\n </Text>\n <Text>\n <Text bold>Type:</Text> {transport.type}\n </Text>\n <Text>\n <Text bold>Status:</Text>{' '}\n <Text color={getStatusColor(transport.status)}>\n {transport.statusText} ({transport.status})\n </Text>\n </Text>\n {transport.target && (\n <Text>\n <Text bold>Target:</Text> {transport.target}{' '}\n {transport.targetDesc && `(${transport.targetDesc})`}\n </Text>\n )}\n {transport.tasks.length > 0 && (\n <Box marginTop={1}>\n <Text bold color=\"yellow\">\n 📋 Tasks ({transport.tasks.length}):\n </Text>\n </Box>\n )}\n {transport.objects.length > 0 && (\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n 📦 Objects ({transport.objects.length}):\n </Text>\n </Box>\n )}\n </Box>\n );\n\n const isTask = transport.isTask;\n return {\n title: `${isTask ? 'Task' : 'Transport Request'}: ${transport.number}`,\n icon: isTask ? '�' : '�',\n color: isTask ? 'yellow' : 'cyan',\n subtitle:\n isTask && transport.parent ? `Parent: ${transport.parent}` : undefined,\n content,\n menu,\n footer: '[o] XML in VS Code | [e] open in Eclipse ADT',\n };\n}\n\n// Default export for file-based routing\nexport default transportPage;\n","/**\n * Auto-generated route manifest\n * DO NOT EDIT - Generated by scripts/generate-routes.ts\n */\n\nimport { default as Page0 } from './sap/bc/adt/cts/transportrequests/[slug]';\nimport type { PageComponent } from '../lib/types';\n\nexport interface Route {\n pattern: string;\n regex: RegExp;\n page: PageComponent;\n}\n\nexport const routes: Route[] = [\n {\n pattern: '/sap/bc/adt/cts/transportrequests/:slug',\n regex: new RegExp('^/sap/bc/adt/cts/transportrequests/([^/]+)$'),\n page: Page0,\n },\n];\n\n/**\n * Match URL to route\n */\nexport function matchRoute(url: string): Route | null {\n for (const route of routes) {\n if (route.regex.test(url)) {\n return route;\n }\n }\n return null;\n}\n","/**\n * Generic Page Component\n *\n * Fallback page for unknown endpoints - shows payload + links.\n * Returns PageResult for framework-driven rendering.\n */\n\n// React import not needed with JSX transform\nimport { Box, Text } from 'ink';\nimport type { PageProps, PageResult, MenuItem } from '../lib/types';\nimport { getActionName } from '../lib/parser';\n\ninterface SummaryItem {\n key: string;\n value: string;\n}\n\n/**\n * Generic page - returns PageResult for framework rendering\n */\nexport function genericPage({ url, response }: PageProps): PageResult {\n // Extract summary from data\n const summary = extractSummary(response.data);\n\n // Build menu items from links\n const menu: MenuItem[] = [\n { key: 'back', label: 'Back', icon: '←', isBack: true },\n ];\n\n for (const link of response.links) {\n const title = link.title || getActionName(link.rel);\n\n // Make path relative/shorter for display\n let displayPath = link.href;\n const currentBase = url.split('/').slice(0, -1).join('/');\n if (link.href.startsWith(currentBase)) {\n displayPath = '.' + link.href.slice(currentBase.length);\n } else if (link.href.startsWith('/sap/bc/adt/')) {\n displayPath = link.href.replace('/sap/bc/adt/', '/');\n }\n if (displayPath.length > 40) {\n displayPath = '...' + displayPath.slice(-37);\n }\n\n menu.push({\n key: link.href,\n label: title,\n icon: '🔗',\n href: link.href,\n info: displayPath,\n });\n }\n\n // Build content\n const content = (\n <Box flexDirection=\"column\">\n <Text dimColor>URL: {url}</Text>\n <Box marginTop={1} flexDirection=\"column\">\n {summary.length > 0 ? (\n summary.map((item, i) => (\n <Text key={i}>\n <Text color=\"yellow\">{item.key}:</Text> {item.value}\n </Text>\n ))\n ) : (\n <Text dimColor>No summary available</Text>\n )}\n </Box>\n </Box>\n );\n\n return {\n title: `${response.namespace || 'unknown'}:${response.rootElement || 'response'}`,\n icon: '📄',\n color: 'cyan',\n content,\n menu,\n footer: `[o] XML | [e] Eclipse ADT | ${response.links.length} links`,\n };\n}\n\n/**\n * Extract key fields for summary display\n */\nfunction extractSummary(data: Record<string, unknown>): SummaryItem[] {\n const summary: SummaryItem[] = [];\n const seen = new Set<string>();\n\n function extract(obj: unknown, prefix = ''): void {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n obj.forEach((item) => extract(item, prefix));\n return;\n }\n\n const record = obj as Record<string, unknown>;\n for (const [key, value] of Object.entries(record)) {\n // Skip links and xml declaration\n if (key.includes('link') || key === '?xml') continue;\n\n // Extract interesting attributes (those starting with @_)\n if (\n (key.startsWith('@_') && typeof value === 'string') ||\n typeof value === 'number'\n ) {\n const cleanKey = key.replace('@_', '').replace(/^\\w+:/, '');\n // Skip duplicates and uninteresting fields\n if (\n seen.has(cleanKey) ||\n cleanKey === 'version' ||\n cleanKey === 'encoding'\n )\n continue;\n seen.add(cleanKey);\n\n // Limit to important fields\n const important = [\n 'number',\n 'owner',\n 'desc',\n 'status',\n 'status_text',\n 'type',\n 'target',\n 'name',\n 'uri',\n ];\n if (important.some((f) => cleanKey.includes(f))) {\n summary.push({ key: cleanKey, value: String(value) });\n }\n }\n\n // Recurse into nested objects\n if (typeof value === 'object') {\n extract(value, key);\n }\n }\n }\n\n extract(data);\n return summary.slice(0, 8); // Limit to 8 items\n}\n\n// removeLinks function removed - was unused\n","/**\n * Navigator Component\n *\n * Main entry point - renders pages using the framework.\n * Pages return PageResult, Navigator handles rendering.\n */\n\nimport { useState, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport TextInput from 'ink-text-input';\nimport { writeFileSync, existsSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { exec, execFile } from 'node:child_process';\nimport { NavigationProvider, useNavigation } from './lib/context';\nimport { parseResponse } from './lib/parser';\nimport { PageRenderer } from './lib/PageRenderer';\nimport { matchRoute } from './pages/_routes';\nimport { genericPage } from './pages/GenericPage';\nimport type { FetchFn, PageComponent, PageResult } from './lib/types';\n\ninterface NavigatorProps {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function */\n fetch: FetchFn;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n}\n\n/**\n * Open raw XML in IDE (VS Code)\n */\nfunction openXmlInIde(xml: string, url: string): void {\n const safeName = url.replaceAll(/[^a-zA-Z0-9]/g, '_').slice(-50);\n const filename = `adt_${safeName}.xml`;\n const filepath = join(tmpdir(), filename);\n writeFileSync(filepath, xml, 'utf-8');\n exec(`code \"${filepath}\"`, (error) => {\n if (error) {\n exec(`xdg-open \"${filepath}\"`);\n }\n });\n}\n\n/**\n * Resolve absolute path to a launcher binary from an allow-list of known\n * install locations. Prevents PATH-hijack (S4036) by avoiding bare-name\n * lookups when an absolute path is available. Falls back to the bare name\n * only if none of the known paths exist, so packaged distributions with\n * non-standard layouts still function.\n */\nfunction resolveLauncher(\n candidates: readonly string[],\n fallbackName: string,\n): string {\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return fallbackName;\n}\n\nconst XDG_OPEN = resolveLauncher(\n ['/usr/bin/xdg-open', '/usr/local/bin/xdg-open'],\n 'xdg-open',\n);\nconst OPEN_MAC = resolveLauncher(\n ['/usr/bin/open', '/usr/local/bin/open'],\n 'open',\n);\n\n/**\n * Open in Eclipse ADT\n * Format: adt://[system]/[path]\n * @see https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/opening-adt-links\n */\nfunction openInAdt(systemName: string, url: string): void {\n const adtUrl = `adt://${systemName}${url}`;\n // Use execFile (arg array, no shell) to avoid shell-command injection\n // via systemName/url. Try xdg-open (Linux), fall back to open (macOS).\n // Paths resolved above via allow-list to prevent PATH-hijack (S4036).\n execFile(XDG_OPEN, [adtUrl], (error) => {\n if (error) {\n execFile(OPEN_MAC, [adtUrl], (err2) => {\n if (err2) {\n console.error('Failed to open ADT link:', err2.message);\n }\n });\n }\n });\n}\n\n/**\n * Inner component that uses navigation context\n */\nfunction NavigatorInner({ systemName }: { systemName?: string }) {\n const { current, loading, error, navigate, back } = useNavigation();\n\n // Get page result\n const pageResult = useMemo<PageResult | null>(() => {\n if (!current) return null;\n\n // Try file-based route matching first\n const fileRoute = matchRoute(current.url);\n const pageFn: PageComponent = fileRoute?.page ?? genericPage;\n\n return pageFn({ url: current.url, response: current.response });\n }, [current]);\n\n // Handle actions\n const handleAction = (key: string) => {\n if (key === 'openXml' && current) {\n openXmlInIde(current.response.raw, current.url);\n } else if (key === 'openAdt' && current && systemName) {\n openInAdt(systemName, current.url);\n }\n };\n\n if (loading) {\n return (\n <Box padding={1}>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n <Text> Loading...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box padding={1} flexDirection=\"column\">\n <Text color=\"red\">❌ Error: {error}</Text>\n <Text dimColor>Press Ctrl+C to exit</Text>\n </Box>\n );\n }\n\n if (!current) {\n return <UrlPrompt onSubmit={navigate} />;\n }\n\n if (!pageResult) {\n return (\n <Box padding={1}>\n <Text dimColor>No content loaded</Text>\n </Box>\n );\n }\n\n return (\n <PageRenderer\n result={pageResult}\n onNavigate={navigate}\n onBack={back}\n onAction={handleAction}\n />\n );\n}\n\n/**\n * Main Navigator component\n */\nexport function Navigator({\n startUrl,\n fetch,\n systemName,\n}: NavigatorProps): React.ReactNode {\n return (\n <NavigationProvider\n fetch={fetch}\n parseResponse={parseResponse}\n initialUrl={startUrl}\n >\n <NavigatorInner systemName={systemName} />\n </NavigationProvider>\n );\n}\n\n/**\n * URL input prompt component\n */\nfunction UrlPrompt({ onSubmit }: { onSubmit: (url: string) => void }) {\n const [url, setUrl] = useState('');\n\n const handleSubmit = () => {\n if (url.trim()) {\n onSubmit(url.trim());\n }\n };\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"cyan\" bold>\n ADT TUI - Hypermedia Navigator\n </Text>\n <Box marginTop={1}>\n <Text>Enter URL: </Text>\n <TextInput value={url} onChange={setUrl} onSubmit={handleSubmit} />\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Example: /sap/bc/adt/cts/transportrequests/TRLK900001\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Main App Component\n *\n * Entry point for the TUI application.\n */\n\nimport { useState, useEffect } from 'react';\nimport { Navigator } from './Navigator';\nimport type { FetchFn } from './lib/types';\nimport type { Router } from './lib/router';\n\nexport interface AppProps {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function for making HTTP requests */\n fetch: FetchFn;\n /** Optional custom router */\n router?: Router;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n}\n\n/**\n * Main TUI Application\n */\nexport function App({\n startUrl,\n fetch,\n router: _router,\n systemName,\n}: AppProps): React.ReactNode {\n const [, setResizeKey] = useState(0);\n\n // Handle terminal resize - just trigger re-render, don't clear\n useEffect(() => {\n const handleResize = () => {\n setResizeKey((k) => k + 1);\n };\n\n process.stdout.on('resize', handleResize);\n return () => {\n process.stdout.off('resize', handleResize);\n };\n }, []);\n\n return (\n <Navigator startUrl={startUrl} fetch={fetch} systemName={systemName} />\n );\n}\n","/**\n * Run TUI Application\n *\n * Helper to render the TUI and wait for exit.\n */\n\n// React import not needed with JSX transform\nimport { render } from 'ink';\nimport { App } from './App';\nimport type { FetchFn } from './lib/types';\nimport type { Router } from './lib/router';\n\nexport interface RunOptions {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function for making HTTP requests */\n fetch: FetchFn;\n /** Optional custom router */\n router?: Router;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n /** Called when app exits */\n onExit?: () => void;\n}\n\n/**\n * Run the TUI application\n *\n * @returns Promise that resolves when the app exits\n */\nexport async function run(options: RunOptions): Promise<void> {\n const { onExit, ...appProps } = options;\n\n // Clear terminal on start\n console.clear();\n\n const { waitUntilExit, clear } = render(<App {...appProps} />);\n\n await waitUntilExit();\n\n // Cleanup\n clear();\n onExit?.();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["Page0"],"sources":["../src/lib/context.tsx","../src/lib/parser.ts","../src/lib/PageRenderer.tsx","../src/pages/sap/bc/adt/cts/transportrequests/[slug].loader.ts","../src/pages/sap/bc/adt/cts/transportrequests/[slug].tsx","../src/pages/_routes.ts","../src/pages/GenericPage.tsx","../src/Navigator.tsx","../src/App.tsx","../src/run.tsx"],"sourcesContent":["/**\n * Navigation Context\n *\n * React context for sharing navigation state across components.\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n type ReactNode,\n} from 'react';\nimport type { NavigationEntry, ParsedResponse, FetchFn } from './types';\n\ninterface NavigationContextValue {\n /** Current navigation entry */\n current: NavigationEntry | null;\n /** Navigation history */\n history: NavigationEntry[];\n /** Navigate to URL */\n navigate: (url: string) => Promise<void>;\n /** Go back */\n back: () => void;\n /** Is loading */\n loading: boolean;\n /** Error message */\n error: string | null;\n /** Fetch function */\n fetch: FetchFn;\n}\n\nconst NavigationContext = createContext<NavigationContextValue | null>(null);\n\ninterface NavigationProviderProps {\n children: ReactNode;\n /** Fetch function for making requests */\n fetch: FetchFn;\n /** Parse response function */\n parseResponse: (xml: string) => ParsedResponse;\n /** Initial URL to load */\n initialUrl?: string;\n}\n\nexport function NavigationProvider({\n children,\n fetch,\n parseResponse,\n initialUrl,\n}: NavigationProviderProps): React.ReactNode {\n const [current, setCurrent] = useState<NavigationEntry | null>(null);\n const [history, setHistory] = useState<NavigationEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const navigate = useCallback(\n async (url: string) => {\n setLoading(true);\n setError(null);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: '*/*' },\n });\n\n const parsed = parseResponse(response);\n const entry: NavigationEntry = {\n url,\n response: parsed,\n timestamp: new Date(),\n };\n\n // Push current to history if exists\n if (current) {\n setHistory((prev: NavigationEntry[]) => [...prev, current]);\n }\n\n setCurrent(entry);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setLoading(false);\n }\n },\n [current, fetch, parseResponse],\n );\n\n const back = useCallback(() => {\n if (history.length === 0) return;\n\n const prev = history[history.length - 1];\n setHistory((h: NavigationEntry[]) => h.slice(0, -1));\n setCurrent(prev);\n }, [history]);\n\n // Load initial URL on mount\n React.useEffect(() => {\n if (initialUrl && !current) {\n navigate(initialUrl);\n }\n }, [initialUrl, current, navigate]);\n\n return (\n <NavigationContext.Provider\n value={{\n current,\n history,\n navigate,\n back,\n loading,\n error,\n fetch,\n }}\n >\n {children}\n </NavigationContext.Provider>\n );\n}\n\n/**\n * Hook to access navigation context\n */\nexport function useNavigation(): NavigationContextValue {\n const context = useContext(NavigationContext);\n if (!context) {\n throw new Error('useNavigation must be used within NavigationProvider');\n }\n return context;\n}\n","/**\n * XML Response Parser\n *\n * Parses ADT XML responses and extracts hypermedia links.\n */\n\nimport { XMLParser } from 'fast-xml-parser';\nimport type { ParsedResponse, HypermediaLink } from './types';\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n removeNSPrefix: false,\n parseAttributeValue: true,\n trimValues: true,\n});\n\n/**\n * Extract all atom:link elements from parsed XML object\n */\nfunction extractLinks(\n obj: unknown,\n links: HypermediaLink[] = [],\n): HypermediaLink[] {\n if (!obj || typeof obj !== 'object') return links;\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n extractLinks(item, links);\n }\n } else {\n const record = obj as Record<string, unknown>;\n\n const linkKey = Object.keys(record).find(\n (k) => k === 'atom:link' || k === 'link' || k.endsWith(':link'),\n );\n\n if (linkKey) {\n const linkData = record[linkKey];\n const linkArray = Array.isArray(linkData) ? linkData : [linkData];\n\n for (const link of linkArray) {\n if (link && typeof link === 'object') {\n const linkObj = link as Record<string, unknown>;\n const href = linkObj['@_href'] as string;\n const rel = linkObj['@_rel'] as string;\n\n if (href && rel) {\n links.push({\n href,\n rel,\n type: linkObj['@_type'] as string | undefined,\n title: linkObj['@_title'] as string | undefined,\n });\n }\n }\n }\n }\n\n for (const key of Object.keys(record)) {\n if (key !== linkKey) {\n extractLinks(record[key], links);\n }\n }\n }\n\n return links;\n}\n\n/**\n * Detect root element and namespace from parsed XML\n */\nfunction detectRootInfo(data: Record<string, unknown>): {\n namespace?: string;\n rootElement?: string;\n} {\n const keys = Object.keys(data).filter((k) => k !== '?xml');\n if (keys.length === 0) return {};\n\n const rootKey = keys[0];\n const colonIndex = rootKey.indexOf(':');\n\n if (colonIndex > 0) {\n return {\n namespace: rootKey.substring(0, colonIndex),\n rootElement: rootKey.substring(colonIndex + 1),\n };\n }\n\n return { rootElement: rootKey };\n}\n\n/**\n * Parse ADT XML response\n */\nexport function parseResponse(xml: string): ParsedResponse {\n const data = parser.parse(xml) as Record<string, unknown>;\n const links = extractLinks(data);\n const { namespace, rootElement } = detectRootInfo(data);\n\n return {\n raw: xml,\n data,\n links,\n namespace,\n rootElement,\n };\n}\n\n/**\n * Get action name from relation URL\n */\nexport function getActionName(rel: string): string {\n const lastSlash = rel.lastIndexOf('/');\n return lastSlash >= 0 ? rel.substring(lastSlash + 1) : rel;\n}\n\n/**\n * Categorize links by type\n */\nexport function categorizeLinks(links: HypermediaLink[]): {\n navigation: HypermediaLink[];\n actions: HypermediaLink[];\n self: HypermediaLink[];\n} {\n const navigation: HypermediaLink[] = [];\n const actions: HypermediaLink[] = [];\n const self: HypermediaLink[] = [];\n\n for (const link of links) {\n if (link.rel === 'self') {\n self.push(link);\n } else if (\n link.rel.includes('/relations/') ||\n link.rel.includes('adturi')\n ) {\n actions.push(link);\n } else {\n navigation.push(link);\n }\n }\n\n return { navigation, actions, self };\n}\n","/**\n * PageRenderer - Framework component that renders PageResult\n *\n * Handles:\n * - Header with title/icon\n * - Page content\n * - Menu navigation with keyboard\n * - Footer\n */\n\nimport { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { PageResult, MenuItem } from './types';\n\ninterface PageRendererProps {\n result: PageResult;\n onNavigate: (url: string) => void;\n onBack: () => void;\n onAction?: (key: string) => void;\n}\n\n/**\n * Render a single menu item\n */\nfunction MenuItemRow({\n item,\n isSelected,\n}: {\n item: MenuItem;\n isSelected: boolean;\n}) {\n const prefix = isSelected ? '❯ ' : ' ';\n\n return (\n <Text color={isSelected ? 'cyan' : undefined}>\n {prefix}\n {item.icon && `${item.icon} `}\n {item.label}\n {item.status && (\n <Text color={item.status.color} dimColor={!isSelected}>\n {' '}\n [{item.status.text}]\n </Text>\n )}\n {item.info && <Text dimColor> {item.info}</Text>}\n </Text>\n );\n}\n\n/**\n * PageRenderer component\n */\nexport function PageRenderer({\n result,\n onNavigate,\n onBack,\n onAction,\n}: PageRendererProps): React.ReactNode {\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n // Handle keyboard input\n useInput((input, key) => {\n if (key.upArrow) {\n setSelectedIndex((i) => Math.max(0, i - 1));\n } else if (key.downArrow) {\n setSelectedIndex((i) => Math.min(result.menu.length - 1, i + 1));\n } else if (key.return) {\n const item = result.menu[selectedIndex];\n if (item.isBack) {\n onBack();\n } else if (item.href) {\n onNavigate(item.href);\n } else if (onAction) {\n onAction(item.key);\n }\n } else if (input === 'o' || input === 'O') {\n // Open XML in VS Code\n onAction?.('openXml');\n } else if (input === 'e' || input === 'E') {\n // Open in Eclipse ADT\n onAction?.('openAdt');\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header */}\n <Box\n borderStyle=\"round\"\n borderColor={result.color || 'cyan'}\n paddingX={2}\n marginBottom={1}\n >\n <Text bold color={result.color || 'cyan'}>\n {result.icon && `${result.icon} `}\n {result.title}\n </Text>\n {result.subtitle && <Text dimColor> ({result.subtitle})</Text>}\n </Box>\n\n {/* Content */}\n <Box flexDirection=\"column\" marginBottom={1}>\n {result.content}\n </Box>\n\n {/* Menu */}\n <Box flexDirection=\"column\">\n {result.menu.map((item, i) => (\n <MenuItemRow\n key={item.key}\n item={item}\n isSelected={i === selectedIndex}\n />\n ))}\n </Box>\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text dimColor>\n {result.footer || '[↑↓] navigate | [Enter] select'}\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Transport Request/Task Loader\n *\n * Uses adt-contracts for type-safe XML parsing.\n */\n\nimport {\n transportmanagmentSingle,\n type TransportResponse,\n} from '@abapify/adt-contracts';\n\n// Re-export the schema for type inference\nexport { transportmanagmentSingle as schema };\n\n// Use type from contracts package\ntype TransportRoot = TransportResponse;\n\n// Extract nested types - TransportResponse has root.request structure\nexport type Request = NonNullable<\n NonNullable<TransportRoot['root']>['request']\n>;\nexport type Task = NonNullable<Request['task']>[number];\nexport type AbapObject = NonNullable<Task['abap_object']>[number];\n\n/**\n * Parsed transport data with computed properties\n */\nexport interface TransportData {\n /** Whether this is a task (vs request) */\n isTask: boolean;\n /** Transport/Task number */\n number: string;\n /** Parent request number (for tasks) */\n parent?: string;\n /** Owner user ID */\n owner: string;\n /** Description */\n desc: string;\n /** Transport type */\n type: string;\n /** Status code (D=Modifiable, R=Released, O=Protected) */\n status: string;\n /** Status text */\n statusText: string;\n /** Target system */\n target: string;\n /** Target description */\n targetDesc: string;\n /** Child tasks (for requests) */\n tasks: TaskInfo[];\n /** Objects (for tasks) */\n objects: ObjectInfo[];\n /** Raw parsed data */\n raw: TransportRoot;\n}\n\nexport interface TaskInfo {\n number: string;\n owner: string;\n desc: string;\n status: string;\n statusText: string;\n uri: string;\n}\n\nexport interface ObjectInfo {\n pgmid: string;\n type: string;\n name: string;\n info: string;\n lockStatus: string;\n uri?: string;\n}\n\n/**\n * Load and parse transport request/task XML\n */\nexport function load(xml: string): TransportData {\n const parsed = transportmanagmentSingle.parse(xml);\n return transformToTransportData(parsed);\n}\n\n/**\n * Transform parsed XSD data to TransportData\n */\nfunction transformToTransportData(data: TransportRoot): TransportData {\n const request = data.root?.request;\n\n if (!request) {\n throw new Error('No request element found in transport data');\n }\n\n // Check if this is a task view (has parent) or request view\n const isTask = !!request.parent;\n\n // Extract tasks\n const tasks: TaskInfo[] = [];\n if (request.task && !isTask) {\n const taskArray = Array.isArray(request.task)\n ? request.task\n : [request.task];\n for (const task of taskArray) {\n tasks.push({\n number: task.number ?? '',\n owner: task.owner ?? '',\n desc: task.desc ?? '',\n status: task.status ?? '',\n statusText: task.status_text ?? '',\n uri: task.uri ?? '',\n });\n }\n }\n\n // Extract objects (from task's abap_object)\n const objects: ObjectInfo[] = [];\n if (request.task && isTask) {\n // When viewing a task, the task element contains objects\n const taskArray = Array.isArray(request.task)\n ? request.task\n : [request.task];\n for (const task of taskArray) {\n if (task.abap_object) {\n const objArray = Array.isArray(task.abap_object)\n ? task.abap_object\n : [task.abap_object];\n for (const obj of objArray) {\n objects.push({\n pgmid: obj.pgmid ?? '',\n type: obj.type ?? '',\n name: obj.name ?? '',\n info: obj.obj_info ?? obj.obj_desc ?? '',\n lockStatus: obj.lock_status ?? '',\n uri: obj.uri,\n });\n }\n }\n }\n }\n\n return {\n isTask,\n number: request.number ?? '',\n parent: request.parent,\n owner: request.owner ?? '',\n desc: request.desc ?? '',\n type: request.type ?? '',\n status: request.status ?? '',\n statusText: request.status_text ?? '',\n target: request.target ?? '',\n targetDesc: request.target_desc ?? '',\n tasks,\n objects,\n raw: data,\n };\n}\n","/**\n * Transport Request/Task Page\n *\n * Returns PageResult for framework-driven rendering.\n * Uses schema-driven parsing via [slug].loader.ts\n */\n\nimport { Box, Text } from 'ink';\nimport type {\n PageProps,\n PageResult,\n MenuItem,\n} from '../../../../../../lib/types';\nimport { load } from './[slug].loader';\n\n/**\n * Get status color\n */\nfunction getStatusColor(status: string): string {\n switch (status) {\n case 'D':\n return 'yellow'; // Modifiable\n case 'R':\n return 'green'; // Released\n case 'O':\n return 'cyan'; // Protected\n default:\n return 'white';\n }\n}\n\n/**\n * Transport Page - returns PageResult for framework rendering\n */\nexport function transportPage({\n url: _url,\n response,\n}: PageProps): PageResult | null {\n // Parse transport data\n let transport;\n try {\n transport = load(response.raw);\n } catch (_e) {\n return null;\n }\n\n // Build menu items\n const menu: MenuItem[] = [\n { key: 'back', label: 'Back', icon: '←', isBack: true },\n ];\n\n // Add parent link for tasks\n if (transport.isTask && transport.parent) {\n menu.push({\n key: 'parent',\n label: 'Go to Parent Request',\n icon: '⬆️',\n href: `/sap/bc/adt/cts/transportrequests/${transport.parent}`,\n });\n }\n\n // Add tasks (for requests)\n for (const task of transport.tasks) {\n menu.push({\n key: task.number,\n label: `${task.number} - ${task.desc || '(no desc)'}`,\n icon: '📝',\n href: task.uri,\n info: `@${task.owner}`,\n status: { text: task.statusText, color: getStatusColor(task.status) },\n });\n }\n\n // Add objects (for tasks)\n for (const obj of transport.objects) {\n const lockIcon = obj.lockStatus === 'X' ? '🔒' : '📦';\n menu.push({\n key: `${obj.pgmid}-${obj.name}`,\n label: `${obj.type} ${obj.name}`,\n icon: lockIcon,\n href: obj.uri,\n info: obj.uri ? undefined : '(no link)',\n });\n }\n\n // Add actions from links\n const actions = [\n { rel: 'consistencycheck', label: 'Consistency Check', icon: '🔍' },\n { rel: 'newreleasejobs', label: 'Release', icon: '🚀' },\n { rel: 'transportchecks', label: 'Transport Checks', icon: '✅' },\n ];\n\n for (const action of actions) {\n const link = response.links.find((l) => l.rel.includes(action.rel));\n if (link) {\n menu.push({\n key: action.rel,\n label: action.label,\n icon: action.icon,\n href: link.href,\n });\n }\n }\n\n // Build content\n const content = (\n <Box flexDirection=\"column\">\n <Text>\n <Text bold>Description:</Text> {transport.desc || '(no description)'}\n </Text>\n <Text>\n <Text bold>Owner:</Text> {transport.owner}\n </Text>\n <Text>\n <Text bold>Type:</Text> {transport.type}\n </Text>\n <Text>\n <Text bold>Status:</Text>{' '}\n <Text color={getStatusColor(transport.status)}>\n {transport.statusText} ({transport.status})\n </Text>\n </Text>\n {transport.target && (\n <Text>\n <Text bold>Target:</Text> {transport.target}{' '}\n {transport.targetDesc && `(${transport.targetDesc})`}\n </Text>\n )}\n {transport.tasks.length > 0 && (\n <Box marginTop={1}>\n <Text bold color=\"yellow\">\n 📋 Tasks ({transport.tasks.length}):\n </Text>\n </Box>\n )}\n {transport.objects.length > 0 && (\n <Box marginTop={1}>\n <Text bold color=\"cyan\">\n 📦 Objects ({transport.objects.length}):\n </Text>\n </Box>\n )}\n </Box>\n );\n\n const isTask = transport.isTask;\n return {\n title: `${isTask ? 'Task' : 'Transport Request'}: ${transport.number}`,\n icon: isTask ? '�' : '�',\n color: isTask ? 'yellow' : 'cyan',\n subtitle:\n isTask && transport.parent ? `Parent: ${transport.parent}` : undefined,\n content,\n menu,\n footer: '[o] XML in VS Code | [e] open in Eclipse ADT',\n };\n}\n\n// Default export for file-based routing\nexport default transportPage;\n","/**\n * Auto-generated route manifest\n * DO NOT EDIT - Generated by scripts/generate-routes.ts\n */\n\nimport { default as Page0 } from './sap/bc/adt/cts/transportrequests/[slug]';\nimport type { PageComponent } from '../lib/types';\n\nexport interface Route {\n pattern: string;\n regex: RegExp;\n page: PageComponent;\n}\n\nexport const routes: Route[] = [\n {\n pattern: '/sap/bc/adt/cts/transportrequests/:slug',\n regex: new RegExp('^/sap/bc/adt/cts/transportrequests/([^/]+)$'),\n page: Page0,\n },\n];\n\n/**\n * Match URL to route\n */\nexport function matchRoute(url: string): Route | null {\n for (const route of routes) {\n if (route.regex.test(url)) {\n return route;\n }\n }\n return null;\n}\n","/**\n * Generic Page Component\n *\n * Fallback page for unknown endpoints - shows payload + links.\n * Returns PageResult for framework-driven rendering.\n */\n\n// React import not needed with JSX transform\nimport { Box, Text } from 'ink';\nimport type { PageProps, PageResult, MenuItem } from '../lib/types';\nimport { getActionName } from '../lib/parser';\n\ninterface SummaryItem {\n key: string;\n value: string;\n}\n\n/**\n * Generic page - returns PageResult for framework rendering\n */\nexport function genericPage({ url, response }: PageProps): PageResult {\n // Extract summary from data\n const summary = extractSummary(response.data);\n\n // Build menu items from links\n const menu: MenuItem[] = [\n { key: 'back', label: 'Back', icon: '←', isBack: true },\n ];\n\n for (const link of response.links) {\n const title = link.title || getActionName(link.rel);\n\n // Make path relative/shorter for display\n let displayPath = link.href;\n const currentBase = url.split('/').slice(0, -1).join('/');\n if (link.href.startsWith(currentBase)) {\n displayPath = '.' + link.href.slice(currentBase.length);\n } else if (link.href.startsWith('/sap/bc/adt/')) {\n displayPath = link.href.replace('/sap/bc/adt/', '/');\n }\n if (displayPath.length > 40) {\n displayPath = '...' + displayPath.slice(-37);\n }\n\n menu.push({\n key: link.href,\n label: title,\n icon: '🔗',\n href: link.href,\n info: displayPath,\n });\n }\n\n // Build content\n const content = (\n <Box flexDirection=\"column\">\n <Text dimColor>URL: {url}</Text>\n <Box marginTop={1} flexDirection=\"column\">\n {summary.length > 0 ? (\n summary.map((item, i) => (\n <Text key={i}>\n <Text color=\"yellow\">{item.key}:</Text> {item.value}\n </Text>\n ))\n ) : (\n <Text dimColor>No summary available</Text>\n )}\n </Box>\n </Box>\n );\n\n return {\n title: `${response.namespace || 'unknown'}:${response.rootElement || 'response'}`,\n icon: '📄',\n color: 'cyan',\n content,\n menu,\n footer: `[o] XML | [e] Eclipse ADT | ${response.links.length} links`,\n };\n}\n\n/**\n * Extract key fields for summary display\n */\nfunction extractSummary(data: Record<string, unknown>): SummaryItem[] {\n const summary: SummaryItem[] = [];\n const seen = new Set<string>();\n\n function extract(obj: unknown, prefix = ''): void {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n obj.forEach((item) => extract(item, prefix));\n return;\n }\n\n const record = obj as Record<string, unknown>;\n for (const [key, value] of Object.entries(record)) {\n // Skip links and xml declaration\n if (key.includes('link') || key === '?xml') continue;\n\n // Extract interesting attributes (those starting with @_)\n if (\n (key.startsWith('@_') && typeof value === 'string') ||\n typeof value === 'number'\n ) {\n const cleanKey = key.replace('@_', '').replace(/^\\w+:/, '');\n // Skip duplicates and uninteresting fields\n if (\n seen.has(cleanKey) ||\n cleanKey === 'version' ||\n cleanKey === 'encoding'\n )\n continue;\n seen.add(cleanKey);\n\n // Limit to important fields\n const important = [\n 'number',\n 'owner',\n 'desc',\n 'status',\n 'status_text',\n 'type',\n 'target',\n 'name',\n 'uri',\n ];\n if (important.some((f) => cleanKey.includes(f))) {\n summary.push({ key: cleanKey, value: String(value) });\n }\n }\n\n // Recurse into nested objects\n if (typeof value === 'object') {\n extract(value, key);\n }\n }\n }\n\n extract(data);\n return summary.slice(0, 8); // Limit to 8 items\n}\n\n// removeLinks function removed - was unused\n","/**\n * Navigator Component\n *\n * Main entry point - renders pages using the framework.\n * Pages return PageResult, Navigator handles rendering.\n */\n\nimport { useState, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport TextInput from 'ink-text-input';\nimport { writeFileSync, existsSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { exec, execFile } from 'node:child_process';\nimport { NavigationProvider, useNavigation } from './lib/context';\nimport { parseResponse } from './lib/parser';\nimport { PageRenderer } from './lib/PageRenderer';\nimport { matchRoute } from './pages/_routes';\nimport { genericPage } from './pages/GenericPage';\nimport type { FetchFn, PageComponent, PageResult } from './lib/types';\n\ninterface NavigatorProps {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function */\n fetch: FetchFn;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n}\n\n/**\n * Open raw XML in IDE (VS Code)\n */\nfunction openXmlInIde(xml: string, url: string): void {\n const safeName = url.replaceAll(/[^a-zA-Z0-9]/g, '_').slice(-50);\n const filename = `adt_${safeName}.xml`;\n const filepath = join(tmpdir(), filename);\n writeFileSync(filepath, xml, 'utf-8');\n exec(`code \"${filepath}\"`, (error) => {\n if (error) {\n exec(`xdg-open \"${filepath}\"`);\n }\n });\n}\n\n/**\n * Resolve absolute path to a launcher binary from an allow-list of known\n * install locations. Prevents PATH-hijack (S4036) by avoiding bare-name\n * lookups when an absolute path is available. Falls back to the bare name\n * only if none of the known paths exist, so packaged distributions with\n * non-standard layouts still function.\n */\nfunction resolveLauncher(\n candidates: readonly string[],\n fallbackName: string,\n): string {\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return fallbackName;\n}\n\nconst XDG_OPEN = resolveLauncher(\n ['/usr/bin/xdg-open', '/usr/local/bin/xdg-open'],\n 'xdg-open',\n);\nconst OPEN_MAC = resolveLauncher(\n ['/usr/bin/open', '/usr/local/bin/open'],\n 'open',\n);\n\n/**\n * Open in Eclipse ADT\n * Format: adt://[system]/[path]\n * @see https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/opening-adt-links\n */\nfunction openInAdt(systemName: string, url: string): void {\n const adtUrl = `adt://${systemName}${url}`;\n // Use execFile (arg array, no shell) to avoid shell-command injection\n // via systemName/url. Try xdg-open (Linux), fall back to open (macOS).\n // Paths resolved above via allow-list to prevent PATH-hijack (S4036).\n execFile(XDG_OPEN, [adtUrl], (error) => {\n if (error) {\n execFile(OPEN_MAC, [adtUrl], (err2) => {\n if (err2) {\n console.error('Failed to open ADT link:', err2.message);\n }\n });\n }\n });\n}\n\n/**\n * Inner component that uses navigation context\n */\nfunction NavigatorInner({ systemName }: { systemName?: string }) {\n const { current, loading, error, navigate, back } = useNavigation();\n\n // Get page result\n const pageResult = useMemo<PageResult | null>(() => {\n if (!current) return null;\n\n // Try file-based route matching first\n const fileRoute = matchRoute(current.url);\n const pageFn: PageComponent = fileRoute?.page ?? genericPage;\n\n return pageFn({ url: current.url, response: current.response });\n }, [current]);\n\n // Handle actions\n const handleAction = (key: string) => {\n if (key === 'openXml' && current) {\n openXmlInIde(current.response.raw, current.url);\n } else if (key === 'openAdt' && current && systemName) {\n openInAdt(systemName, current.url);\n }\n };\n\n if (loading) {\n return (\n <Box padding={1}>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n <Text> Loading...</Text>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box padding={1} flexDirection=\"column\">\n <Text color=\"red\">❌ Error: {error}</Text>\n <Text dimColor>Press Ctrl+C to exit</Text>\n </Box>\n );\n }\n\n if (!current) {\n return <UrlPrompt onSubmit={navigate} />;\n }\n\n if (!pageResult) {\n return (\n <Box padding={1}>\n <Text dimColor>No content loaded</Text>\n </Box>\n );\n }\n\n return (\n <PageRenderer\n result={pageResult}\n onNavigate={navigate}\n onBack={back}\n onAction={handleAction}\n />\n );\n}\n\n/**\n * Main Navigator component\n */\nexport function Navigator({\n startUrl,\n fetch,\n systemName,\n}: NavigatorProps): React.ReactNode {\n return (\n <NavigationProvider\n fetch={fetch}\n parseResponse={parseResponse}\n initialUrl={startUrl}\n >\n <NavigatorInner systemName={systemName} />\n </NavigationProvider>\n );\n}\n\n/**\n * URL input prompt component\n */\nfunction UrlPrompt({ onSubmit }: { onSubmit: (url: string) => void }) {\n const [url, setUrl] = useState('');\n\n const handleSubmit = () => {\n if (url.trim()) {\n onSubmit(url.trim());\n }\n };\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"cyan\" bold>\n ADT TUI - Hypermedia Navigator\n </Text>\n <Box marginTop={1}>\n <Text>Enter URL: </Text>\n <TextInput value={url} onChange={setUrl} onSubmit={handleSubmit} />\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Example: /sap/bc/adt/cts/transportrequests/TRLK900001\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Main App Component\n *\n * Entry point for the TUI application.\n */\n\nimport { useState, useEffect } from 'react';\nimport { Navigator } from './Navigator';\nimport type { FetchFn } from './lib/types';\nimport type { Router } from './lib/router';\n\nexport interface AppProps {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function for making HTTP requests */\n fetch: FetchFn;\n /** Optional custom router */\n router?: Router;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n}\n\n/**\n * Main TUI Application\n */\nexport function App({\n startUrl,\n fetch,\n router: _router,\n systemName,\n}: AppProps): React.ReactNode {\n const [, setResizeKey] = useState(0);\n\n // Handle terminal resize - just trigger re-render, don't clear\n useEffect(() => {\n const handleResize = () => {\n setResizeKey((k) => k + 1);\n };\n\n process.stdout.on('resize', handleResize);\n return () => {\n process.stdout.off('resize', handleResize);\n };\n }, []);\n\n return (\n <Navigator startUrl={startUrl} fetch={fetch} systemName={systemName} />\n );\n}\n","/**\n * Run TUI Application\n *\n * Helper to render the TUI and wait for exit.\n */\n\n// React import not needed with JSX transform\nimport { render } from 'ink';\nimport { App } from './App';\nimport type { FetchFn } from './lib/types';\nimport type { Router } from './lib/router';\n\nexport interface RunOptions {\n /** Optional starting URL - if not provided, shows prompt */\n startUrl?: string;\n /** Fetch function for making HTTP requests */\n fetch: FetchFn;\n /** Optional custom router */\n router?: Router;\n /** SAP system name for ADT links (e.g., 'TRL', 'NPL') */\n systemName?: string;\n /** Called when app exits */\n onExit?: () => void;\n}\n\n/**\n * Run the TUI application\n *\n * @returns Promise that resolves when the app exits\n */\nexport async function run(options: RunOptions): Promise<void> {\n const { onExit, ...appProps } = options;\n\n // Clear terminal on start\n console.clear();\n\n const { waitUntilExit, clear } = render(<App {...appProps} />);\n\n await waitUntilExit();\n\n // Cleanup\n clear();\n onExit?.();\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abapify/adt-tui",
3
- "version": "0.4.17",
3
+ "version": "0.4.19",
4
4
  "description": "Terminal UI components for ADT - page-based navigation with Ink",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -17,7 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "dependencies": {
20
- "@abapify/adt-contracts": "0.4.17",
20
+ "@abapify/adt-contracts": "0.4.19",
21
21
  "fast-xml-parser": "^5.3.1",
22
22
  "ink": "5.1.0",
23
23
  "ink-select-input": "^6.0.0",
@@ -29,7 +29,7 @@
29
29
  "@types/react": "18.3.0"
30
30
  },
31
31
  "peerDependencies": {
32
- "@abapify/adt-client": "0.4.16"
32
+ "@abapify/adt-client": "0.4.19"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",