cadr-cli 0.0.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/bin/cadr.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Executable wrapper for cadr-cli
4
+ // This file is the entry point when running 'cadr' command
5
+
6
+ const { displayWelcome, processStagedFiles } = require('../dist/index.js');
7
+
8
+ // Display welcome message first
9
+ displayWelcome();
10
+
11
+ // Then process staged files
12
+ processStagedFiles().catch((error) => {
13
+ console.error('Failed to process staged files:', error.message);
14
+ process.exit(1);
15
+ });
16
+
package/dist/git.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare class GitError extends Error {
2
+ readonly code: 'NOT_GIT_REPO' | 'GIT_NOT_FOUND' | 'GIT_ERROR';
3
+ readonly originalError?: Error | undefined;
4
+ constructor(message: string, code: 'NOT_GIT_REPO' | 'GIT_NOT_FOUND' | 'GIT_ERROR', originalError?: Error | undefined);
5
+ }
6
+ /**
7
+ * Retrieves the list of staged files in the current Git repository
8
+ * @returns Promise<string[]> Array of staged file paths
9
+ * @throws GitError When Git is not available or repository is invalid
10
+ */
11
+ export declare function getStagedFiles(): Promise<string[]>;
12
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAKA,qBAAa,QAAS,SAAQ,KAAK;aAGf,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,WAAW;aACpD,aAAa,CAAC,EAAE,KAAK;gBAFrC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,WAAW,EACpD,aAAa,CAAC,EAAE,KAAK,YAAA;CAKxC;AAED;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAsCxD"}
package/dist/git.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitError = void 0;
4
+ exports.getStagedFiles = getStagedFiles;
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
8
+ class GitError extends Error {
9
+ code;
10
+ originalError;
11
+ constructor(message, code, originalError) {
12
+ super(message);
13
+ this.code = code;
14
+ this.originalError = originalError;
15
+ this.name = 'GitError';
16
+ }
17
+ }
18
+ exports.GitError = GitError;
19
+ /**
20
+ * Retrieves the list of staged files in the current Git repository
21
+ * @returns Promise<string[]> Array of staged file paths
22
+ * @throws GitError When Git is not available or repository is invalid
23
+ */
24
+ async function getStagedFiles() {
25
+ try {
26
+ const { stdout } = await execAsync('git diff --cached --name-only');
27
+ // Split by newlines and filter out empty strings
28
+ const stagedFiles = stdout
29
+ .split('\n')
30
+ .map(file => file.trim())
31
+ .filter(file => file.length > 0);
32
+ return stagedFiles;
33
+ }
34
+ catch (error) {
35
+ // Handle different Git error scenarios
36
+ const errorWithCode = error;
37
+ if (errorWithCode.code === 128) {
38
+ throw new GitError('Not in a Git repository. Please run \'cadr\' from within a Git repository.', 'NOT_GIT_REPO', error instanceof Error ? error : new Error(String(error)));
39
+ }
40
+ if (errorWithCode.code === 127) {
41
+ throw new GitError('Git is not installed. Please install Git and try again.', 'GIT_NOT_FOUND', error instanceof Error ? error : new Error(String(error)));
42
+ }
43
+ // Handle other Git errors (permissions, corruption, etc.)
44
+ throw new GitError('Unable to read Git repository. Please check repository permissions.', 'GIT_ERROR', error instanceof Error ? error : new Error(String(error)));
45
+ }
46
+ }
47
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":";;;AAqBA,wCAsCC;AA3DD,iDAAqC;AACrC,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAElC,MAAa,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,IAAoD,EACpD,aAAqB;QAErC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAgD;QACpD,kBAAa,GAAb,aAAa,CAAQ;QAGrC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AATD,4BASC;AAED;;;;GAIG;AACI,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAEpE,iDAAiD;QACjD,MAAM,WAAW,GAAG,MAAM;aACvB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEnC,OAAO,WAAW,CAAC;IACrB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,uCAAuC;QACvC,MAAM,aAAa,GAAG,KAA0B,CAAC;QAEjD,IAAI,aAAa,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAChB,4EAA4E,EAC5E,cAAc,EACd,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAChB,yDAAyD,EACzD,eAAe,EACf,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CAAC;QACJ,CAAC;QAED,0DAA0D;QAC1D,MAAM,IAAI,QAAQ,CAChB,qEAAqE,EACrE,WAAW,EACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function getWelcomeMessage(): string;
2
+ export declare function displayWelcome(): void;
3
+ export declare function processStagedFiles(): Promise<void>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,wBAAgB,iBAAiB,IAAI,MAAM,CAY1C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmCxD"}
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWelcomeMessage = getWelcomeMessage;
4
+ exports.displayWelcome = displayWelcome;
5
+ exports.processStagedFiles = processStagedFiles;
6
+ const git_1 = require("./git");
7
+ const logger_1 = require("./logger");
8
+ // Version constants
9
+ const CORE_VERSION = '0.0.1';
10
+ const CLI_VERSION = '0.0.1';
11
+ // Parse command line arguments
12
+ const args = process.argv.slice(2);
13
+ const isVerbose = args.includes('--verbose') || args.includes('-v');
14
+ function getWelcomeMessage() {
15
+ return `šŸŽ‰ Hello, cADR!
16
+
17
+ cADR (Continuous Architectural Decision Records) helps you automatically
18
+ capture and document architectural decisions as you code.
19
+
20
+ Version: ${CLI_VERSION}
21
+ Core: ${CORE_VERSION}
22
+ Learn more: https://github.com/YotpoLtd/cADR
23
+
24
+ Get started by running 'cadr --verbose' to see detailed logs
25
+ `;
26
+ }
27
+ function displayWelcome() {
28
+ // Use process.stdout.write instead of console.log (Constitution: no console.log)
29
+ process.stdout.write(getWelcomeMessage());
30
+ }
31
+ async function processStagedFiles() {
32
+ try {
33
+ const stagedFiles = await (0, git_1.getStagedFiles)();
34
+ // Display staged files to user
35
+ if (stagedFiles.length > 0) {
36
+ process.stdout.write(`\nšŸ“ Found ${stagedFiles.length} staged file${stagedFiles.length === 1 ? '' : 's'}:\n`);
37
+ stagedFiles.forEach((file) => {
38
+ process.stdout.write(` • ${file}\n`);
39
+ });
40
+ }
41
+ else {
42
+ process.stdout.write(`\nšŸ“ No staged files found.\n`);
43
+ }
44
+ // Only log for debugging when verbose mode is enabled
45
+ if (isVerbose) {
46
+ logger_1.loggerInstance.info('Retrieved staged files', {
47
+ staged_files: stagedFiles,
48
+ count: stagedFiles.length
49
+ });
50
+ }
51
+ }
52
+ catch (error) {
53
+ if (error instanceof git_1.GitError) {
54
+ // Display helpful error message to stdout
55
+ process.stdout.write(`\nāŒ ${error.message}\n`);
56
+ process.exit(1);
57
+ }
58
+ else {
59
+ // Log unexpected errors (always show errors)
60
+ const errorMessage = error instanceof Error ? error.message : String(error);
61
+ logger_1.loggerInstance.error('Unexpected error occurred', {
62
+ error: errorMessage
63
+ });
64
+ process.exit(1);
65
+ }
66
+ }
67
+ }
68
+ // Main execution block - run when module is executed directly
69
+ if (require.main === module) {
70
+ // Display welcome message first
71
+ displayWelcome();
72
+ // Then process staged files
73
+ processStagedFiles().catch((error) => {
74
+ logger_1.loggerInstance.error('Failed to process staged files', {
75
+ error: error instanceof Error ? error.message : String(error)
76
+ });
77
+ process.exit(1);
78
+ });
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAWA,8CAYC;AAED,wCAGC;AAED,gDAmCC;AAjED,+BAAiD;AACjD,qCAA0C;AAE1C,oBAAoB;AACpB,MAAM,YAAY,GAAG,OAAO,CAAC;AAC7B,MAAM,WAAW,GAAG,OAAO,CAAC;AAE5B,+BAA+B;AAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAEpE,SAAgB,iBAAiB;IAC/B,OAAO;;;;;WAKE,WAAW;QACd,YAAY;;;;CAInB,CAAC;AACF,CAAC;AAED,SAAgB,cAAc;IAC5B,iFAAiF;IACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAC5C,CAAC;AAEM,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,IAAA,oBAAc,GAAE,CAAC;QAE3C,+BAA+B;QAC/B,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,WAAW,CAAC,MAAM,eAAe,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;YAC9G,WAAW,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,EAAE;gBACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACxD,CAAC;QAED,sDAAsD;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,uBAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE;gBAC5C,YAAY,EAAE,WAAW;gBACzB,KAAK,EAAE,WAAW,CAAC,MAAM;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,cAAQ,EAAE,CAAC;YAC9B,0CAA0C;YAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,6CAA6C;YAC7C,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,uBAAc,CAAC,KAAK,CAAC,2BAA2B,EAAE;gBAChD,KAAK,EAAE,YAAY;aACpB,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,gCAAgC;IAChC,cAAc,EAAE,CAAC;IAEjB,4BAA4B;IAC5B,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,uBAAc,CAAC,KAAK,CAAC,gCAAgC,EAAE;YACrD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare class Logger {
2
+ info(message: string, context?: object): void;
3
+ warn(message: string, context?: object): void;
4
+ error(message: string, context?: object): void;
5
+ }
6
+ export declare const loggerInstance: Logger;
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAWA,qBAAa,MAAM;IACjB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;CAO/C;AAGD,eAAO,MAAM,cAAc,QAAe,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loggerInstance = exports.Logger = void 0;
7
+ const pino_1 = __importDefault(require("pino"));
8
+ // Configure Pino to output JSON to stderr
9
+ const logger = (0, pino_1.default)({
10
+ level: 'info',
11
+ transport: {
12
+ target: 'pino/file',
13
+ options: { destination: 2 } // stderr
14
+ }
15
+ });
16
+ class Logger {
17
+ info(message, context) {
18
+ if (context) {
19
+ logger.info(context, message);
20
+ }
21
+ else {
22
+ logger.info(message);
23
+ }
24
+ }
25
+ warn(message, context) {
26
+ if (context) {
27
+ logger.warn(context, message);
28
+ }
29
+ else {
30
+ logger.warn(message);
31
+ }
32
+ }
33
+ error(message, context) {
34
+ if (context) {
35
+ logger.error(context, message);
36
+ }
37
+ else {
38
+ logger.error(message);
39
+ }
40
+ }
41
+ }
42
+ exports.Logger = Logger;
43
+ // Export singleton logger instance
44
+ exports.loggerInstance = new Logger();
45
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,0CAA0C;AAC1C,MAAM,MAAM,GAAG,IAAA,cAAI,EAAC;IAClB,KAAK,EAAE,MAAM;IACb,SAAS,EAAE;QACT,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,SAAS;KACtC;CACF,CAAC,CAAC;AAEH,MAAa,MAAM;IACjB,IAAI,CAAC,OAAe,EAAE,OAAgB;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAAgB;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAgB;QACrC,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;CACF;AAxBD,wBAwBC;AAED,mCAAmC;AACtB,QAAA,cAAc,GAAG,IAAI,MAAM,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "cadr-cli",
3
+ "version": "0.0.1",
4
+ "description": "Continuous Architectural Decision Records - Automatically capture ADRs as you code",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "cadr": "./bin/cadr.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "jest"
12
+ },
13
+ "keywords": [
14
+ "adr",
15
+ "architecture",
16
+ "cli",
17
+ "decision-records",
18
+ "documentation"
19
+ ],
20
+ "author": "",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/YotpoLtd/cADR.git"
25
+ },
26
+ "engines": {
27
+ "node": ">=20.0.0"
28
+ },
29
+ "dependencies": {
30
+ "pino": "^8.17.2"
31
+ }
32
+ }
package/src/git.ts ADDED
@@ -0,0 +1,60 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+
4
+ const execAsync = promisify(exec);
5
+
6
+ export class GitError extends Error {
7
+ constructor(
8
+ message: string,
9
+ public readonly code: 'NOT_GIT_REPO' | 'GIT_NOT_FOUND' | 'GIT_ERROR',
10
+ public readonly originalError?: Error
11
+ ) {
12
+ super(message);
13
+ this.name = 'GitError';
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Retrieves the list of staged files in the current Git repository
19
+ * @returns Promise<string[]> Array of staged file paths
20
+ * @throws GitError When Git is not available or repository is invalid
21
+ */
22
+ export async function getStagedFiles(): Promise<string[]> {
23
+ try {
24
+ const { stdout } = await execAsync('git diff --cached --name-only');
25
+
26
+ // Split by newlines and filter out empty strings
27
+ const stagedFiles = stdout
28
+ .split('\n')
29
+ .map(file => file.trim())
30
+ .filter(file => file.length > 0);
31
+
32
+ return stagedFiles;
33
+ } catch (error: unknown) {
34
+ // Handle different Git error scenarios
35
+ const errorWithCode = error as { code?: number };
36
+
37
+ if (errorWithCode.code === 128) {
38
+ throw new GitError(
39
+ 'Not in a Git repository. Please run \'cadr\' from within a Git repository.',
40
+ 'NOT_GIT_REPO',
41
+ error instanceof Error ? error : new Error(String(error))
42
+ );
43
+ }
44
+
45
+ if (errorWithCode.code === 127) {
46
+ throw new GitError(
47
+ 'Git is not installed. Please install Git and try again.',
48
+ 'GIT_NOT_FOUND',
49
+ error instanceof Error ? error : new Error(String(error))
50
+ );
51
+ }
52
+
53
+ // Handle other Git errors (permissions, corruption, etc.)
54
+ throw new GitError(
55
+ 'Unable to read Git repository. Please check repository permissions.',
56
+ 'GIT_ERROR',
57
+ error instanceof Error ? error : new Error(String(error))
58
+ );
59
+ }
60
+ }
package/src/index.ts ADDED
@@ -0,0 +1,80 @@
1
+ import { getStagedFiles, GitError } from './git';
2
+ import { loggerInstance } from './logger';
3
+
4
+ // Version constants
5
+ const CORE_VERSION = '0.0.1';
6
+ const CLI_VERSION = '0.0.1';
7
+
8
+ // Parse command line arguments
9
+ const args = process.argv.slice(2);
10
+ const isVerbose = args.includes('--verbose') || args.includes('-v');
11
+
12
+ export function getWelcomeMessage(): string {
13
+ return `šŸŽ‰ Hello, cADR!
14
+
15
+ cADR (Continuous Architectural Decision Records) helps you automatically
16
+ capture and document architectural decisions as you code.
17
+
18
+ Version: ${CLI_VERSION}
19
+ Core: ${CORE_VERSION}
20
+ Learn more: https://github.com/YotpoLtd/cADR
21
+
22
+ Get started by running 'cadr --verbose' to see detailed logs
23
+ `;
24
+ }
25
+
26
+ export function displayWelcome(): void {
27
+ // Use process.stdout.write instead of console.log (Constitution: no console.log)
28
+ process.stdout.write(getWelcomeMessage());
29
+ }
30
+
31
+ export async function processStagedFiles(): Promise<void> {
32
+ try {
33
+ const stagedFiles = await getStagedFiles();
34
+
35
+ // Display staged files to user
36
+ if (stagedFiles.length > 0) {
37
+ process.stdout.write(`\nšŸ“ Found ${stagedFiles.length} staged file${stagedFiles.length === 1 ? '' : 's'}:\n`);
38
+ stagedFiles.forEach((file: string) => {
39
+ process.stdout.write(` • ${file}\n`);
40
+ });
41
+ } else {
42
+ process.stdout.write(`\nšŸ“ No staged files found.\n`);
43
+ }
44
+
45
+ // Only log for debugging when verbose mode is enabled
46
+ if (isVerbose) {
47
+ loggerInstance.info('Retrieved staged files', {
48
+ staged_files: stagedFiles,
49
+ count: stagedFiles.length
50
+ });
51
+ }
52
+ } catch (error: unknown) {
53
+ if (error instanceof GitError) {
54
+ // Display helpful error message to stdout
55
+ process.stdout.write(`\nāŒ ${error.message}\n`);
56
+ process.exit(1);
57
+ } else {
58
+ // Log unexpected errors (always show errors)
59
+ const errorMessage = error instanceof Error ? error.message : String(error);
60
+ loggerInstance.error('Unexpected error occurred', {
61
+ error: errorMessage
62
+ });
63
+ process.exit(1);
64
+ }
65
+ }
66
+ }
67
+
68
+ // Main execution block - run when module is executed directly
69
+ if (require.main === module) {
70
+ // Display welcome message first
71
+ displayWelcome();
72
+
73
+ // Then process staged files
74
+ processStagedFiles().catch((error) => {
75
+ loggerInstance.error('Failed to process staged files', {
76
+ error: error instanceof Error ? error.message : String(error)
77
+ });
78
+ process.exit(1);
79
+ });
80
+ }
package/src/logger.ts ADDED
@@ -0,0 +1,39 @@
1
+ import pino from 'pino';
2
+
3
+ // Configure Pino to output JSON to stderr
4
+ const logger = pino({
5
+ level: 'info',
6
+ transport: {
7
+ target: 'pino/file',
8
+ options: { destination: 2 } // stderr
9
+ }
10
+ });
11
+
12
+ export class Logger {
13
+ info(message: string, context?: object): void {
14
+ if (context) {
15
+ logger.info(context, message);
16
+ } else {
17
+ logger.info(message);
18
+ }
19
+ }
20
+
21
+ warn(message: string, context?: object): void {
22
+ if (context) {
23
+ logger.warn(context, message);
24
+ } else {
25
+ logger.warn(message);
26
+ }
27
+ }
28
+
29
+ error(message: string, context?: object): void {
30
+ if (context) {
31
+ logger.error(context, message);
32
+ } else {
33
+ logger.error(message);
34
+ }
35
+ }
36
+ }
37
+
38
+ // Export singleton logger instance
39
+ export const loggerInstance = new Logger();
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "references": []
9
+ }