fundgraph 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FundGraph contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,3 +1,88 @@
1
- # Temporary Holding Version
1
+ <p align="center"><img src="assets/fundgraph-cli.svg" alt="FundGraph CLI: local dependency analysis from your terminal" width="100%"></p>
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ <p align="center">
4
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-56d6be?style=flat-square" alt="MIT license"></a>
5
+ <img src="https://img.shields.io/badge/Node.js-20%20%7C%2022-83a8ff?style=flat-square" alt="Node.js 20 and 22">
6
+ <img src="https://img.shields.io/badge/command-fundgraph-b6a9ff?style=flat-square" alt="fundgraph command">
7
+ </p>
8
+
9
+ # fundgraph-cli
10
+
11
+ The command-line interface for local dependency discovery and deterministic text or JSON reports. It uses
12
+ `@fundgraph/core` for models and analysis; it does not duplicate domain logic.
13
+
14
+ ## Current scope
15
+
16
+ `fundgraph analyze` reads a supported project directory, a JSON model file, or JSON from stdin. Directory discovery
17
+ supports npm, PyPI, Cargo, and baseline Go `go.mod` requirements. The default directory mode is local-only. Add
18
+ `--network` to explicitly fetch public npm, PyPI, or crates.io metadata and produce the complete evidence-backed
19
+ funding report. Go remains discovery-only because Go metadata and funding providers are not implemented.
20
+
21
+ The CLI now orchestrates those stages for arbitrary npm, PyPI, and Cargo projects when `--network` is explicitly
22
+ supplied. Default directory analysis remains local-only; Go is discovery-only.
23
+
24
+ ## Commands
25
+
26
+ ```text
27
+ fundgraph --help
28
+ fundgraph version
29
+ fundgraph analyze [PATH] [--format text|json] [--offline|--network] [--strict]
30
+ ```
31
+
32
+ `PATH` defaults to the current directory. Use `-` or omit the path to read JSON from stdin. `--offline` makes the local
33
+ only behavior explicit. `--strict` treats invalid model input as an error.
34
+
35
+ | Exit code | Meaning |
36
+ |---:|---|
37
+ | `0` | Analysis completed without diagnostics |
38
+ | `1` | Partial analysis or model diagnostics |
39
+ | `2` | Usage or invalid input |
40
+ | `3` | Unexpected internal failure |
41
+
42
+ JSON output keeps the compatibility summary fields and includes the versioned core report under `report`. Text output
43
+ prints the summary and deterministic report. `--network` is opt-in and uses the core network policy.
44
+
45
+ ## Try it from the workspace
46
+
47
+ The CLI package is not published yet. Run these commands from the `fundgraph-cli` repository directory:
48
+
49
+ ```sh
50
+ cd ../fundgraph-core
51
+ npm ci
52
+ npm run build
53
+
54
+ cd ../fundgraph-cli
55
+ npm install --ignore-scripts --no-save ../fundgraph-core
56
+ npm run build
57
+ node dist/main.js --help
58
+ node dist/main.js analyze ../fundgraph-core/test/fixtures/npm-workspace --format text --offline
59
+ node dist/main.js analyze ../fundgraph-core/test/fixtures/npm-workspace --format json --offline
60
+ node dist/main.js analyze ./my-project --format json --network
61
+ ```
62
+
63
+ After compatible npm packages are published, install and run it with:
64
+
65
+ ```sh
66
+ npm install -g fundgraph
67
+ fundgraph analyze ./my-project --format text --offline
68
+ ```
69
+
70
+ ## Ownership and safety
71
+
72
+ - This repository owns argument parsing, terminal output, CLI errors, and process exit codes.
73
+ - `fundgraph-core` owns dependency models, parsing, evidence, relationship logic, and opt-in project orchestration.
74
+ - Input files are bounded and treated as data; the CLI does not execute project code.
75
+ - The command does not identify maintainers, endorse funding destinations, manage wallets, or execute payments.
76
+
77
+ ## Development
78
+
79
+ ```sh
80
+ npm run lint
81
+ npm run typecheck
82
+ npm test
83
+ npm run build
84
+ npm pack --dry-run
85
+ ```
86
+
87
+ CI defines Ubuntu, Windows, and macOS jobs on Node 20 and 22. See [`CONTRIBUTING.md`](CONTRIBUTING.md) and the
88
+ project-level `fundgraph` repository for the cross-repository roadmap and policies.
package/dist/main.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const CLI_VERSION = "0.1.0";
2
+ export declare const MAX_INPUT_BYTES = 1048576;
3
+ export declare function run(argv: readonly string[]): Promise<number>;
4
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,eAAe,UAAY,CAAC;AAoLzC,wBAAsB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBlE"}
package/dist/main.js ADDED
@@ -0,0 +1,201 @@
1
+ import { readFileSync, statSync } from 'node:fs';
2
+ import { stderr, stdout } from 'node:process';
3
+ import { analyzeProject, createReport, discoverDependencies, renderReportText, validateModel } from '@fundgraph/core';
4
+ import { FundGraphCliError, parseArguments } from './options.js';
5
+ export const CLI_VERSION = '0.1.0';
6
+ export const MAX_INPUT_BYTES = 1_048_576;
7
+ const HELP = `FundGraph ${CLI_VERSION}
8
+
9
+ Analyze a JSON model document and explain its validated model inventory.
10
+
11
+ Usage:
12
+ fundgraph analyze [PATH] [--format text|json] [--offline|--network] [--strict]
13
+ fundgraph version
14
+ fundgraph --help
15
+
16
+ Input:
17
+ PATH may be a project directory (npm, PyPI, or Cargo), a JSON file
18
+ containing versioned FundGraph models, or -/omitted for stdin.
19
+
20
+ Options:
21
+ --format text|json Select output format (default: text)
22
+ --offline Use only local input and do not enable network access
23
+ --network Fetch public registry metadata and parse declared funding evidence
24
+ --strict Treat invalid models as an invalid-input failure
25
+ -h, --help Show this help
26
+ -v, --version Show the CLI version
27
+ `;
28
+ function readInput(inputPath) {
29
+ if (inputPath === '-')
30
+ return readFromStdin();
31
+ let stats;
32
+ try {
33
+ stats = statSync(inputPath);
34
+ }
35
+ catch {
36
+ throw new FundGraphCliError('INVALID_INPUT', `Input path does not exist: ${inputPath}`);
37
+ }
38
+ if (!stats.isFile()) {
39
+ throw new FundGraphCliError('INVALID_INPUT', 'Input must be a JSON model file or a supported project directory.');
40
+ }
41
+ if (stats.size > MAX_INPUT_BYTES) {
42
+ throw new FundGraphCliError('INPUT_TOO_LARGE', `Input exceeds ${MAX_INPUT_BYTES} bytes`);
43
+ }
44
+ return readFileSync(inputPath, 'utf8');
45
+ }
46
+ function readFromStdin() {
47
+ const input = readFileSync(0);
48
+ if (input.byteLength > MAX_INPUT_BYTES)
49
+ throw new FundGraphCliError('INPUT_TOO_LARGE', `Input exceeds ${MAX_INPUT_BYTES} bytes`);
50
+ return input.toString('utf8');
51
+ }
52
+ function extractModels(parsed) {
53
+ if (Array.isArray(parsed))
54
+ return parsed;
55
+ if (typeof parsed === 'object' && parsed !== null && Array.isArray(parsed.models)) {
56
+ return parsed.models;
57
+ }
58
+ throw new FundGraphCliError('INVALID_INPUT', 'JSON input must be an array of models or an object containing a models array');
59
+ }
60
+ function reportForModels(models, diagnostics) {
61
+ const grouped = {
62
+ Project: [],
63
+ Dependency: [],
64
+ Package: [],
65
+ Registry: [],
66
+ Repository: [],
67
+ FundingSource: [],
68
+ Evidence: [],
69
+ Confidence: [],
70
+ Relationship: []
71
+ };
72
+ for (const model of models)
73
+ grouped[model.kind].push(model);
74
+ const project = grouped.Project[0];
75
+ return createReport({
76
+ ...(project ? { project } : {}),
77
+ dependencies: grouped.Dependency,
78
+ packages: grouped.Package,
79
+ registries: grouped.Registry,
80
+ repositories: grouped.Repository,
81
+ fundingSources: grouped.FundingSource,
82
+ evidence: grouped.Evidence,
83
+ relationships: grouped.Relationship,
84
+ diagnostics,
85
+ });
86
+ }
87
+ async function analyze(options) {
88
+ if (options.inputPath !== '-') {
89
+ try {
90
+ if (statSync(options.inputPath).isDirectory()) {
91
+ if (options.network) {
92
+ const analyzed = await analyzeProject(options.inputPath);
93
+ const diagnostics = analyzed.report.diagnostics;
94
+ return {
95
+ schemaVersion: '1.0', input: options.inputPath, offline: false, strict: options.strict,
96
+ network: true,
97
+ modelCount: analyzed.report.summary.dependencyCount, edgeCount: analyzed.discovery.graph.edges.length,
98
+ ecosystems: analyzed.discovery.ecosystems, counts: { Dependency: analyzed.report.summary.dependencyCount, Package: analyzed.report.summary.packageCount, FundingSource: analyzed.report.summary.fundingSourceCount, Relationship: analyzed.report.summary.relationshipCount },
99
+ diagnostics, report: analyzed.report,
100
+ };
101
+ }
102
+ const discovered = discoverDependencies(options.inputPath);
103
+ const diagnostics = discovered.diagnostics.map((item) => ({ code: item.code, message: item.message, ...(item.sourcePath === undefined ? {} : { sourcePath: item.sourcePath }) }));
104
+ if (options.strict && diagnostics.length > 0)
105
+ throw new FundGraphCliError('INVALID_INPUT', `${diagnostics.length} discovery diagnostic(s) reported`);
106
+ const report = createReport({ project: discovered.project, dependencies: discovered.graph.nodes, diagnostics });
107
+ return {
108
+ schemaVersion: '1.0',
109
+ input: options.inputPath,
110
+ offline: options.offline,
111
+ strict: options.strict,
112
+ network: false,
113
+ modelCount: discovered.graph.nodes.length,
114
+ edgeCount: discovered.graph.edges.length,
115
+ ecosystems: discovered.ecosystems,
116
+ counts: { Dependency: discovered.graph.nodes.length },
117
+ diagnostics,
118
+ report,
119
+ };
120
+ }
121
+ }
122
+ catch (error) {
123
+ if (error instanceof FundGraphCliError)
124
+ throw error;
125
+ throw new FundGraphCliError('INVALID_INPUT', error instanceof Error ? error.message : 'Unable to inspect input path');
126
+ }
127
+ }
128
+ const source = readInput(options.inputPath);
129
+ let parsed;
130
+ try {
131
+ parsed = JSON.parse(source);
132
+ }
133
+ catch {
134
+ throw new FundGraphCliError('INVALID_INPUT', 'Input is not valid JSON');
135
+ }
136
+ const models = extractModels(parsed);
137
+ const diagnostics = [];
138
+ const validModels = [];
139
+ models.forEach((model, index) => {
140
+ try {
141
+ validateModel(model);
142
+ validModels.push(model);
143
+ }
144
+ catch (error) {
145
+ const code = error instanceof Error && 'code' in error ? String(error.code) : 'INVALID_MODEL';
146
+ const message = error instanceof Error ? error.message : 'Model validation failed';
147
+ diagnostics.push({ code, message, index });
148
+ }
149
+ });
150
+ if (options.strict && diagnostics.length > 0) {
151
+ throw new FundGraphCliError('INVALID_INPUT', `${diagnostics.length} model(s) failed validation`);
152
+ }
153
+ const counts = {};
154
+ for (const model of validModels)
155
+ counts[model.kind] = (counts[model.kind] ?? 0) + 1;
156
+ const report = reportForModels(validModels, diagnostics);
157
+ return { schemaVersion: '1.0', input: options.inputPath, offline: options.offline, strict: options.strict, network: false, modelCount: validModels.length, edgeCount: 0, ecosystems: [], counts, diagnostics, report };
158
+ }
159
+ function renderText(result) {
160
+ const lines = [
161
+ 'FundGraph analysis',
162
+ `Input: ${result.input}`,
163
+ `Models: ${result.modelCount}`,
164
+ `Edges: ${result.edgeCount}`,
165
+ ...(result.ecosystems.length > 0 ? [`Ecosystems: ${result.ecosystems.join(', ')}`] : []),
166
+ `Network: ${result.network ? 'enabled (public metadata only)' : 'disabled'}`,
167
+ ];
168
+ for (const [kind, count] of Object.entries(result.counts).sort(([a], [b]) => a.localeCompare(b)))
169
+ lines.push(` ${kind}: ${count}`);
170
+ if (result.diagnostics.length > 0) {
171
+ lines.push(`Diagnostics: ${result.diagnostics.length}`);
172
+ for (const diagnostic of result.diagnostics)
173
+ lines.push(` [${diagnostic.code}] model ${diagnostic.index}: ${diagnostic.message}`);
174
+ }
175
+ return `${lines.join('\n')}\n\n${renderReportText(result.report)}`;
176
+ }
177
+ export async function run(argv) {
178
+ try {
179
+ const parsed = parseArguments(argv);
180
+ if (parsed.command === 'help') {
181
+ stdout.write(HELP);
182
+ return 0;
183
+ }
184
+ if (parsed.command === 'version') {
185
+ stdout.write(`${CLI_VERSION}\n`);
186
+ return 0;
187
+ }
188
+ const result = await analyze(parsed.options);
189
+ stdout.write(parsed.options.format === 'json' ? `${JSON.stringify(result, null, 2)}\n` : renderText(result));
190
+ return result.diagnostics.length > 0 ? 1 : 0;
191
+ }
192
+ catch (error) {
193
+ const code = error instanceof FundGraphCliError ? error.code : 'INTERNAL_ERROR';
194
+ const message = error instanceof Error ? error.message : 'Unexpected error';
195
+ stderr.write(`fundgraph: [${code}] ${message}\n`);
196
+ return code === 'USAGE' || code === 'INVALID_INPUT' || code === 'INPUT_TOO_LARGE' ? 2 : 3;
197
+ }
198
+ }
199
+ if (process.argv[1])
200
+ run(process.argv.slice(2)).then((code) => { process.exitCode = code; });
201
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export type OutputFormat = 'text' | 'json';
2
+ export interface CliOptions {
3
+ inputPath: string;
4
+ format: OutputFormat;
5
+ offline: boolean;
6
+ network: boolean;
7
+ strict: boolean;
8
+ }
9
+ export type ParsedCommand = {
10
+ command: 'help';
11
+ } | {
12
+ command: 'version';
13
+ } | {
14
+ command: 'analyze';
15
+ options: CliOptions;
16
+ };
17
+ export type CliErrorCode = 'USAGE' | 'INVALID_INPUT' | 'INPUT_TOO_LARGE' | 'INTERNAL_ERROR';
18
+ export declare class FundGraphCliError extends Error {
19
+ readonly code: CliErrorCode;
20
+ constructor(code: CliErrorCode, message: string);
21
+ }
22
+ export declare function parseArguments(argv: readonly string[]): ParsedCommand;
23
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB;IAAE,OAAO,EAAE,SAAS,CAAA;CAAE,GACtB;IAAE,OAAO,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAEhD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE5F,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,IAAI,EAAE,YAAY;IAAvC,YAAqB,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAGvD;CACF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CAgDrE"}
@@ -0,0 +1,66 @@
1
+ export class FundGraphCliError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = 'FundGraphCliError';
7
+ }
8
+ }
9
+ export function parseArguments(argv) {
10
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h')
11
+ return { command: 'help' };
12
+ if (argv[0] === 'version' || argv[0] === '--version' || argv[0] === '-v') {
13
+ if (argv.length > 1)
14
+ throw new FundGraphCliError('USAGE', 'version does not accept additional arguments');
15
+ return { command: 'version' };
16
+ }
17
+ if (argv[0] !== 'analyze')
18
+ throw new FundGraphCliError('USAGE', `Unknown command: ${argv[0]}`);
19
+ let inputPath = '-';
20
+ let format = 'text';
21
+ let offline = false;
22
+ let network = false;
23
+ let strict = false;
24
+ let pathSeen = false;
25
+ for (let index = 1; index < argv.length; index += 1) {
26
+ const argument = argv[index];
27
+ if (argument === '--help' || argument === '-h')
28
+ return { command: 'help' };
29
+ if (argument === '--offline') {
30
+ offline = true;
31
+ continue;
32
+ }
33
+ if (argument === '--network') {
34
+ network = true;
35
+ continue;
36
+ }
37
+ if (argument === '--strict') {
38
+ strict = true;
39
+ continue;
40
+ }
41
+ if (argument === '--format') {
42
+ const value = argv[++index];
43
+ if (value !== 'text' && value !== 'json')
44
+ throw new FundGraphCliError('USAGE', '--format requires text or json');
45
+ format = value;
46
+ continue;
47
+ }
48
+ if (argument?.startsWith('--format=')) {
49
+ const value = argument.slice('--format='.length);
50
+ if (value !== 'text' && value !== 'json')
51
+ throw new FundGraphCliError('USAGE', '--format requires text or json');
52
+ format = value;
53
+ continue;
54
+ }
55
+ if (argument?.startsWith('-'))
56
+ throw new FundGraphCliError('USAGE', `Unknown option: ${argument}`);
57
+ if (pathSeen)
58
+ throw new FundGraphCliError('USAGE', 'analyze accepts only one input path');
59
+ inputPath = argument ?? '-';
60
+ pathSeen = true;
61
+ }
62
+ if (offline && network)
63
+ throw new FundGraphCliError('USAGE', '--offline and --network cannot be combined');
64
+ return { command: 'analyze', options: { inputPath, format, offline, network, strict } };
65
+ }
66
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
- {
2
- "name": "fundgraph",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "fundgraph",
3
+ "version": "0.1.0",
4
+ "description": "CLI for evidence-first dependency funding analysis",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "private": false,
8
+ "bin": "./dist/main.js",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "dependencies": {
13
+ "@fundgraph/core": "0.1.0"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.json",
17
+ "lint": "node scripts/lint.mjs",
18
+ "typecheck": "tsc -p tsconfig.json --noEmit",
19
+ "test": "npm run build && node --test test/cli.test.js"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^26.6.4",
23
+ "typescript": "^7.0.2"
24
+ }
25
+ }
26
+