@etherond/topo-cli 0.10.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/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # @topo/cli
2
+
3
+ CLI tool for syncing product context from Topo to your local project.
4
+
5
+ ## Installation
6
+
7
+ No installation required - run directly with npx:
8
+
9
+ ```bash
10
+ npx @topo/cli sync
11
+ ```
12
+
13
+ Or install globally:
14
+
15
+ ```bash
16
+ npm install -g @topo/cli
17
+ topo sync
18
+ ```
19
+
20
+ ## Setup
21
+
22
+ 1. Create an API token in Topo: **Project Settings → API Tokens**
23
+ 2. Add the token to your project's `.env` file:
24
+
25
+ ```bash
26
+ TOPO_API_TOKEN=topo_xxx
27
+ ```
28
+
29
+ Or set it in your shell environment:
30
+
31
+ ```bash
32
+ export TOPO_API_TOKEN=topo_xxx
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```bash
38
+ # Sync product context to default directory (.topo)
39
+ npx @topo/cli sync
40
+
41
+ # Specify output directory
42
+ npx @topo/cli sync --output ./my-docs
43
+
44
+ # Use consolidated format (fewer, larger files)
45
+ npx @topo/cli sync --format consolidated
46
+
47
+ # Pass token directly (alternative to env var)
48
+ npx @topo/cli sync --token topo_xxx
49
+ ```
50
+
51
+ ## Options
52
+
53
+ | Option | Description | Default |
54
+ |--------|-------------|---------|
55
+ | `-o, --output <dir>` | Output directory | `.topo` |
56
+ | `-t, --token <token>` | API token | `TOPO_API_TOKEN` env var |
57
+ | `-f, --format <format>` | `structured` or `consolidated` | `structured` |
58
+ | `--base-url <url>` | API base URL (for development) | `https://topo.prosaic.fr` |
59
+
60
+ ## Output
61
+
62
+ The CLI creates markdown files in a hidden `.topo` directory (signaling these are managed files, not for manual editing):
63
+
64
+ ```
65
+ .topo/
66
+ ├── foundations.md
67
+ ├── ux.md
68
+ └── features/
69
+ └── {area}/{feature}.md
70
+ ```
71
+
72
+ ## Integration with Claude Code
73
+
74
+ When using the Topo MCP server, Claude will automatically suggest running this CLI to sync product context. Just run the command Claude provides.
75
+
76
+ ## Local Development Installation
77
+
78
+ To use the CLI from a local clone of the Topo repository (without publishing to npm), you can link it to your project:
79
+
80
+ ### Option 1: npm link (recommended)
81
+
82
+ ```bash
83
+ # In the topo/packages/cli directory, build and create a global link
84
+ cd /path/to/topo/packages/cli
85
+ npm install
86
+ npm run build
87
+ npm link
88
+
89
+ # In your Next.js project, link to the local package
90
+ cd /path/to/your-nextjs-project
91
+ npm link @topo/cli
92
+
93
+ # Now you can run the CLI
94
+ npx topo sync
95
+ ```
96
+
97
+ To unlink later:
98
+ ```bash
99
+ cd /path/to/your-nextjs-project
100
+ npm unlink @topo/cli
101
+ ```
102
+
103
+ ### Option 2: Direct path execution
104
+
105
+ Run the CLI directly without linking:
106
+
107
+ ```bash
108
+ # From your project directory
109
+ node /path/to/topo/packages/cli/dist/index.js sync
110
+ ```
111
+
112
+ ### Option 3: Add as a local dependency
113
+
114
+ In your Next.js project's `package.json`:
115
+
116
+ ```json
117
+ {
118
+ "devDependencies": {
119
+ "@topo/cli": "file:/path/to/topo/packages/cli"
120
+ }
121
+ }
122
+ ```
123
+
124
+ Then run:
125
+ ```bash
126
+ npm install
127
+ npx topo sync
128
+ ```
129
+
130
+ ## Requirements
131
+
132
+ - Node.js 18+
package/bin/topo.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,3 @@
1
+ import type { SyncOptions } from '../lib/types.js';
2
+ export declare function sync(options: SyncOptions): Promise<void>;
3
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAInD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuG9D"}
@@ -0,0 +1,84 @@
1
+ import { ApiClient, AuthenticationError, AuthorizationError, NotFoundError, } from '../lib/api.js';
2
+ import { writeFiles, PermissionError } from '../lib/files.js';
3
+ const MAX_FILES_TO_DISPLAY = 7;
4
+ export async function sync(options) {
5
+ const token = options.token || process.env.TOPO_API_TOKEN;
6
+ if (!token) {
7
+ console.error('Error: TOPO_API_TOKEN environment variable is not set.\n');
8
+ console.error('Set it with: export TOPO_API_TOKEN=your_token_here\n');
9
+ console.error('You can create an API token in Topo: Project Settings → API Tokens');
10
+ process.exit(1);
11
+ }
12
+ console.log('Fetching product context from Topo...');
13
+ try {
14
+ const client = new ApiClient(options.baseUrl, token);
15
+ const exportData = await client.fetchProductExport();
16
+ console.log('Writing files...\n');
17
+ const result = await writeFiles(options.output, exportData.files, exportData.projectId);
18
+ if (result.errors.length > 0) {
19
+ console.error('Some files could not be written:');
20
+ for (const err of result.errors) {
21
+ console.error(` - ${err.path}: ${err.error}`);
22
+ }
23
+ console.error('');
24
+ }
25
+ if (result.written.length > 0) {
26
+ console.log(`✓ Synced ${result.written.length} files to ${options.output}`);
27
+ // Display file list
28
+ const displayFiles = result.written.slice(0, MAX_FILES_TO_DISPLAY);
29
+ for (const file of displayFiles) {
30
+ console.log(` - ${file}`);
31
+ }
32
+ if (result.written.length > MAX_FILES_TO_DISPLAY) {
33
+ const remaining = result.written.length - MAX_FILES_TO_DISPLAY;
34
+ console.log(` ... and ${remaining} more`);
35
+ }
36
+ }
37
+ else {
38
+ console.log('No files were written.');
39
+ }
40
+ if (result.removed.length > 0) {
41
+ console.log(`\n✓ Removed ${result.removed.length} stale files`);
42
+ const displayRemoved = result.removed.slice(0, MAX_FILES_TO_DISPLAY);
43
+ for (const file of displayRemoved) {
44
+ console.log(` - ${file}`);
45
+ }
46
+ if (result.removed.length > MAX_FILES_TO_DISPLAY) {
47
+ const remaining = result.removed.length - MAX_FILES_TO_DISPLAY;
48
+ console.log(` ... and ${remaining} more`);
49
+ }
50
+ }
51
+ // Exit with error code if some files failed
52
+ if (result.errors.length > 0) {
53
+ process.exit(1);
54
+ }
55
+ }
56
+ catch (err) {
57
+ if (err instanceof AuthenticationError) {
58
+ console.error(`Error: ${err.message}`);
59
+ process.exit(1);
60
+ }
61
+ if (err instanceof AuthorizationError) {
62
+ console.error(`Error: ${err.message}`);
63
+ process.exit(1);
64
+ }
65
+ if (err instanceof NotFoundError) {
66
+ console.error(`Error: ${err.message}`);
67
+ process.exit(1);
68
+ }
69
+ if (err instanceof PermissionError) {
70
+ console.error(`Error: ${err.message}`);
71
+ process.exit(1);
72
+ }
73
+ // Network errors
74
+ if (err instanceof TypeError && err.message?.includes('fetch')) {
75
+ console.error('Error: Network error. Please check your internet connection and try again.');
76
+ process.exit(1);
77
+ }
78
+ // Unknown errors
79
+ const error = err;
80
+ console.error(`Error: ${error.message || 'An unexpected error occurred'}`);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import "dotenv/config";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import "dotenv/config";
2
+ import { Command } from "commander";
3
+ import { sync } from "./commands/sync.js";
4
+ const DEFAULT_BASE_URL = "https://topo.prosaic.fr";
5
+ const DEFAULT_OUTPUT = ".topo";
6
+ const program = new Command();
7
+ program
8
+ .name("topo")
9
+ .description("Topo CLI - Sync product context to your local project")
10
+ .version("1.0.0");
11
+ program
12
+ .command("sync")
13
+ .description("Sync product context from Topo to local files")
14
+ .option("-o, --output <dir>", "Output directory", DEFAULT_OUTPUT)
15
+ .option("-t, --token <token>", "API token (or use TOPO_API_TOKEN env var)")
16
+ .option("--base-url <url>", "Topo API base URL (for development)", DEFAULT_BASE_URL)
17
+ .action(async (opts) => {
18
+ const options = {
19
+ output: opts.output,
20
+ token: opts.token,
21
+ baseUrl: opts.baseUrl,
22
+ };
23
+ await sync(options);
24
+ });
25
+ program.parse();
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAG1C,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AACnD,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,uDAAuD,CAAC;KACpE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,cAAc,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,2CAA2C,CAAC;KAC1E,MAAM,CACL,kBAAkB,EAClB,qCAAqC,EACrC,gBAAgB,CACjB;KACA,MAAM,CAAC,KAAK,EAAE,IAAyD,EAAE,EAAE;IAC1E,MAAM,OAAO,GAAgB;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC;IAEF,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ExportResponse } from './types.js';
2
+ export declare class ApiClient {
3
+ private baseUrl;
4
+ private token;
5
+ constructor(baseUrl: string, token: string);
6
+ fetchProductExport(): Promise<ExportResponse>;
7
+ }
8
+ export declare class AuthenticationError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ export declare class AuthorizationError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ export declare class NotFoundError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare class ApiRequestError extends Error {
18
+ status: number;
19
+ constructor(message: string, status: number);
20
+ }
21
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,YAAY,CAAC;AAE3D,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAKpC,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC;CAiDpD;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK5C"}
@@ -0,0 +1,71 @@
1
+ export class ApiClient {
2
+ baseUrl;
3
+ token;
4
+ constructor(baseUrl, token) {
5
+ this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
6
+ this.token = token;
7
+ }
8
+ async fetchProductExport() {
9
+ const url = new URL('/api/cli/export', this.baseUrl);
10
+ const response = await fetch(url.toString(), {
11
+ method: 'GET',
12
+ headers: {
13
+ Authorization: `Bearer ${this.token}`,
14
+ 'Content-Type': 'application/json',
15
+ },
16
+ });
17
+ if (!response.ok) {
18
+ const status = response.status;
19
+ if (status === 401) {
20
+ throw new AuthenticationError('Invalid API token. Please check your TOPO_API_TOKEN.\n\n' +
21
+ 'You can create a new token in Topo: Project Settings → API Tokens');
22
+ }
23
+ if (status === 403) {
24
+ throw new AuthorizationError('Access denied. Your token may not have access to this project.');
25
+ }
26
+ if (status === 404) {
27
+ throw new NotFoundError('Project not found. Please check that your token is valid.');
28
+ }
29
+ // Try to get error message from response
30
+ let errorMessage = `Request failed with status ${status}`;
31
+ try {
32
+ const errorBody = (await response.json());
33
+ if (errorBody.message || errorBody.error) {
34
+ errorMessage = errorBody.message || errorBody.error;
35
+ }
36
+ }
37
+ catch {
38
+ // Ignore JSON parse errors
39
+ }
40
+ throw new ApiRequestError(errorMessage, status);
41
+ }
42
+ return (await response.json());
43
+ }
44
+ }
45
+ export class AuthenticationError extends Error {
46
+ constructor(message) {
47
+ super(message);
48
+ this.name = 'AuthenticationError';
49
+ }
50
+ }
51
+ export class AuthorizationError extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = 'AuthorizationError';
55
+ }
56
+ }
57
+ export class NotFoundError extends Error {
58
+ constructor(message) {
59
+ super(message);
60
+ this.name = 'NotFoundError';
61
+ }
62
+ }
63
+ export class ApiRequestError extends Error {
64
+ status;
65
+ constructor(message, status) {
66
+ super(message);
67
+ this.name = 'ApiRequestError';
68
+ this.status = status;
69
+ }
70
+ }
71
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,SAAS;IACZ,OAAO,CAAS;IAChB,KAAK,CAAS;IAEtB,YAAY,OAAe,EAAE,KAAa;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,wBAAwB;QACnE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;gBACrC,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAE/B,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,mBAAmB,CAC3B,0DAA0D;oBACxD,mEAAmE,CACtE,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,kBAAkB,CAC1B,gEAAgE,CACjE,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,aAAa,CACrB,2DAA2D,CAC5D,CAAC;YACJ,CAAC;YAED,yCAAyC;YACzC,IAAI,YAAY,GAAG,8BAA8B,MAAM,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAa,CAAC;gBACtD,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;oBACzC,YAAY,GAAG,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC;gBACtD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;YAED,MAAM,IAAI,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;IACnD,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,MAAM,CAAS;IAEf,YAAY,OAAe,EAAE,MAAc;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { ExportFile } from './types.js';
2
+ export interface WriteResult {
3
+ written: string[];
4
+ removed: string[];
5
+ errors: Array<{
6
+ path: string;
7
+ error: string;
8
+ }>;
9
+ }
10
+ export declare function writeFiles(outputDir: string, files: ExportFile[], projectId: string): Promise<WriteResult>;
11
+ export declare class PermissionError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/lib/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAI3D,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAwGtB;AAqDD,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,140 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ const MANIFEST_FILENAME = '.topo-manifest.json';
4
+ export async function writeFiles(outputDir, files, projectId) {
5
+ const result = {
6
+ written: [],
7
+ removed: [],
8
+ errors: [],
9
+ };
10
+ // Ensure output directory exists
11
+ try {
12
+ await fs.mkdir(outputDir, { recursive: true });
13
+ }
14
+ catch (err) {
15
+ const error = err;
16
+ if (error.code === 'EACCES') {
17
+ throw new PermissionError(`Permission denied: Cannot create output directory '${outputDir}'`);
18
+ }
19
+ throw error;
20
+ }
21
+ // Read existing manifest and remove stale files
22
+ const manifestPath = path.join(outputDir, MANIFEST_FILENAME);
23
+ const existingManifest = await readManifest(manifestPath);
24
+ const newFilePaths = new Set(files.map((f) => f.path));
25
+ if (existingManifest) {
26
+ const staleFiles = existingManifest.files.filter((f) => !newFilePaths.has(f));
27
+ for (const staleFile of staleFiles) {
28
+ const fullPath = path.join(outputDir, staleFile);
29
+ try {
30
+ await fs.unlink(fullPath);
31
+ result.removed.push(staleFile);
32
+ }
33
+ catch (err) {
34
+ const error = err;
35
+ // Ignore if file doesn't exist (already removed)
36
+ if (error.code !== 'ENOENT') {
37
+ result.errors.push({
38
+ path: staleFile,
39
+ error: `Failed to remove: ${error.message || 'Unknown error'}`,
40
+ });
41
+ }
42
+ }
43
+ }
44
+ // Clean up empty directories left after removing files
45
+ await cleanupEmptyDirectories(outputDir, staleFiles);
46
+ }
47
+ // Collect all unique directories that need to be created
48
+ const directories = new Set();
49
+ for (const file of files) {
50
+ const fullPath = path.join(outputDir, file.path);
51
+ const dir = path.dirname(fullPath);
52
+ if (dir !== outputDir) {
53
+ directories.add(dir);
54
+ }
55
+ }
56
+ // Create all directories
57
+ for (const dir of directories) {
58
+ try {
59
+ await fs.mkdir(dir, { recursive: true });
60
+ }
61
+ catch (err) {
62
+ const error = err;
63
+ if (error.code === 'EACCES') {
64
+ throw new PermissionError(`Permission denied: Cannot create directory '${dir}'`);
65
+ }
66
+ throw error;
67
+ }
68
+ }
69
+ // Write all files
70
+ await Promise.all(files.map(async (file) => {
71
+ const fullPath = path.join(outputDir, file.path);
72
+ try {
73
+ await fs.writeFile(fullPath, file.content, 'utf-8');
74
+ result.written.push(file.path);
75
+ }
76
+ catch (err) {
77
+ const error = err;
78
+ result.errors.push({
79
+ path: file.path,
80
+ error: error.code === 'EACCES'
81
+ ? 'Permission denied'
82
+ : error.message || 'Unknown error',
83
+ });
84
+ }
85
+ }));
86
+ // Write manifest with successfully written files
87
+ const manifest = {
88
+ syncedAt: new Date().toISOString(),
89
+ projectId,
90
+ files: result.written,
91
+ };
92
+ await writeManifest(manifestPath, manifest);
93
+ return result;
94
+ }
95
+ async function readManifest(manifestPath) {
96
+ try {
97
+ const content = await fs.readFile(manifestPath, 'utf-8');
98
+ return JSON.parse(content);
99
+ }
100
+ catch (err) {
101
+ const error = err;
102
+ // Return null if manifest doesn't exist or is invalid
103
+ if (error.code === 'ENOENT') {
104
+ return null;
105
+ }
106
+ // Log warning for corrupted manifest but continue
107
+ console.warn(`Warning: Could not read manifest file: ${error.message}`);
108
+ return null;
109
+ }
110
+ }
111
+ async function writeManifest(manifestPath, manifest) {
112
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');
113
+ }
114
+ async function cleanupEmptyDirectories(outputDir, removedFiles) {
115
+ // Get unique directories from removed files, sorted by depth (deepest first)
116
+ const directories = [
117
+ ...new Set(removedFiles
118
+ .map((f) => path.dirname(f))
119
+ .filter((d) => d !== '.')),
120
+ ].sort((a, b) => b.split(path.sep).length - a.split(path.sep).length);
121
+ for (const dir of directories) {
122
+ const fullPath = path.join(outputDir, dir);
123
+ try {
124
+ const entries = await fs.readdir(fullPath);
125
+ if (entries.length === 0) {
126
+ await fs.rmdir(fullPath);
127
+ }
128
+ }
129
+ catch {
130
+ // Ignore errors - directory might not exist or not be empty
131
+ }
132
+ }
133
+ }
134
+ export class PermissionError extends Error {
135
+ constructor(message) {
136
+ super(message);
137
+ this.name = 'PermissionError';
138
+ }
139
+ }
140
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/lib/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface SyncOptions {
2
+ output: string;
3
+ token?: string;
4
+ baseUrl: string;
5
+ }
6
+ export interface ExportFile {
7
+ path: string;
8
+ content: string;
9
+ }
10
+ export interface ExportResponse {
11
+ exportedAt: string;
12
+ projectId: string;
13
+ projectName: string;
14
+ version: string;
15
+ files: ExportFile[];
16
+ }
17
+ export interface ApiError {
18
+ error: string;
19
+ message?: string;
20
+ }
21
+ export interface SyncManifest {
22
+ syncedAt: string;
23
+ projectId: string;
24
+ files: string[];
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@etherond/topo-cli",
3
+ "version": "0.10.0",
4
+ "description": "Topo CLI - Sync product context to your local project",
5
+ "type": "module",
6
+ "bin": {
7
+ "topo": "./bin/topo.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "topo",
20
+ "cli",
21
+ "product",
22
+ "context",
23
+ "ai",
24
+ "claude"
25
+ ],
26
+ "author": "",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "commander": "^12.1.0",
30
+ "dotenv": "^16.4.5"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20.10.0",
34
+ "typescript": "^5.3.0"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ }
39
+ }