@abapify/adt-tui 0.4.1 → 0.4.4
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 +8 -31
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React$1, { ReactNode } from "react";
|
|
2
|
-
|
|
3
2
|
//#region src/lib/types.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Core types for ADT TUI
|
|
@@ -144,7 +143,7 @@ interface RunOptions {
|
|
|
144
143
|
fetch: FetchFn;
|
|
145
144
|
/** Optional custom router */
|
|
146
145
|
router?: Router;
|
|
147
|
-
/** SAP system name for ADT links (e.g., '
|
|
146
|
+
/** SAP system name for ADT links (e.g., 'TRL', 'NPL') */
|
|
148
147
|
systemName?: string;
|
|
149
148
|
/** Called when app exits */
|
|
150
149
|
onExit?: () => void;
|
|
@@ -164,18 +163,13 @@ interface AppProps {
|
|
|
164
163
|
fetch: FetchFn;
|
|
165
164
|
/** Optional custom router */
|
|
166
165
|
router?: Router;
|
|
167
|
-
/** SAP system name for ADT links (e.g., '
|
|
166
|
+
/** SAP system name for ADT links (e.g., 'TRL', 'NPL') */
|
|
168
167
|
systemName?: string;
|
|
169
168
|
}
|
|
170
169
|
/**
|
|
171
170
|
* Main TUI Application
|
|
172
171
|
*/
|
|
173
|
-
declare function App({
|
|
174
|
-
startUrl,
|
|
175
|
-
fetch,
|
|
176
|
-
router: _router,
|
|
177
|
-
systemName
|
|
178
|
-
}: AppProps): React.ReactNode;
|
|
172
|
+
declare function App({ startUrl, fetch, router: _router, systemName }: AppProps): React.ReactNode;
|
|
179
173
|
//#endregion
|
|
180
174
|
//#region src/Navigator.d.ts
|
|
181
175
|
interface NavigatorProps {
|
|
@@ -183,17 +177,13 @@ interface NavigatorProps {
|
|
|
183
177
|
startUrl?: string;
|
|
184
178
|
/** Fetch function */
|
|
185
179
|
fetch: FetchFn;
|
|
186
|
-
/** SAP system name for ADT links (e.g., '
|
|
180
|
+
/** SAP system name for ADT links (e.g., 'TRL', 'NPL') */
|
|
187
181
|
systemName?: string;
|
|
188
182
|
}
|
|
189
183
|
/**
|
|
190
184
|
* Main Navigator component
|
|
191
185
|
*/
|
|
192
|
-
declare function Navigator({
|
|
193
|
-
startUrl,
|
|
194
|
-
fetch,
|
|
195
|
-
systemName
|
|
196
|
-
}: NavigatorProps): React.ReactNode;
|
|
186
|
+
declare function Navigator({ startUrl, fetch, systemName }: NavigatorProps): React.ReactNode;
|
|
197
187
|
//#endregion
|
|
198
188
|
//#region src/lib/PageRenderer.d.ts
|
|
199
189
|
interface PageRendererProps {
|
|
@@ -205,12 +195,7 @@ interface PageRendererProps {
|
|
|
205
195
|
/**
|
|
206
196
|
* PageRenderer component
|
|
207
197
|
*/
|
|
208
|
-
declare function PageRenderer({
|
|
209
|
-
result,
|
|
210
|
-
onNavigate,
|
|
211
|
-
onBack,
|
|
212
|
-
onAction
|
|
213
|
-
}: PageRendererProps): React.ReactNode;
|
|
198
|
+
declare function PageRenderer({ result, onNavigate, onBack, onAction }: PageRendererProps): React.ReactNode;
|
|
214
199
|
//#endregion
|
|
215
200
|
//#region src/lib/context.d.ts
|
|
216
201
|
interface NavigationContextValue {
|
|
@@ -238,12 +223,7 @@ interface NavigationProviderProps {
|
|
|
238
223
|
/** Initial URL to load */
|
|
239
224
|
initialUrl?: string;
|
|
240
225
|
}
|
|
241
|
-
declare function NavigationProvider({
|
|
242
|
-
children,
|
|
243
|
-
fetch,
|
|
244
|
-
parseResponse,
|
|
245
|
-
initialUrl
|
|
246
|
-
}: NavigationProviderProps): React$1.ReactNode;
|
|
226
|
+
declare function NavigationProvider({ children, fetch, parseResponse, initialUrl }: NavigationProviderProps): React$1.ReactNode;
|
|
247
227
|
/**
|
|
248
228
|
* Hook to access navigation context
|
|
249
229
|
*/
|
|
@@ -271,10 +251,7 @@ declare function categorizeLinks(links: HypermediaLink[]): {
|
|
|
271
251
|
/**
|
|
272
252
|
* Generic page - returns PageResult for framework rendering
|
|
273
253
|
*/
|
|
274
|
-
declare function genericPage({
|
|
275
|
-
url,
|
|
276
|
-
response
|
|
277
|
-
}: PageProps): PageResult;
|
|
254
|
+
declare function genericPage({ url, response }: PageProps): PageResult;
|
|
278
255
|
//#endregion
|
|
279
256
|
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 };
|
|
280
257
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -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":"
|
|
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"}
|
package/dist/index.mjs
CHANGED
|
@@ -2,10 +2,10 @@ import { Box, Text, render, useInput } from "ink";
|
|
|
2
2
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import Spinner from "ink-spinner";
|
|
4
4
|
import TextInput from "ink-text-input";
|
|
5
|
-
import { existsSync, writeFileSync } from "fs";
|
|
6
|
-
import { tmpdir } from "os";
|
|
7
|
-
import { join } from "path";
|
|
8
|
-
import { exec, execFile } from "child_process";
|
|
5
|
+
import { existsSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { exec, execFile } from "node:child_process";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
import { XMLParser } from "fast-xml-parser";
|
|
11
11
|
import { transportmanagmentSingle } from "@abapify/adt-contracts";
|
|
@@ -720,8 +720,8 @@ function NavigatorInner({ systemName }) {
|
|
|
720
720
|
children: "Press Ctrl+C to exit"
|
|
721
721
|
})]
|
|
722
722
|
});
|
|
723
|
-
if (!current
|
|
724
|
-
if (!
|
|
723
|
+
if (!current) return /* @__PURE__ */ jsx(UrlPrompt, { onSubmit: navigate });
|
|
724
|
+
if (!pageResult) return /* @__PURE__ */ jsx(Box, {
|
|
725
725
|
padding: 1,
|
|
726
726
|
children: /* @__PURE__ */ jsx(Text, {
|
|
727
727
|
dimColor: true,
|
|
@@ -775,7 +775,7 @@ function UrlPrompt({ onSubmit }) {
|
|
|
775
775
|
marginTop: 1,
|
|
776
776
|
children: /* @__PURE__ */ jsx(Text, {
|
|
777
777
|
dimColor: true,
|
|
778
|
-
children: "Example: /sap/bc/adt/cts/transportrequests/
|
|
778
|
+
children: "Example: /sap/bc/adt/cts/transportrequests/TRLK900001"
|
|
779
779
|
})
|
|
780
780
|
})
|
|
781
781
|
]
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 'fs';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { exec, execFile } from '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., 'S0D', '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 && !loading) {\n return <UrlPrompt onSubmit={navigate} />;\n }\n\n if (!current || !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/S0DK900001\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., 'S0D', '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., 'S0D', '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.
|
|
3
|
+
"version": "0.4.4",
|
|
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.
|
|
20
|
+
"@abapify/adt-contracts": "0.4.4",
|
|
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.
|
|
32
|
+
"@abapify/adt-client": "0.4.4"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|