@saptools/service-flow 0.1.0 โ†’ 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,38 +1,250 @@
1
- # @saptools/service-flow
1
+ <div align="center">
2
2
 
3
- `service-flow` is a standalone npm CLI for SAP CAP/CDS TypeScript workspaces made of many independent Git repositories. It statically indexes repositories, stores CAP facts in SQLite, links service-to-service calls across repository boundaries, and traces one exposed operation through handlers, helper packages, database access, remote OData calls, external HTTP calls, and async channels.
3
+ # ๐Ÿงญ `@saptools/service-flow`
4
4
 
5
- ## Installation
5
+ **Trace SAP CAP service-to-service flows across multi-repository TypeScript workspaces.**
6
+
7
+ Index independent Git repositories, persist CAP/CDS facts in SQLite, resolve cross-repo service calls, and explain one operation end-to-end through handlers, helper packages, local database access, remote OData calls, external HTTP calls, and async channels โ€” without running the applications.
8
+
9
+ [![npm version](https://img.shields.io/npm/v/@saptools/service-flow.svg?style=flat&color=CB3837&logo=npm)](https://www.npmjs.com/package/@saptools/service-flow)
10
+ [![license](https://img.shields.io/npm/l/@saptools/service-flow.svg?style=flat&color=blue)](./LICENSE)
11
+ [![node](https://img.shields.io/node/v/@saptools/service-flow.svg?style=flat&color=339933&logo=node.js&logoColor=white)](https://nodejs.org)
12
+ [![install size](https://packagephobia.com/badge?p=@saptools/service-flow)](https://packagephobia.com/result?p=@saptools/service-flow)
13
+ [![types](https://img.shields.io/npm/types/@saptools/service-flow.svg?style=flat&color=3178C6&logo=typescript&logoColor=white)](https://www.typescriptlang.org)
14
+
15
+ [Install](#-install) โ€ข [Quick Start](#-quick-start) โ€ข [CLI](#-cli) โ€ข [FAQ](#-faq)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## โœจ Features
22
+
23
+ - ๐Ÿงญ **Cross-repository CAP tracing** โ€” starts from a repo, service, operation path, operation name, or handler and follows the indexed flow across workspace boundaries
24
+ - ๐Ÿงฉ **Static CAP/CDS indexing** โ€” extracts services, actions, functions, events, handler classes, decorator metadata, handler registrations, generated constants, and package-level `cds.requires`
25
+ - ๐Ÿ”— **Service-to-service linking** โ€” resolves `cds.connect.to(...)`, `remote.send(...)`, `cds.services.*` style calls, helper package imports, dynamic candidates, and unresolved evidence into graph edges
26
+ - ๐Ÿ—„๏ธ **SQLite-backed workspace cache** โ€” stores deterministic facts under `.service-flow/service-flow.db` so large workspaces can be queried repeatedly without reparsing everything
27
+ - ๐Ÿง  **Dynamic edge support** โ€” preserves parameterized destinations and service paths such as `svc_${objectCode}_process`, then lets traces apply runtime `--var key=value` values
28
+ - ๐Ÿ“Š **Multiple output modes** โ€” renders human-readable tables, JSON for automation, and Mermaid diagrams for architecture docs
29
+ - ๐Ÿฉบ **Diagnostics-first workflow** โ€” records parse/index issues and exposes them through `service-flow doctor` instead of hiding partial analysis
30
+ - ๐Ÿ” **Secret-aware summaries** โ€” redacts sensitive keys in persisted summaries and CLI output while keeping useful source evidence
31
+ - ๐Ÿ“ฆ **Standalone CLI & typed package** โ€” ships as an npm CLI with TypeScript definitions for integration into other saptools workflows
32
+
33
+ ---
34
+
35
+ ## ๐Ÿ“ฆ Install
6
36
 
7
37
  ```bash
38
+ # Global CLI
8
39
  npm install -g @saptools/service-flow
40
+
41
+ # Or as a dependency
42
+ npm install @saptools/service-flow
43
+ # pnpm add @saptools/service-flow
44
+ # yarn add @saptools/service-flow
9
45
  ```
10
46
 
11
- ## Quick start
47
+ > [!NOTE]
48
+ > Requires **Node.js โ‰ฅ 20**. The analyzer is static: it reads files and package metadata, but it does not start CAP services, connect to SAP BTP, or execute application code.
49
+
50
+ ---
51
+
52
+ ## ๐Ÿš€ Quick Start
12
53
 
13
54
  ```bash
55
+ # 1. Initialize a workspace that contains many CAP/helper Git repositories
14
56
  service-flow init /path/to/workspace
57
+
58
+ # 2. Index source facts from every discovered repository
15
59
  service-flow index --workspace /path/to/workspace
60
+
61
+ # 3. Resolve cross-repository edges after all repos have been indexed
16
62
  service-flow link --workspace /path/to/workspace
63
+
64
+ # 4. Trace one operation as a readable table
17
65
  service-flow trace --workspace /path/to/workspace --repo facade-service --operation doWork
66
+
67
+ # 5. Generate a Mermaid diagram for documentation
18
68
  service-flow graph --workspace /path/to/workspace --service /FacadeService --path /doWork --format mermaid
69
+
70
+ # 6. Check parse/index diagnostics
71
+ service-flow doctor --workspace /path/to/workspace
72
+ ```
73
+
74
+ After `init`, the workspace configuration and SQLite database live below the selected workspace by default. Run `index` whenever source changes, then run `link` to rebuild the graph edges used by `trace` and `graph`.
75
+
76
+ ---
77
+
78
+ ## ๐Ÿงฐ CLI
79
+
80
+ ### ๐Ÿ `service-flow init <workspace>`
81
+
82
+ Discover nested Git repositories, create workspace state, save configuration, and record repository metadata.
83
+
84
+ ```bash
85
+ service-flow init /path/to/workspace
86
+ service-flow init /path/to/workspace --db /custom/path/service-flow.db
87
+ service-flow init /path/to/workspace --ignore node_modules dist coverage .git
88
+ ```
89
+
90
+ | Flag | Description |
91
+ | --- | --- |
92
+ | `--db <path>` | Store the SQLite database at a custom path instead of `<workspace>/.service-flow/service-flow.db` |
93
+ | `--ignore <pattern...>` | Override the default discovery ignore patterns |
94
+
95
+ ### ๐Ÿ”Ž `service-flow index`
96
+
97
+ Parse repository files and persist CAP facts. Use `--repo` for a focused refresh or `--force` when you want to re-index unchanged files.
98
+
99
+ ```bash
100
+ service-flow index --workspace /path/to/workspace
101
+ service-flow index --workspace /path/to/workspace --repo facade-service
102
+ service-flow index --workspace /path/to/workspace --repo identity-service --force
103
+ ```
104
+
105
+ | Flag | Description |
106
+ | --- | --- |
107
+ | `--workspace <path>` | Workspace root or a path that can load the saved workspace configuration |
108
+ | `--repo <name>` | Index only one repository by discovered repository name |
109
+ | `--force` | Re-index even when file hashes indicate nothing changed |
110
+ | `--concurrency <n>` | Reserved for future parallel indexing; currently defaults to `1` |
111
+
112
+ ### ๐Ÿ”— `service-flow link`
113
+
114
+ Resolve indexed outbound calls after repositories have been indexed. This rebuilds the `graph_edges` table for the workspace.
115
+
116
+ ```bash
117
+ service-flow link --workspace /path/to/workspace
118
+ service-flow link --workspace /path/to/workspace --force
119
+ ```
120
+
121
+ | Flag | Description |
122
+ | --- | --- |
123
+ | `--workspace <path>` | Workspace to link |
124
+ | `--force` | Accepted for workflow symmetry; linking always rebuilds graph edges |
125
+
126
+ ### ๐Ÿงต `service-flow trace`
127
+
128
+ Trace one starting point and render table, JSON, or Mermaid output.
129
+
130
+ ```bash
131
+ service-flow trace --workspace /path/to/workspace --repo facade-service --operation doWork
132
+ service-flow trace --workspace /path/to/workspace --service /FacadeService --path /doWork --format json
133
+ service-flow trace --workspace /path/to/workspace --handler EntryHandler --include-db --include-external --include-async
134
+ service-flow trace --workspace /path/to/workspace --repo facade-service --operation doWork --var objectCode=xx --var objectType=Thing
135
+ ```
136
+
137
+ | Flag | Description |
138
+ | --- | --- |
139
+ | `--workspace <path>` | Workspace to read |
140
+ | `--repo <name>` | Start from a repository |
141
+ | `--operation <name>` | Start from an operation/action/function name |
142
+ | `--service <path>` | Start from a CAP service path such as `/FacadeService` |
143
+ | `--path <operationPath>` | Start from an operation path such as `/doWork` |
144
+ | `--handler <name>` | Start from a handler class or handler-like selector |
145
+ | `--depth <n>` | Maximum traversal depth; defaults to `25` |
146
+ | `--format <format>` | `table`, `json`, or `mermaid`; defaults to `table` |
147
+ | `--include-external` | Include external HTTP/destination edges in traversal output |
148
+ | `--include-db` | Include local DB query edges in traversal output |
149
+ | `--include-async` | Include async publish/subscribe edges in traversal output |
150
+ | `--var <key=value>` | Apply runtime values to dynamic destinations/service paths; repeatable |
151
+
152
+ ### ๐Ÿ—บ๏ธ `service-flow graph`
153
+
154
+ Render a deeper architecture graph from the same selector model used by `trace`. Graph output includes DB, async, and external edges by default and uses depth `100`.
155
+
156
+ ```bash
157
+ service-flow graph --workspace /path/to/workspace --service /FacadeService --path /doWork
158
+ service-flow graph --workspace /path/to/workspace --repo facade-service --operation doWork --format json
159
+ ```
160
+
161
+ | Flag | Description |
162
+ | --- | --- |
163
+ | `--workspace <path>` | Workspace to read |
164
+ | `--repo <name>` | Filter/start by repository |
165
+ | `--operation <name>` | Filter/start by operation name |
166
+ | `--service <path>` | Filter/start by service path |
167
+ | `--path <operationPath>` | Filter/start by operation path |
168
+ | `--format <format>` | `mermaid` or `json`; defaults to `mermaid` |
169
+
170
+ ### ๐Ÿ“š `service-flow list ...`
171
+
172
+ Inspect indexed facts as JSON.
173
+
174
+ ```bash
175
+ service-flow list repos --workspace /path/to/workspace
176
+ service-flow list services --workspace /path/to/workspace --repo facade-service
177
+ service-flow list operations --workspace /path/to/workspace --repo facade-service --service /FacadeService
178
+ service-flow list calls --workspace /path/to/workspace --repo facade-service
179
+ ```
180
+
181
+ | Command | Description |
182
+ | --- | --- |
183
+ | `list repos` | Print discovered repositories with kind and package name |
184
+ | `list services` | Print indexed CDS services, optionally filtered by repo |
185
+ | `list operations` | Print indexed actions/functions/events, optionally filtered by repo and service |
186
+ | `list calls` | Print indexed outbound calls, optionally filtered by repo |
187
+
188
+ ### ๐Ÿ”ฌ `service-flow inspect ...`
189
+
190
+ Inspect raw indexed records for a repository or operation selector.
191
+
192
+ ```bash
193
+ service-flow inspect repo facade-service --workspace /path/to/workspace
194
+ service-flow inspect operation doWork --workspace /path/to/workspace
195
+ service-flow inspect operation /doWork --workspace /path/to/workspace
196
+ ```
197
+
198
+ | Command | Description |
199
+ | --- | --- |
200
+ | `inspect repo <name>` | Print one repository database record or `{ "error": "repo not found" }` |
201
+ | `inspect operation <selector>` | Print operations whose name or path equals the selector |
202
+
203
+ ### ๐Ÿฉบ `service-flow doctor`
204
+
205
+ Print stored diagnostics. A clean workspace prints `No diagnostics recorded`.
206
+
207
+ ```bash
19
208
  service-flow doctor --workspace /path/to/workspace
20
209
  ```
21
210
 
22
- ## Phases
211
+ ### ๐Ÿงน `service-flow clean`
23
212
 
24
- - **init** discovers nested Git repositories, creates `.service-flow/service-flow.db`, saves workspace configuration, and records repository metadata.
25
- - **index** parses each repository independently. It extracts `package.json#cds.requires`, CDS services and operations, decorator handlers, handler registrations, service bindings, outbound calls, async topics, external HTTP calls, and local database queries.
26
- - **link** resolves indexed calls after every repository has been indexed. It creates graph edges for resolved remote operations, helper package imports, dynamic candidates, async topics, local DB calls, external destinations, and unresolved calls.
27
- - **trace** starts from a repository, service path, operation, operation path, or handler selector and renders table, JSON, or Mermaid output.
213
+ Remove generated service-flow state.
28
214
 
29
- ## Supported CAP patterns
215
+ ```bash
216
+ service-flow clean --workspace /path/to/workspace --db-only
217
+ service-flow clean --workspace /path/to/workspace
218
+ ```
219
+
220
+ | Flag | Description |
221
+ | --- | --- |
222
+ | `--db-only` | Remove only the configured SQLite database |
223
+ | *(default)* | Remove the whole `.service-flow` state directory for the workspace |
224
+
225
+ ---
226
+
227
+ ## ๐Ÿงฑ What Gets Indexed
30
228
 
31
- The indexer supports CAP projects with `.cds` models, `@sap/cds` package metadata, `cds-routing-handlers` decorators, `cds.connect.to("alias")`, `remote.send({ method, path })`, `remote.send({ query })`, `cds.run(SELECT...)`, `cds.services.Service.operation()`, Event Mesh-style `emit`, `publish`, and `on`, Cloud SDK-style HTTP calls, generated constants, and thin service wrappers that import helper packages.
229
+ `service-flow` favors explainable static facts with source-file evidence and confidence scores.
32
230
 
33
- ## Dynamic edges
231
+ | Area | Examples |
232
+ | --- | --- |
233
+ | Repository metadata | nested Git repos, package name/version, dependency graph, repository kind |
234
+ | CAP model facts | `.cds` services, service paths, actions, functions, events, parameters, return types |
235
+ | Handler facts | `cds-routing-handlers` decorators, handler classes/methods, server registrations |
236
+ | Service bindings | `cds.connect.to("alias")`, aliases from `package.json#cds.requires`, destination/service path expressions |
237
+ | Outbound calls | `remote.send({ method, path })`, `remote.send({ query })`, `cds.services.Service.operation()`, service wrapper calls |
238
+ | Local data access | `cds.run(SELECT...)` and local entity query evidence |
239
+ | Async channels | Event Mesh-style `emit`, `publish`, and `on` facts |
240
+ | External calls | Cloud SDK-style HTTP/destination calls and external edge evidence |
241
+ | Generated constants | constants used to resolve service paths, operation paths, and thin helper wrappers |
34
242
 
35
- Dynamic destinations and service paths are preserved as parameterized edges:
243
+ ---
244
+
245
+ ## ๐Ÿง  Dynamic Edges
246
+
247
+ Runtime-dependent destinations and paths are preserved as parameterized evidence instead of being discarded.
36
248
 
37
249
  ```text
38
250
  destination: svc_${objectCode}_process
@@ -43,26 +255,45 @@ operationPath: /getPaths
43
255
  Pass runtime values during trace:
44
256
 
45
257
  ```bash
46
- service-flow trace --repo facade-service --operation doWork --var objectCode=xx --var objectType=Thing
258
+ service-flow trace --workspace /path/to/workspace --repo facade-service --operation doWork --var objectCode=xx --var objectType=Thing
47
259
  ```
48
260
 
49
- The trace shows both the parameterized evidence and the concrete value used for matching when a target operation exists.
261
+ When a concrete target exists after variable substitution, the trace shows both the parameterized evidence and the resolved match. When it does not, `service-flow` keeps the edge as a dynamic candidate or unresolved edge so the missing link remains visible.
262
+
263
+ ---
50
264
 
51
- ## SQLite database location
265
+ ## ๐Ÿ“ Workspace State
52
266
 
53
267
  By default, state is stored below the selected workspace:
54
268
 
55
269
  ```text
56
- /path/to/workspace/.service-flow/service-flow.db
270
+ /path/to/workspace/.service-flow/service-flow.db # SQLite fact and graph database
271
+ /path/to/workspace/.service-flow/config.json # saved workspace configuration
57
272
  ```
58
273
 
59
- Use `service-flow init /path/to/workspace --db /custom/path/service-flow.db` to override it.
274
+ Use a custom database path when the workspace is read-only or when you want to keep generated state elsewhere:
275
+
276
+ ```bash
277
+ service-flow init /path/to/workspace --db /custom/path/service-flow.db
278
+ ```
279
+
280
+ > [!IMPORTANT]
281
+ > Generated state is derived from source code and may reveal internal repository names, service names, endpoints, entity names, and call paths. Do not commit `.service-flow/` or attach the database to public tickets.
282
+
283
+ ---
284
+
285
+ ## ๐Ÿ” Security & Redaction
286
+
287
+ - The analyzer reads static source files and package metadata only.
288
+ - It does **not** execute CAP services, load `.env` files, call SAP BTP, or connect to remote systems.
289
+ - Persisted summaries and CLI output redact keys that look like credentials, including `authorization`, `cookie`, `token`, `secret`, `password`, `key`, and `credential`.
290
+ - Payload bodies are summarized for traceability; runtime payload values are not required for indexing.
60
291
 
61
- ## Security and redaction
292
+ ---
62
293
 
63
- The tool stores static source evidence and expression summaries only. It does not execute applications and does not persist runtime payload bodies. Keys matching `authorization`, `cookie`, `token`, `secret`, `password`, `key`, or `credential` are redacted in persisted summaries and CLI output.
294
+ ## ๐Ÿ“ค Output Examples
64
295
 
65
- ## Output examples
296
+ ### Table
66
297
 
67
298
  ```text
68
299
  Start: facade-service /FacadeService doWork
@@ -72,6 +303,8 @@ Step Type From To
72
303
  2 remote_action facade-service:srv/functions/Entry /IdentityService/resolveAccess srv/functions/EntryHandler.ts:10
73
304
  ```
74
305
 
306
+ ### JSON
307
+
75
308
  ```json
76
309
  {
77
310
  "start": {
@@ -85,22 +318,82 @@ Step Type From To
85
318
  }
86
319
  ```
87
320
 
321
+ ### Mermaid
322
+
88
323
  ```mermaid
89
324
  flowchart TD
90
325
  EntryHandler -->|remote_action| IdentityService
91
326
  ```
92
327
 
93
- ## Limitations
328
+ ---
94
329
 
95
- - Static analysis cannot know all runtime branches.
96
- - Dynamic service names may need `--var` values.
97
- - Unsupported custom frameworks may appear as unresolved edges.
330
+ ## โš ๏ธ Limitations
331
+
332
+ - Static analysis cannot know every runtime branch, feature flag, or environment-specific destination.
333
+ - Dynamic service names and paths may need `--var key=value` values to resolve concrete targets.
334
+ - Highly customized frameworks can still appear as unresolved edges until parser support is added.
98
335
  - Parse failures are stored as diagnostics and reported by `service-flow doctor`.
99
- - The analysis favors explainable evidence and confidence scores over speculative resolution.
336
+ - The resolver prefers source evidence and confidence scores over speculative matches.
337
+
338
+ ---
339
+
340
+ ## โ“ FAQ
341
+
342
+ <details>
343
+ <summary><b>Does service-flow run my CAP application?</b></summary>
344
+
345
+ No. It is a static analyzer. It reads source files, `.cds` models, `package.json`, and TypeScript AST information, then stores derived facts in SQLite.
346
+
347
+ </details>
348
+
349
+ <details>
350
+ <summary><b>When should I run index and link again?</b></summary>
351
+
352
+ Run `service-flow index` after source, CDS, package metadata, or helper-package code changes. Run `service-flow link` after indexing so cross-repository edges are rebuilt from the latest facts.
353
+
354
+ </details>
355
+
356
+ <details>
357
+ <summary><b>Why is an expected call unresolved?</b></summary>
358
+
359
+ Check `service-flow doctor`, then inspect the facts with `service-flow list services`, `service-flow list operations`, and `service-flow list calls`. Dynamic destinations may need `--var key=value`, and custom wrappers may need new parser support.
360
+
361
+ </details>
362
+
363
+ <details>
364
+ <summary><b>Is the SQLite database safe to commit?</b></summary>
365
+
366
+ No. It should not contain runtime secrets by design, but it can expose internal topology, service names, paths, repository names, and source evidence. Keep `.service-flow/` out of git.
367
+
368
+ </details>
369
+
370
+ ---
371
+
372
+ ## ๐Ÿ› ๏ธ Development
373
+
374
+ From the monorepo root:
375
+
376
+ ```bash
377
+ pnpm install
378
+ pnpm --filter @saptools/service-flow build
379
+ pnpm --filter @saptools/service-flow typecheck
380
+ pnpm --filter @saptools/service-flow lint
381
+ pnpm --filter @saptools/service-flow test:unit
382
+ pnpm --filter @saptools/service-flow test:e2e
383
+ ```
384
+
385
+ The e2e tests use fixture CAP workspaces and fake-backed flows. They do not need live SAP BTP credentials.
386
+
387
+ ---
388
+
389
+ ## ๐Ÿ‘จโ€๐Ÿ’ป Author
390
+
391
+ **dongtran** โœจ
392
+
393
+ ## ๐Ÿ“„ License
394
+
395
+ MIT
100
396
 
101
- ## Troubleshooting
397
+ ---
102
398
 
103
- - Run `service-flow doctor --workspace /path/to/workspace` to inspect parse errors and unresolved diagnostics.
104
- - Run `service-flow list repos --workspace /path/to/workspace` to confirm repository discovery.
105
- - Run `service-flow list services --repo facade-service` and `service-flow list calls --repo facade-service` to inspect indexed facts.
106
- - Use `service-flow clean --workspace /path/to/workspace --db-only` and re-run `init`, `index`, and `link` if the database becomes stale.
399
+ Made with โค๏ธ to make your work life easier!
package/dist/cli.js CHANGED
@@ -631,7 +631,7 @@ function createProgram() {
631
631
  const program = new Command();
632
632
  program.name("service-flow").description(
633
633
  "Trace SAP CAP service-to-service flows across multi-repository workspaces"
634
- ).version("0.1.0");
634
+ ).version("0.1.1");
635
635
  program.command("init").argument("<workspace>").option("--db <path>").option("--ignore <pattern...>").action(
636
636
  (workspace, opts) => void init(workspace, opts).catch(fail)
637
637
  );
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/config/defaults.ts","../src/config/workspace-config.ts","../src/db/connection.ts","../src/db/schema.ts","../src/db/migrations.ts","../src/db/repositories.ts","../src/discovery/classify-repository.ts","../src/indexer/repository-indexer.ts","../src/indexer/incremental-index.ts","../src/utils/hashing.ts","../src/utils/diagnostics.ts","../src/indexer/workspace-indexer.ts","../src/trace/selectors.ts","../src/output/table-output.ts","../src/output/json-output.ts","../src/output/mermaid-output.ts"],"sourcesContent":["import { Command } from 'commander';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport pc from 'picocolors';\nimport { DEFAULT_IGNORES } from './config/defaults.js';\nimport {\n createWorkspaceConfig,\n loadWorkspaceConfig,\n saveWorkspaceConfig\n} from './config/workspace-config.js';\nimport { openDatabase } from './db/connection.js';\nimport {\n getWorkspace,\n listRepositories,\n repoByName,\n upsertRepository,\n upsertWorkspace\n} from './db/repositories.js';\nimport { discoverRepositories } from './discovery/discover-repositories.js';\nimport { parsePackageJson } from './parsers/package-json-parser.js';\nimport { classifyRepository } from './discovery/classify-repository.js';\nimport { indexWorkspace } from './indexer/workspace-indexer.js';\nimport { linkWorkspace } from './linker/cross-repo-linker.js';\nimport { trace } from './trace/trace-engine.js';\nimport { parseVars } from './trace/selectors.js';\nimport { renderTraceTable } from './output/table-output.js';\nimport { renderTraceJson, renderJson } from './output/json-output.js';\nimport { renderMermaid } from './output/mermaid-output.js';\nasync function init(\n workspace: string,\n options: { db?: string; ignore?: string[] }\n): Promise<void> {\n const config = createWorkspaceConfig(\n workspace,\n options.db,\n options.ignore?.length ? options.ignore : [...DEFAULT_IGNORES]\n );\n const repos = await discoverRepositories(config.rootPath, config.ignore);\n await saveWorkspaceConfig(config);\n const db = openDatabase(config.dbPath);\n const workspaceId = upsertWorkspace(db, config.rootPath, config.dbPath);\n for (const repo of repos) {\n const pkg = await parsePackageJson(repo.absolutePath);\n const kind = await classifyRepository(repo.absolutePath, pkg);\n upsertRepository(db, workspaceId, {\n ...repo,\n packageName: pkg.packageName,\n packageVersion: pkg.packageVersion,\n dependencies: pkg.dependencies,\n kind\n });\n }\n db.close();\n process.stdout.write(\n `Workspace: ${config.rootPath}\\nDatabase: ${config.dbPath}\\nRepositories: ${repos.length}\\nIgnored: ${config.ignore.join(', ')}\\nNext: service-flow index --workspace ${config.rootPath}\\n`\n );\n}\nasync function withWorkspace<T>(\n workspace: string | undefined,\n fn: (\n db: ReturnType<typeof openDatabase>,\n workspaceId: number,\n rootPath: string\n ) => Promise<T> | T\n): Promise<T> {\n const config = await loadWorkspaceConfig(workspace);\n const db = openDatabase(config.dbPath);\n try {\n const row = getWorkspace(db, config.rootPath);\n const workspaceId =\n row?.id ?? upsertWorkspace(db, config.rootPath, config.dbPath);\n return await fn(db, workspaceId, config.rootPath);\n } finally {\n db.close();\n }\n}\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name('service-flow')\n .description(\n 'Trace SAP CAP service-to-service flows across multi-repository workspaces'\n )\n .version('0.1.0');\n program\n .command('init')\n .argument('<workspace>')\n .option('--db <path>')\n .option('--ignore <pattern...>')\n .action(\n (workspace: string, opts: { db?: string; ignore?: string[] }) =>\n void init(workspace, opts).catch(fail)\n );\n program\n .command('index')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--force')\n .option('--concurrency <n>', 'reserved for future parallel indexing', '1')\n .action(\n (opts: { workspace?: string; repo?: string; force?: boolean }) =>\n void withWorkspace(opts.workspace, async (db, workspaceId) => {\n const r = await indexWorkspace(db, workspaceId, {\n repo: opts.repo,\n force: Boolean(opts.force)\n });\n process.stdout.write(\n `Indexed ${r.repoCount} repositories, ${r.fileCount} files, ${r.diagnosticCount} diagnostics\\n`\n );\n }).catch(fail)\n );\n program\n .command('link')\n .option('--workspace <path>')\n .option('--force')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db, workspaceId) => {\n const r = linkWorkspace(db, workspaceId);\n process.stdout.write(\n `Linked ${r.edgeCount} edges, ${r.unresolvedCount} unresolved\\n`\n );\n }).catch(fail)\n );\n program\n .command('trace')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .option('--service <path>')\n .option('--path <operationPath>')\n .option('--handler <name>')\n .option('--depth <n>', 'trace depth', '25')\n .option('--format <format>', 'table|json|mermaid', 'table')\n .option('--include-external')\n .option('--include-db')\n .option('--include-async')\n .option('--var <key=value>', 'dynamic variable', collect, [])\n .action(\n (opts: {\n workspace?: string;\n repo?: string;\n operation?: string;\n service?: string;\n path?: string;\n handler?: string;\n depth: string;\n format: string;\n includeExternal?: boolean;\n includeDb?: boolean;\n includeAsync?: boolean;\n var: string[];\n }) =>\n void withWorkspace(opts.workspace, (db) => {\n const result = trace(\n db,\n {\n repo: opts.repo,\n servicePath: opts.service,\n operation: opts.operation,\n operationPath: opts.path,\n handler: opts.handler\n },\n {\n depth: Number(opts.depth),\n vars: parseVars(opts.var),\n includeExternal: Boolean(opts.includeExternal),\n includeDb: Boolean(opts.includeDb),\n includeAsync: Boolean(opts.includeAsync)\n }\n );\n process.stdout.write(\n opts.format === 'json'\n ? renderTraceJson(result)\n : opts.format === 'mermaid'\n ? renderMermaid(result)\n : renderTraceTable(result)\n );\n }).catch(fail)\n );\n const list = program.command('list');\n list\n .command('repos')\n .option('--workspace <path>')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) =>\n process.stdout.write(\n renderJson(\n listRepositories(db).map((r) => ({\n name: r.name,\n kind: r.kind,\n packageName: r.package_name\n }))\n )\n )\n ).catch(fail)\n );\n list\n .command('services')\n .option('--workspace <path>')\n .option('--repo <name>')\n .action(\n (opts: { workspace?: string; repo?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,s.service_path servicePath,s.qualified_name qualifiedName FROM cds_services s JOIN repositories r ON r.id=s.repo_id WHERE (? IS NULL OR s.repo_id=?) ORDER BY r.name,s.service_path'\n )\n .all(repo?.id, repo?.id);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n list\n .command('operations')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--service <path>')\n .action(\n (opts: { workspace?: string; repo?: string; service?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,s.service_path servicePath,o.operation_name operation,o.operation_path path FROM cds_operations o JOIN cds_services s ON s.id=o.service_id JOIN repositories r ON r.id=s.repo_id WHERE (? IS NULL OR s.repo_id=?) AND (? IS NULL OR s.service_path=?)'\n )\n .all(repo?.id, repo?.id, opts.service, opts.service);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n list\n .command('calls')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .action(\n (opts: { workspace?: string; repo?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,c.call_type type,c.operation_path_expr path,c.source_file file,c.source_line line FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id WHERE (? IS NULL OR c.repo_id=?)'\n )\n .all(repo?.id, repo?.id);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n program\n .command('graph')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .option('--service <path>')\n .option('--path <operationPath>')\n .option('--format <format>', 'mermaid|json', 'mermaid')\n .action(\n (opts: {\n workspace?: string;\n repo?: string;\n operation?: string;\n service?: string;\n path?: string;\n format: string;\n }) =>\n void withWorkspace(opts.workspace, (db) => {\n const result = trace(\n db,\n {\n repo: opts.repo,\n operation: opts.operation,\n servicePath: opts.service,\n operationPath: opts.path\n },\n {\n depth: 100,\n includeAsync: true,\n includeDb: true,\n includeExternal: true\n }\n );\n process.stdout.write(\n opts.format === 'json'\n ? renderTraceJson(result)\n : renderMermaid(result)\n );\n }).catch(fail)\n );\n const inspect = program.command('inspect');\n inspect\n .command('repo')\n .argument('<name>')\n .option('--workspace <path>')\n .action(\n (name: string, opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) =>\n process.stdout.write(\n renderJson(repoByName(db, name) ?? { error: 'repo not found' })\n )\n ).catch(fail)\n );\n inspect\n .command('operation')\n .argument('<selector>')\n .option('--workspace <path>')\n .action(\n (selector: string, opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const rows = db\n .prepare(\n 'SELECT * FROM cds_operations WHERE operation_name=? OR operation_path=?'\n )\n .all(selector, selector);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n program\n .command('doctor')\n .option('--workspace <path>')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const diagnostics = db\n .prepare(\n 'SELECT severity,code,message,source_file sourceFile,source_line sourceLine FROM diagnostics ORDER BY id'\n )\n .all();\n process.stdout.write(\n diagnostics.length\n ? renderJson(diagnostics)\n : `${pc.green('No diagnostics recorded')}\\n`\n );\n }).catch(fail)\n );\n program\n .command('clean')\n .option('--workspace <path>')\n .option('--db-only')\n .action(\n (opts: { workspace?: string; dbOnly?: boolean }) =>\n void (async () => {\n const config = await loadWorkspaceConfig(opts.workspace);\n await fs.rm(config.dbPath, { force: true });\n if (!opts.dbOnly)\n await fs.rm(path.dirname(config.dbPath), {\n recursive: true,\n force: true\n });\n process.stdout.write('Cleaned service-flow state\\n');\n })().catch(fail)\n );\n return program;\n}\nfunction collect(value: string, previous: string[]): string[] {\n previous.push(value);\n return previous;\n}\nfunction fail(error: unknown): void {\n process.stderr.write(\n `${error instanceof Error ? error.message : String(error)}\\n`\n );\n process.exitCode = 1;\n}\ncreateProgram().parse(process.argv);\n","export const DEFAULT_IGNORES = [\n 'node_modules',\n 'gen',\n 'dist',\n 'coverage',\n '.git',\n '.turbo',\n '.next',\n '.cache',\n '.service-flow'\n] as const;\nexport const CONFIG_DIR = '.service-flow';\nexport const CONFIG_FILE = 'config.json';\nexport const DEFAULT_DB_FILE = 'service-flow.db';\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { z } from 'zod';\nimport {\n CONFIG_DIR,\n CONFIG_FILE,\n DEFAULT_DB_FILE,\n DEFAULT_IGNORES\n} from './defaults.js';\nconst schema = z.object({\n rootPath: z.string(),\n dbPath: z.string(),\n ignore: z.array(z.string()),\n createdAt: z.string(),\n updatedAt: z.string()\n});\nexport type WorkspaceConfig = z.infer<typeof schema>;\nexport function configPath(rootPath: string): string {\n return path.join(rootPath, CONFIG_DIR, CONFIG_FILE);\n}\nexport function defaultDbPath(rootPath: string): string {\n return path.join(rootPath, CONFIG_DIR, DEFAULT_DB_FILE);\n}\nexport async function saveWorkspaceConfig(\n config: WorkspaceConfig\n): Promise<void> {\n await fs.mkdir(path.dirname(configPath(config.rootPath)), {\n recursive: true\n });\n await fs.writeFile(\n configPath(config.rootPath),\n `${JSON.stringify(config, null, 2)}\\n`\n );\n}\nexport async function loadWorkspaceConfig(\n workspace?: string\n): Promise<WorkspaceConfig> {\n const root = path.resolve(workspace ?? process.cwd());\n const data = await fs.readFile(configPath(root), 'utf8');\n return schema.parse(JSON.parse(data) as unknown);\n}\nexport function createWorkspaceConfig(\n rootPath: string,\n dbPath?: string,\n ignore: string[] = [...DEFAULT_IGNORES]\n): WorkspaceConfig {\n const now = new Date().toISOString();\n const root = path.resolve(rootPath);\n return {\n rootPath: root,\n dbPath: path.resolve(dbPath ?? defaultDbPath(root)),\n ignore,\n createdAt: now,\n updatedAt: now\n };\n}\n","import { execFileSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { migrate } from './migrations.js';\nexport interface Statement {\n run: (...params: unknown[]) => { changes: number };\n get: (...params: unknown[]) => Record<string, unknown> | undefined;\n all: (...params: unknown[]) => Array<Record<string, unknown>>;\n}\nexport interface Db {\n path: string;\n exec: (sql: string) => void;\n prepare: (sql: string) => Statement;\n pragma: (sql: string) => void;\n close: () => void;\n}\nfunction quote(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number')\n return Number.isFinite(value) ? String(value) : 'NULL';\n if (typeof value === 'boolean') return value ? '1' : '0';\n return `'${String(value).replaceAll(\"'\", \"''\")}'`;\n}\nfunction bind(sql: string, params: unknown[]): string {\n let index = 0;\n return sql.replaceAll('?', () => quote(params[index++]));\n}\nfunction call(dbPath: string, args: string[]): string {\n return execFileSync('sqlite3', [dbPath, ...args], { encoding: 'utf8' });\n}\nfunction jsonRows(dbPath: string, sql: string): Array<Record<string, unknown>> {\n const out = call(dbPath, ['-json', sql]);\n if (!out.trim()) return [];\n return JSON.parse(out) as Array<Record<string, unknown>>;\n}\nexport function openDatabase(dbPath: string): Db {\n fs.mkdirSync(path.dirname(dbPath), { recursive: true });\n const db: Db = {\n path: dbPath,\n exec(sql: string): void {\n call(dbPath, [sql]);\n },\n prepare(sql: string): Statement {\n return {\n run: (...params: unknown[]) => {\n call(dbPath, [bind(sql, params)]);\n return { changes: 0 };\n },\n get: (...params: unknown[]) => jsonRows(dbPath, bind(sql, params))[0],\n all: (...params: unknown[]) => jsonRows(dbPath, bind(sql, params))\n };\n },\n pragma(sql: string): void {\n call(dbPath, [`PRAGMA ${sql}`]);\n },\n close(): void {\n /* sqlite3 CLI opens per statement */\n }\n };\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n migrate(db);\n return db;\n}\n","export const schemaSql = `\nCREATE TABLE IF NOT EXISTS workspaces (id INTEGER PRIMARY KEY, root_path TEXT UNIQUE NOT NULL, db_path TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL);\nCREATE TABLE IF NOT EXISTS repositories (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, name TEXT NOT NULL, absolute_path TEXT NOT NULL, relative_path TEXT NOT NULL, package_name TEXT, package_version TEXT, dependencies_json TEXT DEFAULT '{}', kind TEXT NOT NULL, is_git_repo INTEGER NOT NULL, last_indexed_at TEXT, index_status TEXT DEFAULT 'pending', error_count INTEGER DEFAULT 0, UNIQUE(workspace_id, absolute_path));\nCREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, relative_path TEXT NOT NULL, extension TEXT NOT NULL, sha256 TEXT NOT NULL, size_bytes INTEGER NOT NULL, last_indexed_at TEXT NOT NULL, UNIQUE(repo_id, relative_path));\nCREATE TABLE IF NOT EXISTS cds_requires (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, alias TEXT NOT NULL, kind TEXT, model TEXT, destination TEXT, service_path TEXT, request_timeout INTEGER, raw_json TEXT NOT NULL);\nCREATE TABLE IF NOT EXISTS cds_services (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, namespace TEXT, service_name TEXT NOT NULL, qualified_name TEXT NOT NULL, service_path TEXT NOT NULL, is_extend INTEGER NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS cds_operations (id INTEGER PRIMARY KEY, service_id INTEGER NOT NULL, operation_type TEXT NOT NULL, operation_name TEXT NOT NULL, operation_path TEXT NOT NULL, params_json TEXT NOT NULL, return_type TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS symbols (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, file_id INTEGER, kind TEXT NOT NULL, name TEXT NOT NULL, qualified_name TEXT NOT NULL, exported INTEGER NOT NULL, start_line INTEGER NOT NULL, end_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_classes (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, symbol_id INTEGER, class_name TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_methods (id INTEGER PRIMARY KEY, handler_class_id INTEGER NOT NULL, method_name TEXT NOT NULL, decorator_kind TEXT NOT NULL, decorator_value TEXT, decorator_raw_expression TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_registrations (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, handler_class_id INTEGER, registration_file TEXT NOT NULL, registration_line INTEGER NOT NULL, registration_kind TEXT NOT NULL, confidence REAL NOT NULL);\nCREATE TABLE IF NOT EXISTS service_bindings (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, symbol_id INTEGER, variable_name TEXT NOT NULL, alias TEXT, destination_expr TEXT, service_path_expr TEXT, is_dynamic INTEGER NOT NULL, placeholders_json TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS outbound_calls (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, source_symbol_id INTEGER, call_type TEXT NOT NULL, service_binding_id INTEGER, method TEXT, operation_path_expr TEXT, query_entity TEXT, event_name_expr TEXT, payload_summary TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, confidence REAL NOT NULL, unresolved_reason TEXT);\nCREATE TABLE IF NOT EXISTS graph_edges (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, edge_type TEXT NOT NULL, from_kind TEXT NOT NULL, from_id TEXT NOT NULL, to_kind TEXT NOT NULL, to_id TEXT NOT NULL, confidence REAL NOT NULL, evidence_json TEXT NOT NULL, is_dynamic INTEGER NOT NULL, unresolved_reason TEXT);\nCREATE TABLE IF NOT EXISTS index_runs (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, started_at TEXT NOT NULL, finished_at TEXT, status TEXT NOT NULL, repo_count INTEGER NOT NULL, file_count INTEGER NOT NULL, diagnostic_count INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS diagnostics (id INTEGER PRIMARY KEY, repo_id INTEGER, file_id INTEGER, severity TEXT NOT NULL, code TEXT NOT NULL, message TEXT NOT NULL, source_file TEXT, source_line INTEGER);\nCREATE INDEX IF NOT EXISTS idx_repo_name ON repositories(name);\nCREATE INDEX IF NOT EXISTS idx_service_path ON cds_services(service_path);\nCREATE INDEX IF NOT EXISTS idx_operation_name ON cds_operations(operation_name, operation_path);\nCREATE INDEX IF NOT EXISTS idx_calls_repo ON outbound_calls(repo_id, call_type);\nCREATE VIRTUAL TABLE IF NOT EXISTS search_index USING fts5(kind, name, path, repo);\n`;\n","import type { Db } from './connection.js';\nimport { schemaSql } from './schema.js';\nexport function migrate(db: Db): void {\n db.exec(schemaSql);\n}\n","import type { Db } from './connection.js';\nimport type {\n CdsRequire,\n CdsServiceFact,\n HandlerClassFact,\n HandlerRegistrationFact,\n OutboundCallFact,\n ServiceBindingFact\n} from '../types.js';\nexport interface RepoRow {\n id: number;\n name: string;\n absolute_path: string;\n relative_path: string;\n package_name: string | null;\n package_version: string | null;\n dependencies_json: string;\n kind: string;\n}\nexport interface WorkspaceRow {\n id: number;\n root_path: string;\n db_path: string;\n}\nexport function upsertWorkspace(\n db: Db,\n rootPath: string,\n dbPath: string\n): number {\n const now = new Date().toISOString();\n db.prepare(\n 'INSERT INTO workspaces(root_path,db_path,created_at,updated_at) VALUES(?,?,?,?) ON CONFLICT(root_path) DO UPDATE SET db_path=excluded.db_path,updated_at=excluded.updated_at'\n ).run(rootPath, dbPath, now, now);\n return Number(\n db.prepare('SELECT id FROM workspaces WHERE root_path=?').get(rootPath)?.id\n );\n}\nexport function getWorkspace(\n db: Db,\n rootPath: string\n): WorkspaceRow | undefined {\n return db\n .prepare('SELECT * FROM workspaces WHERE root_path=?')\n .get(rootPath) as WorkspaceRow | undefined;\n}\nexport function upsertRepository(\n db: Db,\n workspaceId: number,\n r: {\n name: string;\n absolutePath: string;\n relativePath: string;\n isGitRepo: boolean;\n packageName?: string;\n packageVersion?: string;\n dependencies?: Record<string, string>;\n kind?: string;\n }\n): number {\n db.prepare(\n `INSERT INTO repositories(workspace_id,name,absolute_path,relative_path,package_name,package_version,dependencies_json,kind,is_git_repo) VALUES(?,?,?,?,?,?,?,?,?) ON CONFLICT(workspace_id,absolute_path) DO UPDATE SET name=excluded.name,relative_path=excluded.relative_path,package_name=excluded.package_name,package_version=excluded.package_version,dependencies_json=excluded.dependencies_json,kind=excluded.kind`\n ).run(\n workspaceId,\n r.name,\n r.absolutePath,\n r.relativePath,\n r.packageName,\n r.packageVersion,\n JSON.stringify(r.dependencies ?? {}),\n r.kind ?? 'unknown',\n r.isGitRepo ? 1 : 0\n );\n return Number(\n db\n .prepare(\n 'SELECT id FROM repositories WHERE workspace_id=? AND absolute_path=?'\n )\n .get(workspaceId, r.absolutePath)?.id\n );\n}\nexport function listRepositories(db: Db): RepoRow[] {\n return db\n .prepare('SELECT * FROM repositories ORDER BY name')\n .all() as unknown as RepoRow[];\n}\nexport function repoByName(db: Db, name: string): RepoRow | undefined {\n return db\n .prepare('SELECT * FROM repositories WHERE name=? OR package_name=?')\n .get(name, name) as RepoRow | undefined;\n}\nexport function clearRepoFacts(db: Db, repoId: number): void {\n for (const t of [\n 'cds_requires',\n 'cds_services',\n 'symbols',\n 'handler_classes',\n 'handler_registrations',\n 'service_bindings',\n 'outbound_calls',\n 'diagnostics',\n 'files'\n ])\n db.prepare(`DELETE FROM ${t} WHERE repo_id=?`).run(repoId);\n}\nexport function insertRequires(\n db: Db,\n repoId: number,\n rows: CdsRequire[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO cds_requires(repo_id,alias,kind,model,destination,service_path,request_timeout,raw_json) VALUES(?,?,?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.alias,\n r.kind,\n r.model,\n r.destination,\n r.servicePath,\n r.requestTimeout,\n r.rawJson\n );\n}\nexport function insertService(\n db: Db,\n repoId: number,\n s: CdsServiceFact\n): number {\n const id = Number(\n db\n .prepare(\n 'INSERT INTO cds_services(repo_id,namespace,service_name,qualified_name,service_path,is_extend,source_file,source_line) VALUES(?,?,?,?,?,?,?,?) RETURNING id'\n )\n .get(\n repoId,\n s.namespace,\n s.serviceName,\n s.qualifiedName,\n s.servicePath,\n s.isExtend ? 1 : 0,\n s.sourceFile,\n s.sourceLine\n )?.id\n );\n const stmt = db.prepare(\n 'INSERT INTO cds_operations(service_id,operation_type,operation_name,operation_path,params_json,return_type,source_file,source_line) VALUES(?,?,?,?,?,?,?,?)'\n );\n for (const o of s.operations)\n stmt.run(\n id,\n o.operationType,\n o.operationName,\n o.operationPath,\n o.paramsJson,\n o.returnType,\n o.sourceFile,\n o.sourceLine\n );\n return id;\n}\nexport function insertHandler(\n db: Db,\n repoId: number,\n h: HandlerClassFact\n): number {\n const sid = Number(\n db\n .prepare(\n 'INSERT INTO symbols(repo_id,kind,name,qualified_name,exported,start_line,end_line) VALUES(?,?,?,?,?,?,?) RETURNING id'\n )\n .get(\n repoId,\n 'class',\n h.className,\n h.className,\n 1,\n h.sourceLine,\n h.sourceLine\n )?.id\n );\n const hid = Number(\n db\n .prepare(\n 'INSERT INTO handler_classes(repo_id,symbol_id,class_name,source_file,source_line) VALUES(?,?,?,?,?) RETURNING id'\n )\n .get(repoId, sid, h.className, h.sourceFile, h.sourceLine)?.id\n );\n const stmt = db.prepare(\n 'INSERT INTO handler_methods(handler_class_id,method_name,decorator_kind,decorator_value,decorator_raw_expression,source_file,source_line) VALUES(?,?,?,?,?,?,?)'\n );\n for (const m of h.methods)\n stmt.run(\n hid,\n m.methodName,\n m.decoratorKind,\n m.decoratorValue,\n m.decoratorRawExpression,\n m.sourceFile,\n m.sourceLine\n );\n return hid;\n}\nexport function insertRegistrations(\n db: Db,\n repoId: number,\n rows: HandlerRegistrationFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO handler_registrations(repo_id,handler_class_id,registration_file,registration_line,registration_kind,confidence) VALUES(?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n null,\n r.registrationFile,\n r.registrationLine,\n r.registrationKind,\n r.confidence\n );\n}\nexport function insertBindings(\n db: Db,\n repoId: number,\n rows: ServiceBindingFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO service_bindings(repo_id,variable_name,alias,destination_expr,service_path_expr,is_dynamic,placeholders_json,source_file,source_line) VALUES(?,?,?,?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.variableName,\n r.alias,\n r.destinationExpr,\n r.servicePathExpr,\n r.isDynamic ? 1 : 0,\n JSON.stringify(r.placeholders),\n r.sourceFile,\n r.sourceLine\n );\n}\nexport function insertCalls(\n db: Db,\n repoId: number,\n rows: OutboundCallFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO outbound_calls(repo_id,call_type,method,operation_path_expr,query_entity,event_name_expr,payload_summary,source_file,source_line,confidence,unresolved_reason,service_binding_id) VALUES(?,?,?,?,?,?,?,?,?,?,?,(SELECT id FROM service_bindings WHERE repo_id=? AND variable_name=? ORDER BY id DESC LIMIT 1))'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.callType,\n r.method,\n r.operationPathExpr,\n r.queryEntity,\n r.eventNameExpr,\n r.payloadSummary,\n r.sourceFile,\n r.sourceLine,\n r.confidence,\n r.unresolvedReason,\n repoId,\n r.serviceVariableName\n );\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PackageFacts, RepoKind } from '../types.js';\nexport async function classifyRepository(\n repoPath: string,\n facts: PackageFacts\n): Promise<RepoKind> {\n const hasCdsDep = Boolean(\n facts.dependencies['@sap/cds'] ??\n facts.dependencies.cds ??\n facts.dependencies['cds-routing-handlers']\n );\n const cdsFiles = await findFiles(repoPath, '.cds');\n const serverFiles = await Promise.all(\n ['srv/server.ts', 'srv/server.js', 'src/server.ts', 'src/server.js'].map(\n async (f) =>\n fs\n .access(path.join(repoPath, f))\n .then(() => true)\n .catch(() => false)\n )\n );\n const helper =\n Object.keys(facts.dependencies).includes('cds-routing-handlers') ||\n facts.packageName?.includes('helper') === true;\n if (helper && cdsFiles.length > 0) return 'mixed';\n if (helper) return 'helper-package';\n if (hasCdsDep && (cdsFiles.length > 0 || serverFiles.some(Boolean)))\n return 'cap-service';\n if (cdsFiles.length > 0)\n return serverFiles.some(Boolean) ? 'cap-service' : 'cap-db-model';\n return 'unknown';\n}\n\nasync function findFiles(root: string, suffix: string): Promise<string[]> {\n const out: string[] = [];\n async function walk(dir: string): Promise<void> {\n const entries = await fs\n .readdir(dir, { withFileTypes: true })\n .catch(() => []);\n for (const e of entries) {\n if (e.isDirectory()) {\n if (!['node_modules', 'dist', 'gen', '.git'].includes(e.name))\n await walk(path.join(dir, e.name));\n } else if (e.name.endsWith(suffix)) out.push(path.join(dir, e.name));\n }\n }\n await walk(root);\n return out;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Db } from '../db/connection.js';\nimport {\n clearRepoFacts,\n insertBindings,\n insertCalls,\n insertHandler,\n insertRegistrations,\n insertRequires,\n insertService,\n type RepoRow\n} from '../db/repositories.js';\nimport { classifyRepository } from '../discovery/classify-repository.js';\nimport { parseCdsFile } from '../parsers/cds-parser.js';\nimport { parseDecorators } from '../parsers/decorator-parser.js';\nimport { parseHandlerRegistrations } from '../parsers/handler-registration-parser.js';\nimport { parseOutboundCalls } from '../parsers/outbound-call-parser.js';\nimport { parsePackageJson } from '../parsers/package-json-parser.js';\nimport { parseServiceBindings } from '../parsers/service-binding-parser.js';\nimport { recordFile } from './incremental-index.js';\nimport { errorMessage } from '../utils/diagnostics.js';\nexport interface IndexRepoResult {\n fileCount: number;\n diagnosticCount: number;\n}\nexport async function indexRepository(\n db: Db,\n repo: RepoRow,\n force: boolean\n): Promise<IndexRepoResult> {\n void force;\n let diagnostics = 0;\n let files = 0;\n const facts = await parsePackageJson(repo.absolute_path);\n const kind = await classifyRepository(repo.absolute_path, facts);\n db.prepare(\n 'UPDATE repositories SET package_name=?, package_version=?, dependencies_json=?, kind=?, index_status=? WHERE id=?'\n ).run(\n facts.packageName,\n facts.packageVersion,\n JSON.stringify(facts.dependencies),\n kind,\n 'indexing',\n repo.id\n );\n clearRepoFacts(db, repo.id);\n insertRequires(db, repo.id, facts.cdsRequires);\n const sourceFiles = await findSourceFiles(repo.absolute_path);\n for (const file of sourceFiles) {\n try {\n await recordFile(db, repo.id, repo.absolute_path, file);\n files += 1;\n if (file.endsWith('.cds'))\n for (const s of await parseCdsFile(repo.absolute_path, file))\n insertService(db, repo.id, s);\n if (/\\.[jt]s$/.test(file)) {\n for (const h of await parseDecorators(repo.absolute_path, file))\n insertHandler(db, repo.id, h);\n insertRegistrations(\n db,\n repo.id,\n await parseHandlerRegistrations(repo.absolute_path, file)\n );\n insertBindings(\n db,\n repo.id,\n await parseServiceBindings(repo.absolute_path, file)\n );\n insertCalls(\n db,\n repo.id,\n await parseOutboundCalls(repo.absolute_path, file)\n );\n }\n } catch (error) {\n diagnostics += 1;\n db.prepare(\n 'INSERT INTO diagnostics(repo_id,severity,code,message,source_file) VALUES(?,?,?,?,?)'\n ).run(repo.id, 'warning', 'parse_failed', errorMessage(error), file);\n }\n }\n db.prepare(\n 'UPDATE repositories SET last_indexed_at=?, index_status=?, error_count=? WHERE id=?'\n ).run(\n new Date().toISOString(),\n diagnostics ? 'partial' : 'indexed',\n diagnostics,\n repo.id\n );\n return { fileCount: files, diagnosticCount: diagnostics };\n}\n\nasync function findSourceFiles(root: string): Promise<string[]> {\n const out: string[] = [];\n async function walk(dir: string, prefix = ''): Promise<void> {\n const entries = await fs\n .readdir(dir, { withFileTypes: true })\n .catch(() => []);\n for (const e of entries) {\n const rel = prefix ? `${prefix}/${e.name}` : e.name;\n if (e.isDirectory()) {\n if (\n !['node_modules', 'dist', 'gen', 'coverage', '.git'].includes(e.name)\n )\n await walk(path.join(dir, e.name), rel);\n } else if (/\\.(cds|ts|js)$/.test(e.name)) out.push(rel);\n }\n }\n await walk(root);\n return out.sort();\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { sha256File } from '../utils/hashing.js';\nimport { normalizePath } from '../utils/path-utils.js';\nimport type { Db } from '../db/connection.js';\nexport async function recordFile(\n db: Db,\n repoId: number,\n repoPath: string,\n relativeFile: string\n): Promise<void> {\n const abs = path.join(repoPath, relativeFile);\n const stat = await fs.stat(abs);\n const hash = await sha256File(abs);\n db.prepare(\n 'INSERT INTO files(repo_id,relative_path,extension,sha256,size_bytes,last_indexed_at) VALUES(?,?,?,?,?,?) ON CONFLICT(repo_id,relative_path) DO UPDATE SET sha256=excluded.sha256,size_bytes=excluded.size_bytes,last_indexed_at=excluded.last_indexed_at'\n ).run(\n repoId,\n normalizePath(relativeFile),\n path.extname(relativeFile),\n hash,\n stat.size,\n new Date().toISOString()\n );\n}\n","import { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nexport async function sha256File(filePath: string): Promise<string> {\n return createHash('sha256')\n .update(await readFile(filePath))\n .digest('hex');\n}\nexport function sha256Text(text: string): string {\n return createHash('sha256').update(text).digest('hex');\n}\n","export interface DiagnosticInput {\n severity: 'info' | 'warning' | 'error';\n code: string;\n message: string;\n sourceFile?: string;\n sourceLine?: number;\n}\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import type { Db } from '../db/connection.js';\nimport { listRepositories, repoByName } from '../db/repositories.js';\nimport { indexRepository } from './repository-indexer.js';\nexport async function indexWorkspace(\n db: Db,\n workspaceId: number,\n options: { repo?: string; force: boolean }\n): Promise<{ repoCount: number; fileCount: number; diagnosticCount: number }> {\n const started = new Date().toISOString();\n const repos = options.repo\n ? [repoByName(db, options.repo)].filter((r) => r !== undefined)\n : listRepositories(db);\n const runId = Number(\n db\n .prepare(\n 'INSERT INTO index_runs(workspace_id,started_at,status,repo_count,file_count,diagnostic_count) VALUES(?,?,?,?,?,?) RETURNING id'\n )\n .get(workspaceId, started, 'running', repos.length, 0, 0)?.id\n );\n let fileCount = 0;\n let diagnosticCount = 0;\n for (const repo of repos) {\n const result = await indexRepository(db, repo, options.force);\n fileCount += result.fileCount;\n diagnosticCount += result.diagnosticCount;\n }\n db.prepare(\n 'UPDATE index_runs SET finished_at=?, status=?, file_count=?, diagnostic_count=? WHERE id=?'\n ).run(\n new Date().toISOString(),\n diagnosticCount ? 'partial' : 'success',\n fileCount,\n diagnosticCount,\n runId\n );\n return { repoCount: repos.length, fileCount, diagnosticCount };\n}\n","import type { TraceStart } from '../types.js';\nexport function parseVars(\n values: string[] | undefined\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const value of values ?? []) {\n const [key, ...rest] = value.split('=');\n if (key && rest.length > 0) out[key] = rest.join('=');\n }\n return out;\n}\nexport function startLabel(start: TraceStart): string {\n return [\n start.repo,\n start.servicePath,\n start.operation ?? start.operationPath ?? start.handler\n ]\n .filter(Boolean)\n .join(' ');\n}\n","import type { TraceResult } from '../types.js';\nimport { startLabel } from '../trace/selectors.js';\nexport function renderTraceTable(trace: TraceResult): string {\n const lines = [\n `Start: ${startLabel(trace.start)}`,\n '',\n 'Step Type From To Evidence'\n ];\n for (const e of trace.edges)\n lines.push(\n `${String(e.step).padEnd(5)} ${e.type.padEnd(20)} ${e.from.slice(0, 34).padEnd(35)} ${e.to.slice(0, 35).padEnd(36)} ${String(e.evidence.file ?? '')}:${String(e.evidence.line ?? '')}`\n );\n return `${lines.join('\\n')}\\n`;\n}\n","import type { TraceResult } from '../types.js';\nexport function renderJson(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\nexport function renderTraceJson(trace: TraceResult): string {\n return renderJson(trace);\n}\n","import type { TraceResult } from '../types.js';\nfunction safe(value: string): string {\n return value.replace(/[^\\w-]/g, '_').slice(0, 60);\n}\nexport function renderMermaid(trace: TraceResult): string {\n const lines = ['flowchart TD'];\n for (const e of trace.edges)\n lines.push(\n ` ${safe(e.from)}[\"${e.from}\"] -->|${e.type}| ${safe(e.to)}[\"${e.to}\"]`\n );\n return `${lines.join('\\n')}\\n`;\n}\n"],"mappings":"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","names":["path","fs","fs","path","fs","path","fs","path","fs","path","fs","path","path","fs","fs","path","trace","trace","trace","fs","path"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/config/defaults.ts","../src/config/workspace-config.ts","../src/db/connection.ts","../src/db/schema.ts","../src/db/migrations.ts","../src/db/repositories.ts","../src/discovery/classify-repository.ts","../src/indexer/repository-indexer.ts","../src/indexer/incremental-index.ts","../src/utils/hashing.ts","../src/utils/diagnostics.ts","../src/indexer/workspace-indexer.ts","../src/trace/selectors.ts","../src/output/table-output.ts","../src/output/json-output.ts","../src/output/mermaid-output.ts"],"sourcesContent":["import { Command } from 'commander';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport pc from 'picocolors';\nimport { DEFAULT_IGNORES } from './config/defaults.js';\nimport {\n createWorkspaceConfig,\n loadWorkspaceConfig,\n saveWorkspaceConfig\n} from './config/workspace-config.js';\nimport { openDatabase } from './db/connection.js';\nimport {\n getWorkspace,\n listRepositories,\n repoByName,\n upsertRepository,\n upsertWorkspace\n} from './db/repositories.js';\nimport { discoverRepositories } from './discovery/discover-repositories.js';\nimport { parsePackageJson } from './parsers/package-json-parser.js';\nimport { classifyRepository } from './discovery/classify-repository.js';\nimport { indexWorkspace } from './indexer/workspace-indexer.js';\nimport { linkWorkspace } from './linker/cross-repo-linker.js';\nimport { trace } from './trace/trace-engine.js';\nimport { parseVars } from './trace/selectors.js';\nimport { renderTraceTable } from './output/table-output.js';\nimport { renderTraceJson, renderJson } from './output/json-output.js';\nimport { renderMermaid } from './output/mermaid-output.js';\nasync function init(\n workspace: string,\n options: { db?: string; ignore?: string[] }\n): Promise<void> {\n const config = createWorkspaceConfig(\n workspace,\n options.db,\n options.ignore?.length ? options.ignore : [...DEFAULT_IGNORES]\n );\n const repos = await discoverRepositories(config.rootPath, config.ignore);\n await saveWorkspaceConfig(config);\n const db = openDatabase(config.dbPath);\n const workspaceId = upsertWorkspace(db, config.rootPath, config.dbPath);\n for (const repo of repos) {\n const pkg = await parsePackageJson(repo.absolutePath);\n const kind = await classifyRepository(repo.absolutePath, pkg);\n upsertRepository(db, workspaceId, {\n ...repo,\n packageName: pkg.packageName,\n packageVersion: pkg.packageVersion,\n dependencies: pkg.dependencies,\n kind\n });\n }\n db.close();\n process.stdout.write(\n `Workspace: ${config.rootPath}\\nDatabase: ${config.dbPath}\\nRepositories: ${repos.length}\\nIgnored: ${config.ignore.join(', ')}\\nNext: service-flow index --workspace ${config.rootPath}\\n`\n );\n}\nasync function withWorkspace<T>(\n workspace: string | undefined,\n fn: (\n db: ReturnType<typeof openDatabase>,\n workspaceId: number,\n rootPath: string\n ) => Promise<T> | T\n): Promise<T> {\n const config = await loadWorkspaceConfig(workspace);\n const db = openDatabase(config.dbPath);\n try {\n const row = getWorkspace(db, config.rootPath);\n const workspaceId =\n row?.id ?? upsertWorkspace(db, config.rootPath, config.dbPath);\n return await fn(db, workspaceId, config.rootPath);\n } finally {\n db.close();\n }\n}\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name('service-flow')\n .description(\n 'Trace SAP CAP service-to-service flows across multi-repository workspaces'\n )\n .version('0.1.1');\n program\n .command('init')\n .argument('<workspace>')\n .option('--db <path>')\n .option('--ignore <pattern...>')\n .action(\n (workspace: string, opts: { db?: string; ignore?: string[] }) =>\n void init(workspace, opts).catch(fail)\n );\n program\n .command('index')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--force')\n .option('--concurrency <n>', 'reserved for future parallel indexing', '1')\n .action(\n (opts: { workspace?: string; repo?: string; force?: boolean }) =>\n void withWorkspace(opts.workspace, async (db, workspaceId) => {\n const r = await indexWorkspace(db, workspaceId, {\n repo: opts.repo,\n force: Boolean(opts.force)\n });\n process.stdout.write(\n `Indexed ${r.repoCount} repositories, ${r.fileCount} files, ${r.diagnosticCount} diagnostics\\n`\n );\n }).catch(fail)\n );\n program\n .command('link')\n .option('--workspace <path>')\n .option('--force')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db, workspaceId) => {\n const r = linkWorkspace(db, workspaceId);\n process.stdout.write(\n `Linked ${r.edgeCount} edges, ${r.unresolvedCount} unresolved\\n`\n );\n }).catch(fail)\n );\n program\n .command('trace')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .option('--service <path>')\n .option('--path <operationPath>')\n .option('--handler <name>')\n .option('--depth <n>', 'trace depth', '25')\n .option('--format <format>', 'table|json|mermaid', 'table')\n .option('--include-external')\n .option('--include-db')\n .option('--include-async')\n .option('--var <key=value>', 'dynamic variable', collect, [])\n .action(\n (opts: {\n workspace?: string;\n repo?: string;\n operation?: string;\n service?: string;\n path?: string;\n handler?: string;\n depth: string;\n format: string;\n includeExternal?: boolean;\n includeDb?: boolean;\n includeAsync?: boolean;\n var: string[];\n }) =>\n void withWorkspace(opts.workspace, (db) => {\n const result = trace(\n db,\n {\n repo: opts.repo,\n servicePath: opts.service,\n operation: opts.operation,\n operationPath: opts.path,\n handler: opts.handler\n },\n {\n depth: Number(opts.depth),\n vars: parseVars(opts.var),\n includeExternal: Boolean(opts.includeExternal),\n includeDb: Boolean(opts.includeDb),\n includeAsync: Boolean(opts.includeAsync)\n }\n );\n process.stdout.write(\n opts.format === 'json'\n ? renderTraceJson(result)\n : opts.format === 'mermaid'\n ? renderMermaid(result)\n : renderTraceTable(result)\n );\n }).catch(fail)\n );\n const list = program.command('list');\n list\n .command('repos')\n .option('--workspace <path>')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) =>\n process.stdout.write(\n renderJson(\n listRepositories(db).map((r) => ({\n name: r.name,\n kind: r.kind,\n packageName: r.package_name\n }))\n )\n )\n ).catch(fail)\n );\n list\n .command('services')\n .option('--workspace <path>')\n .option('--repo <name>')\n .action(\n (opts: { workspace?: string; repo?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,s.service_path servicePath,s.qualified_name qualifiedName FROM cds_services s JOIN repositories r ON r.id=s.repo_id WHERE (? IS NULL OR s.repo_id=?) ORDER BY r.name,s.service_path'\n )\n .all(repo?.id, repo?.id);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n list\n .command('operations')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--service <path>')\n .action(\n (opts: { workspace?: string; repo?: string; service?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,s.service_path servicePath,o.operation_name operation,o.operation_path path FROM cds_operations o JOIN cds_services s ON s.id=o.service_id JOIN repositories r ON r.id=s.repo_id WHERE (? IS NULL OR s.repo_id=?) AND (? IS NULL OR s.service_path=?)'\n )\n .all(repo?.id, repo?.id, opts.service, opts.service);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n list\n .command('calls')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .action(\n (opts: { workspace?: string; repo?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const repo = opts.repo ? repoByName(db, opts.repo) : undefined;\n const rows = db\n .prepare(\n 'SELECT r.name repo,c.call_type type,c.operation_path_expr path,c.source_file file,c.source_line line FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id WHERE (? IS NULL OR c.repo_id=?)'\n )\n .all(repo?.id, repo?.id);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n program\n .command('graph')\n .option('--workspace <path>')\n .option('--repo <name>')\n .option('--operation <name>')\n .option('--service <path>')\n .option('--path <operationPath>')\n .option('--format <format>', 'mermaid|json', 'mermaid')\n .action(\n (opts: {\n workspace?: string;\n repo?: string;\n operation?: string;\n service?: string;\n path?: string;\n format: string;\n }) =>\n void withWorkspace(opts.workspace, (db) => {\n const result = trace(\n db,\n {\n repo: opts.repo,\n operation: opts.operation,\n servicePath: opts.service,\n operationPath: opts.path\n },\n {\n depth: 100,\n includeAsync: true,\n includeDb: true,\n includeExternal: true\n }\n );\n process.stdout.write(\n opts.format === 'json'\n ? renderTraceJson(result)\n : renderMermaid(result)\n );\n }).catch(fail)\n );\n const inspect = program.command('inspect');\n inspect\n .command('repo')\n .argument('<name>')\n .option('--workspace <path>')\n .action(\n (name: string, opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) =>\n process.stdout.write(\n renderJson(repoByName(db, name) ?? { error: 'repo not found' })\n )\n ).catch(fail)\n );\n inspect\n .command('operation')\n .argument('<selector>')\n .option('--workspace <path>')\n .action(\n (selector: string, opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const rows = db\n .prepare(\n 'SELECT * FROM cds_operations WHERE operation_name=? OR operation_path=?'\n )\n .all(selector, selector);\n process.stdout.write(renderJson(rows));\n }).catch(fail)\n );\n program\n .command('doctor')\n .option('--workspace <path>')\n .action(\n (opts: { workspace?: string }) =>\n void withWorkspace(opts.workspace, (db) => {\n const diagnostics = db\n .prepare(\n 'SELECT severity,code,message,source_file sourceFile,source_line sourceLine FROM diagnostics ORDER BY id'\n )\n .all();\n process.stdout.write(\n diagnostics.length\n ? renderJson(diagnostics)\n : `${pc.green('No diagnostics recorded')}\\n`\n );\n }).catch(fail)\n );\n program\n .command('clean')\n .option('--workspace <path>')\n .option('--db-only')\n .action(\n (opts: { workspace?: string; dbOnly?: boolean }) =>\n void (async () => {\n const config = await loadWorkspaceConfig(opts.workspace);\n await fs.rm(config.dbPath, { force: true });\n if (!opts.dbOnly)\n await fs.rm(path.dirname(config.dbPath), {\n recursive: true,\n force: true\n });\n process.stdout.write('Cleaned service-flow state\\n');\n })().catch(fail)\n );\n return program;\n}\nfunction collect(value: string, previous: string[]): string[] {\n previous.push(value);\n return previous;\n}\nfunction fail(error: unknown): void {\n process.stderr.write(\n `${error instanceof Error ? error.message : String(error)}\\n`\n );\n process.exitCode = 1;\n}\ncreateProgram().parse(process.argv);\n","export const DEFAULT_IGNORES = [\n 'node_modules',\n 'gen',\n 'dist',\n 'coverage',\n '.git',\n '.turbo',\n '.next',\n '.cache',\n '.service-flow'\n] as const;\nexport const CONFIG_DIR = '.service-flow';\nexport const CONFIG_FILE = 'config.json';\nexport const DEFAULT_DB_FILE = 'service-flow.db';\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { z } from 'zod';\nimport {\n CONFIG_DIR,\n CONFIG_FILE,\n DEFAULT_DB_FILE,\n DEFAULT_IGNORES\n} from './defaults.js';\nconst schema = z.object({\n rootPath: z.string(),\n dbPath: z.string(),\n ignore: z.array(z.string()),\n createdAt: z.string(),\n updatedAt: z.string()\n});\nexport type WorkspaceConfig = z.infer<typeof schema>;\nexport function configPath(rootPath: string): string {\n return path.join(rootPath, CONFIG_DIR, CONFIG_FILE);\n}\nexport function defaultDbPath(rootPath: string): string {\n return path.join(rootPath, CONFIG_DIR, DEFAULT_DB_FILE);\n}\nexport async function saveWorkspaceConfig(\n config: WorkspaceConfig\n): Promise<void> {\n await fs.mkdir(path.dirname(configPath(config.rootPath)), {\n recursive: true\n });\n await fs.writeFile(\n configPath(config.rootPath),\n `${JSON.stringify(config, null, 2)}\\n`\n );\n}\nexport async function loadWorkspaceConfig(\n workspace?: string\n): Promise<WorkspaceConfig> {\n const root = path.resolve(workspace ?? process.cwd());\n const data = await fs.readFile(configPath(root), 'utf8');\n return schema.parse(JSON.parse(data) as unknown);\n}\nexport function createWorkspaceConfig(\n rootPath: string,\n dbPath?: string,\n ignore: string[] = [...DEFAULT_IGNORES]\n): WorkspaceConfig {\n const now = new Date().toISOString();\n const root = path.resolve(rootPath);\n return {\n rootPath: root,\n dbPath: path.resolve(dbPath ?? defaultDbPath(root)),\n ignore,\n createdAt: now,\n updatedAt: now\n };\n}\n","import { execFileSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { migrate } from './migrations.js';\nexport interface Statement {\n run: (...params: unknown[]) => { changes: number };\n get: (...params: unknown[]) => Record<string, unknown> | undefined;\n all: (...params: unknown[]) => Array<Record<string, unknown>>;\n}\nexport interface Db {\n path: string;\n exec: (sql: string) => void;\n prepare: (sql: string) => Statement;\n pragma: (sql: string) => void;\n close: () => void;\n}\nfunction quote(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number')\n return Number.isFinite(value) ? String(value) : 'NULL';\n if (typeof value === 'boolean') return value ? '1' : '0';\n return `'${String(value).replaceAll(\"'\", \"''\")}'`;\n}\nfunction bind(sql: string, params: unknown[]): string {\n let index = 0;\n return sql.replaceAll('?', () => quote(params[index++]));\n}\nfunction call(dbPath: string, args: string[]): string {\n return execFileSync('sqlite3', [dbPath, ...args], { encoding: 'utf8' });\n}\nfunction jsonRows(dbPath: string, sql: string): Array<Record<string, unknown>> {\n const out = call(dbPath, ['-json', sql]);\n if (!out.trim()) return [];\n return JSON.parse(out) as Array<Record<string, unknown>>;\n}\nexport function openDatabase(dbPath: string): Db {\n fs.mkdirSync(path.dirname(dbPath), { recursive: true });\n const db: Db = {\n path: dbPath,\n exec(sql: string): void {\n call(dbPath, [sql]);\n },\n prepare(sql: string): Statement {\n return {\n run: (...params: unknown[]) => {\n call(dbPath, [bind(sql, params)]);\n return { changes: 0 };\n },\n get: (...params: unknown[]) => jsonRows(dbPath, bind(sql, params))[0],\n all: (...params: unknown[]) => jsonRows(dbPath, bind(sql, params))\n };\n },\n pragma(sql: string): void {\n call(dbPath, [`PRAGMA ${sql}`]);\n },\n close(): void {\n /* sqlite3 CLI opens per statement */\n }\n };\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n migrate(db);\n return db;\n}\n","export const schemaSql = `\nCREATE TABLE IF NOT EXISTS workspaces (id INTEGER PRIMARY KEY, root_path TEXT UNIQUE NOT NULL, db_path TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL);\nCREATE TABLE IF NOT EXISTS repositories (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, name TEXT NOT NULL, absolute_path TEXT NOT NULL, relative_path TEXT NOT NULL, package_name TEXT, package_version TEXT, dependencies_json TEXT DEFAULT '{}', kind TEXT NOT NULL, is_git_repo INTEGER NOT NULL, last_indexed_at TEXT, index_status TEXT DEFAULT 'pending', error_count INTEGER DEFAULT 0, UNIQUE(workspace_id, absolute_path));\nCREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, relative_path TEXT NOT NULL, extension TEXT NOT NULL, sha256 TEXT NOT NULL, size_bytes INTEGER NOT NULL, last_indexed_at TEXT NOT NULL, UNIQUE(repo_id, relative_path));\nCREATE TABLE IF NOT EXISTS cds_requires (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, alias TEXT NOT NULL, kind TEXT, model TEXT, destination TEXT, service_path TEXT, request_timeout INTEGER, raw_json TEXT NOT NULL);\nCREATE TABLE IF NOT EXISTS cds_services (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, namespace TEXT, service_name TEXT NOT NULL, qualified_name TEXT NOT NULL, service_path TEXT NOT NULL, is_extend INTEGER NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS cds_operations (id INTEGER PRIMARY KEY, service_id INTEGER NOT NULL, operation_type TEXT NOT NULL, operation_name TEXT NOT NULL, operation_path TEXT NOT NULL, params_json TEXT NOT NULL, return_type TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS symbols (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, file_id INTEGER, kind TEXT NOT NULL, name TEXT NOT NULL, qualified_name TEXT NOT NULL, exported INTEGER NOT NULL, start_line INTEGER NOT NULL, end_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_classes (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, symbol_id INTEGER, class_name TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_methods (id INTEGER PRIMARY KEY, handler_class_id INTEGER NOT NULL, method_name TEXT NOT NULL, decorator_kind TEXT NOT NULL, decorator_value TEXT, decorator_raw_expression TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS handler_registrations (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, handler_class_id INTEGER, registration_file TEXT NOT NULL, registration_line INTEGER NOT NULL, registration_kind TEXT NOT NULL, confidence REAL NOT NULL);\nCREATE TABLE IF NOT EXISTS service_bindings (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, symbol_id INTEGER, variable_name TEXT NOT NULL, alias TEXT, destination_expr TEXT, service_path_expr TEXT, is_dynamic INTEGER NOT NULL, placeholders_json TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS outbound_calls (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, source_symbol_id INTEGER, call_type TEXT NOT NULL, service_binding_id INTEGER, method TEXT, operation_path_expr TEXT, query_entity TEXT, event_name_expr TEXT, payload_summary TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, confidence REAL NOT NULL, unresolved_reason TEXT);\nCREATE TABLE IF NOT EXISTS graph_edges (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, edge_type TEXT NOT NULL, from_kind TEXT NOT NULL, from_id TEXT NOT NULL, to_kind TEXT NOT NULL, to_id TEXT NOT NULL, confidence REAL NOT NULL, evidence_json TEXT NOT NULL, is_dynamic INTEGER NOT NULL, unresolved_reason TEXT);\nCREATE TABLE IF NOT EXISTS index_runs (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, started_at TEXT NOT NULL, finished_at TEXT, status TEXT NOT NULL, repo_count INTEGER NOT NULL, file_count INTEGER NOT NULL, diagnostic_count INTEGER NOT NULL);\nCREATE TABLE IF NOT EXISTS diagnostics (id INTEGER PRIMARY KEY, repo_id INTEGER, file_id INTEGER, severity TEXT NOT NULL, code TEXT NOT NULL, message TEXT NOT NULL, source_file TEXT, source_line INTEGER);\nCREATE INDEX IF NOT EXISTS idx_repo_name ON repositories(name);\nCREATE INDEX IF NOT EXISTS idx_service_path ON cds_services(service_path);\nCREATE INDEX IF NOT EXISTS idx_operation_name ON cds_operations(operation_name, operation_path);\nCREATE INDEX IF NOT EXISTS idx_calls_repo ON outbound_calls(repo_id, call_type);\nCREATE VIRTUAL TABLE IF NOT EXISTS search_index USING fts5(kind, name, path, repo);\n`;\n","import type { Db } from './connection.js';\nimport { schemaSql } from './schema.js';\nexport function migrate(db: Db): void {\n db.exec(schemaSql);\n}\n","import type { Db } from './connection.js';\nimport type {\n CdsRequire,\n CdsServiceFact,\n HandlerClassFact,\n HandlerRegistrationFact,\n OutboundCallFact,\n ServiceBindingFact\n} from '../types.js';\nexport interface RepoRow {\n id: number;\n name: string;\n absolute_path: string;\n relative_path: string;\n package_name: string | null;\n package_version: string | null;\n dependencies_json: string;\n kind: string;\n}\nexport interface WorkspaceRow {\n id: number;\n root_path: string;\n db_path: string;\n}\nexport function upsertWorkspace(\n db: Db,\n rootPath: string,\n dbPath: string\n): number {\n const now = new Date().toISOString();\n db.prepare(\n 'INSERT INTO workspaces(root_path,db_path,created_at,updated_at) VALUES(?,?,?,?) ON CONFLICT(root_path) DO UPDATE SET db_path=excluded.db_path,updated_at=excluded.updated_at'\n ).run(rootPath, dbPath, now, now);\n return Number(\n db.prepare('SELECT id FROM workspaces WHERE root_path=?').get(rootPath)?.id\n );\n}\nexport function getWorkspace(\n db: Db,\n rootPath: string\n): WorkspaceRow | undefined {\n return db\n .prepare('SELECT * FROM workspaces WHERE root_path=?')\n .get(rootPath) as WorkspaceRow | undefined;\n}\nexport function upsertRepository(\n db: Db,\n workspaceId: number,\n r: {\n name: string;\n absolutePath: string;\n relativePath: string;\n isGitRepo: boolean;\n packageName?: string;\n packageVersion?: string;\n dependencies?: Record<string, string>;\n kind?: string;\n }\n): number {\n db.prepare(\n `INSERT INTO repositories(workspace_id,name,absolute_path,relative_path,package_name,package_version,dependencies_json,kind,is_git_repo) VALUES(?,?,?,?,?,?,?,?,?) ON CONFLICT(workspace_id,absolute_path) DO UPDATE SET name=excluded.name,relative_path=excluded.relative_path,package_name=excluded.package_name,package_version=excluded.package_version,dependencies_json=excluded.dependencies_json,kind=excluded.kind`\n ).run(\n workspaceId,\n r.name,\n r.absolutePath,\n r.relativePath,\n r.packageName,\n r.packageVersion,\n JSON.stringify(r.dependencies ?? {}),\n r.kind ?? 'unknown',\n r.isGitRepo ? 1 : 0\n );\n return Number(\n db\n .prepare(\n 'SELECT id FROM repositories WHERE workspace_id=? AND absolute_path=?'\n )\n .get(workspaceId, r.absolutePath)?.id\n );\n}\nexport function listRepositories(db: Db): RepoRow[] {\n return db\n .prepare('SELECT * FROM repositories ORDER BY name')\n .all() as unknown as RepoRow[];\n}\nexport function repoByName(db: Db, name: string): RepoRow | undefined {\n return db\n .prepare('SELECT * FROM repositories WHERE name=? OR package_name=?')\n .get(name, name) as RepoRow | undefined;\n}\nexport function clearRepoFacts(db: Db, repoId: number): void {\n for (const t of [\n 'cds_requires',\n 'cds_services',\n 'symbols',\n 'handler_classes',\n 'handler_registrations',\n 'service_bindings',\n 'outbound_calls',\n 'diagnostics',\n 'files'\n ])\n db.prepare(`DELETE FROM ${t} WHERE repo_id=?`).run(repoId);\n}\nexport function insertRequires(\n db: Db,\n repoId: number,\n rows: CdsRequire[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO cds_requires(repo_id,alias,kind,model,destination,service_path,request_timeout,raw_json) VALUES(?,?,?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.alias,\n r.kind,\n r.model,\n r.destination,\n r.servicePath,\n r.requestTimeout,\n r.rawJson\n );\n}\nexport function insertService(\n db: Db,\n repoId: number,\n s: CdsServiceFact\n): number {\n const id = Number(\n db\n .prepare(\n 'INSERT INTO cds_services(repo_id,namespace,service_name,qualified_name,service_path,is_extend,source_file,source_line) VALUES(?,?,?,?,?,?,?,?) RETURNING id'\n )\n .get(\n repoId,\n s.namespace,\n s.serviceName,\n s.qualifiedName,\n s.servicePath,\n s.isExtend ? 1 : 0,\n s.sourceFile,\n s.sourceLine\n )?.id\n );\n const stmt = db.prepare(\n 'INSERT INTO cds_operations(service_id,operation_type,operation_name,operation_path,params_json,return_type,source_file,source_line) VALUES(?,?,?,?,?,?,?,?)'\n );\n for (const o of s.operations)\n stmt.run(\n id,\n o.operationType,\n o.operationName,\n o.operationPath,\n o.paramsJson,\n o.returnType,\n o.sourceFile,\n o.sourceLine\n );\n return id;\n}\nexport function insertHandler(\n db: Db,\n repoId: number,\n h: HandlerClassFact\n): number {\n const sid = Number(\n db\n .prepare(\n 'INSERT INTO symbols(repo_id,kind,name,qualified_name,exported,start_line,end_line) VALUES(?,?,?,?,?,?,?) RETURNING id'\n )\n .get(\n repoId,\n 'class',\n h.className,\n h.className,\n 1,\n h.sourceLine,\n h.sourceLine\n )?.id\n );\n const hid = Number(\n db\n .prepare(\n 'INSERT INTO handler_classes(repo_id,symbol_id,class_name,source_file,source_line) VALUES(?,?,?,?,?) RETURNING id'\n )\n .get(repoId, sid, h.className, h.sourceFile, h.sourceLine)?.id\n );\n const stmt = db.prepare(\n 'INSERT INTO handler_methods(handler_class_id,method_name,decorator_kind,decorator_value,decorator_raw_expression,source_file,source_line) VALUES(?,?,?,?,?,?,?)'\n );\n for (const m of h.methods)\n stmt.run(\n hid,\n m.methodName,\n m.decoratorKind,\n m.decoratorValue,\n m.decoratorRawExpression,\n m.sourceFile,\n m.sourceLine\n );\n return hid;\n}\nexport function insertRegistrations(\n db: Db,\n repoId: number,\n rows: HandlerRegistrationFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO handler_registrations(repo_id,handler_class_id,registration_file,registration_line,registration_kind,confidence) VALUES(?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n null,\n r.registrationFile,\n r.registrationLine,\n r.registrationKind,\n r.confidence\n );\n}\nexport function insertBindings(\n db: Db,\n repoId: number,\n rows: ServiceBindingFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO service_bindings(repo_id,variable_name,alias,destination_expr,service_path_expr,is_dynamic,placeholders_json,source_file,source_line) VALUES(?,?,?,?,?,?,?,?,?)'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.variableName,\n r.alias,\n r.destinationExpr,\n r.servicePathExpr,\n r.isDynamic ? 1 : 0,\n JSON.stringify(r.placeholders),\n r.sourceFile,\n r.sourceLine\n );\n}\nexport function insertCalls(\n db: Db,\n repoId: number,\n rows: OutboundCallFact[]\n): void {\n const stmt = db.prepare(\n 'INSERT INTO outbound_calls(repo_id,call_type,method,operation_path_expr,query_entity,event_name_expr,payload_summary,source_file,source_line,confidence,unresolved_reason,service_binding_id) VALUES(?,?,?,?,?,?,?,?,?,?,?,(SELECT id FROM service_bindings WHERE repo_id=? AND variable_name=? ORDER BY id DESC LIMIT 1))'\n );\n for (const r of rows)\n stmt.run(\n repoId,\n r.callType,\n r.method,\n r.operationPathExpr,\n r.queryEntity,\n r.eventNameExpr,\n r.payloadSummary,\n r.sourceFile,\n r.sourceLine,\n r.confidence,\n r.unresolvedReason,\n repoId,\n r.serviceVariableName\n );\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PackageFacts, RepoKind } from '../types.js';\nexport async function classifyRepository(\n repoPath: string,\n facts: PackageFacts\n): Promise<RepoKind> {\n const hasCdsDep = Boolean(\n facts.dependencies['@sap/cds'] ??\n facts.dependencies.cds ??\n facts.dependencies['cds-routing-handlers']\n );\n const cdsFiles = await findFiles(repoPath, '.cds');\n const serverFiles = await Promise.all(\n ['srv/server.ts', 'srv/server.js', 'src/server.ts', 'src/server.js'].map(\n async (f) =>\n fs\n .access(path.join(repoPath, f))\n .then(() => true)\n .catch(() => false)\n )\n );\n const helper =\n Object.keys(facts.dependencies).includes('cds-routing-handlers') ||\n facts.packageName?.includes('helper') === true;\n if (helper && cdsFiles.length > 0) return 'mixed';\n if (helper) return 'helper-package';\n if (hasCdsDep && (cdsFiles.length > 0 || serverFiles.some(Boolean)))\n return 'cap-service';\n if (cdsFiles.length > 0)\n return serverFiles.some(Boolean) ? 'cap-service' : 'cap-db-model';\n return 'unknown';\n}\n\nasync function findFiles(root: string, suffix: string): Promise<string[]> {\n const out: string[] = [];\n async function walk(dir: string): Promise<void> {\n const entries = await fs\n .readdir(dir, { withFileTypes: true })\n .catch(() => []);\n for (const e of entries) {\n if (e.isDirectory()) {\n if (!['node_modules', 'dist', 'gen', '.git'].includes(e.name))\n await walk(path.join(dir, e.name));\n } else if (e.name.endsWith(suffix)) out.push(path.join(dir, e.name));\n }\n }\n await walk(root);\n return out;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Db } from '../db/connection.js';\nimport {\n clearRepoFacts,\n insertBindings,\n insertCalls,\n insertHandler,\n insertRegistrations,\n insertRequires,\n insertService,\n type RepoRow\n} from '../db/repositories.js';\nimport { classifyRepository } from '../discovery/classify-repository.js';\nimport { parseCdsFile } from '../parsers/cds-parser.js';\nimport { parseDecorators } from '../parsers/decorator-parser.js';\nimport { parseHandlerRegistrations } from '../parsers/handler-registration-parser.js';\nimport { parseOutboundCalls } from '../parsers/outbound-call-parser.js';\nimport { parsePackageJson } from '../parsers/package-json-parser.js';\nimport { parseServiceBindings } from '../parsers/service-binding-parser.js';\nimport { recordFile } from './incremental-index.js';\nimport { errorMessage } from '../utils/diagnostics.js';\nexport interface IndexRepoResult {\n fileCount: number;\n diagnosticCount: number;\n}\nexport async function indexRepository(\n db: Db,\n repo: RepoRow,\n force: boolean\n): Promise<IndexRepoResult> {\n void force;\n let diagnostics = 0;\n let files = 0;\n const facts = await parsePackageJson(repo.absolute_path);\n const kind = await classifyRepository(repo.absolute_path, facts);\n db.prepare(\n 'UPDATE repositories SET package_name=?, package_version=?, dependencies_json=?, kind=?, index_status=? WHERE id=?'\n ).run(\n facts.packageName,\n facts.packageVersion,\n JSON.stringify(facts.dependencies),\n kind,\n 'indexing',\n repo.id\n );\n clearRepoFacts(db, repo.id);\n insertRequires(db, repo.id, facts.cdsRequires);\n const sourceFiles = await findSourceFiles(repo.absolute_path);\n for (const file of sourceFiles) {\n try {\n await recordFile(db, repo.id, repo.absolute_path, file);\n files += 1;\n if (file.endsWith('.cds'))\n for (const s of await parseCdsFile(repo.absolute_path, file))\n insertService(db, repo.id, s);\n if (/\\.[jt]s$/.test(file)) {\n for (const h of await parseDecorators(repo.absolute_path, file))\n insertHandler(db, repo.id, h);\n insertRegistrations(\n db,\n repo.id,\n await parseHandlerRegistrations(repo.absolute_path, file)\n );\n insertBindings(\n db,\n repo.id,\n await parseServiceBindings(repo.absolute_path, file)\n );\n insertCalls(\n db,\n repo.id,\n await parseOutboundCalls(repo.absolute_path, file)\n );\n }\n } catch (error) {\n diagnostics += 1;\n db.prepare(\n 'INSERT INTO diagnostics(repo_id,severity,code,message,source_file) VALUES(?,?,?,?,?)'\n ).run(repo.id, 'warning', 'parse_failed', errorMessage(error), file);\n }\n }\n db.prepare(\n 'UPDATE repositories SET last_indexed_at=?, index_status=?, error_count=? WHERE id=?'\n ).run(\n new Date().toISOString(),\n diagnostics ? 'partial' : 'indexed',\n diagnostics,\n repo.id\n );\n return { fileCount: files, diagnosticCount: diagnostics };\n}\n\nasync function findSourceFiles(root: string): Promise<string[]> {\n const out: string[] = [];\n async function walk(dir: string, prefix = ''): Promise<void> {\n const entries = await fs\n .readdir(dir, { withFileTypes: true })\n .catch(() => []);\n for (const e of entries) {\n const rel = prefix ? `${prefix}/${e.name}` : e.name;\n if (e.isDirectory()) {\n if (\n !['node_modules', 'dist', 'gen', 'coverage', '.git'].includes(e.name)\n )\n await walk(path.join(dir, e.name), rel);\n } else if (/\\.(cds|ts|js)$/.test(e.name)) out.push(rel);\n }\n }\n await walk(root);\n return out.sort();\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { sha256File } from '../utils/hashing.js';\nimport { normalizePath } from '../utils/path-utils.js';\nimport type { Db } from '../db/connection.js';\nexport async function recordFile(\n db: Db,\n repoId: number,\n repoPath: string,\n relativeFile: string\n): Promise<void> {\n const abs = path.join(repoPath, relativeFile);\n const stat = await fs.stat(abs);\n const hash = await sha256File(abs);\n db.prepare(\n 'INSERT INTO files(repo_id,relative_path,extension,sha256,size_bytes,last_indexed_at) VALUES(?,?,?,?,?,?) ON CONFLICT(repo_id,relative_path) DO UPDATE SET sha256=excluded.sha256,size_bytes=excluded.size_bytes,last_indexed_at=excluded.last_indexed_at'\n ).run(\n repoId,\n normalizePath(relativeFile),\n path.extname(relativeFile),\n hash,\n stat.size,\n new Date().toISOString()\n );\n}\n","import { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nexport async function sha256File(filePath: string): Promise<string> {\n return createHash('sha256')\n .update(await readFile(filePath))\n .digest('hex');\n}\nexport function sha256Text(text: string): string {\n return createHash('sha256').update(text).digest('hex');\n}\n","export interface DiagnosticInput {\n severity: 'info' | 'warning' | 'error';\n code: string;\n message: string;\n sourceFile?: string;\n sourceLine?: number;\n}\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import type { Db } from '../db/connection.js';\nimport { listRepositories, repoByName } from '../db/repositories.js';\nimport { indexRepository } from './repository-indexer.js';\nexport async function indexWorkspace(\n db: Db,\n workspaceId: number,\n options: { repo?: string; force: boolean }\n): Promise<{ repoCount: number; fileCount: number; diagnosticCount: number }> {\n const started = new Date().toISOString();\n const repos = options.repo\n ? [repoByName(db, options.repo)].filter((r) => r !== undefined)\n : listRepositories(db);\n const runId = Number(\n db\n .prepare(\n 'INSERT INTO index_runs(workspace_id,started_at,status,repo_count,file_count,diagnostic_count) VALUES(?,?,?,?,?,?) RETURNING id'\n )\n .get(workspaceId, started, 'running', repos.length, 0, 0)?.id\n );\n let fileCount = 0;\n let diagnosticCount = 0;\n for (const repo of repos) {\n const result = await indexRepository(db, repo, options.force);\n fileCount += result.fileCount;\n diagnosticCount += result.diagnosticCount;\n }\n db.prepare(\n 'UPDATE index_runs SET finished_at=?, status=?, file_count=?, diagnostic_count=? WHERE id=?'\n ).run(\n new Date().toISOString(),\n diagnosticCount ? 'partial' : 'success',\n fileCount,\n diagnosticCount,\n runId\n );\n return { repoCount: repos.length, fileCount, diagnosticCount };\n}\n","import type { TraceStart } from '../types.js';\nexport function parseVars(\n values: string[] | undefined\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const value of values ?? []) {\n const [key, ...rest] = value.split('=');\n if (key && rest.length > 0) out[key] = rest.join('=');\n }\n return out;\n}\nexport function startLabel(start: TraceStart): string {\n return [\n start.repo,\n start.servicePath,\n start.operation ?? start.operationPath ?? start.handler\n ]\n .filter(Boolean)\n .join(' ');\n}\n","import type { TraceResult } from '../types.js';\nimport { startLabel } from '../trace/selectors.js';\nexport function renderTraceTable(trace: TraceResult): string {\n const lines = [\n `Start: ${startLabel(trace.start)}`,\n '',\n 'Step Type From To Evidence'\n ];\n for (const e of trace.edges)\n lines.push(\n `${String(e.step).padEnd(5)} ${e.type.padEnd(20)} ${e.from.slice(0, 34).padEnd(35)} ${e.to.slice(0, 35).padEnd(36)} ${String(e.evidence.file ?? '')}:${String(e.evidence.line ?? '')}`\n );\n return `${lines.join('\\n')}\\n`;\n}\n","import type { TraceResult } from '../types.js';\nexport function renderJson(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\nexport function renderTraceJson(trace: TraceResult): string {\n return renderJson(trace);\n}\n","import type { TraceResult } from '../types.js';\nfunction safe(value: string): string {\n return value.replace(/[^\\w-]/g, '_').slice(0, 60);\n}\nexport function renderMermaid(trace: TraceResult): string {\n const lines = ['flowchart TD'];\n for (const e of trace.edges)\n lines.push(\n ` ${safe(e.from)}[\"${e.from}\"] -->|${e.type}| ${safe(e.to)}[\"${e.to}\"]`\n );\n return `${lines.join('\\n')}\\n`;\n}\n"],"mappings":"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","names":["path","fs","fs","path","fs","path","fs","path","fs","path","fs","path","path","fs","fs","path","trace","trace","trace","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saptools/service-flow",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Trace SAP CAP service-to-service flows across multi-repository workspaces",
5
5
  "type": "module",
6
6
  "publishConfig": {