atabey-shared 0.0.19

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAEA,IAAI,QAAQ,GAA6B,IAAI,CAAC;AAE9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC1B,KAAK,CAAC,EAAqB;QACvB,QAAQ,GAAG,EAAE,CAAC;IAClB,CAAC;IACD,KAAK;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Enterprise Base Error class for the Agent Atabey Framework.
3
+ */
4
+ export declare class AtabeyBaseError extends Error {
5
+ readonly code: string;
6
+ readonly timestamp: Date;
7
+ readonly details?: unknown;
8
+ readonly solution?: string;
9
+ constructor(message: string, code?: string, details?: unknown, solution?: string);
10
+ /**
11
+ * Converts the error into a structured JSON log format.
12
+ */
13
+ toJSON(): {
14
+ name: string;
15
+ message: string;
16
+ code: string;
17
+ timestamp: string;
18
+ details: unknown;
19
+ solution: string | undefined;
20
+ stack: string | undefined;
21
+ };
22
+ }
23
+ /**
24
+ * Thrown when configuration loading or validation fails.
25
+ */
26
+ export declare class ConfigurationError extends AtabeyBaseError {
27
+ constructor(message: string, details?: unknown, solution?: string);
28
+ }
29
+ /**
30
+ * Thrown when data schema or payload validation fails.
31
+ */
32
+ export declare class ValidationError extends AtabeyBaseError {
33
+ constructor(message: string, details?: unknown, solution?: string);
34
+ }
35
+ /**
36
+ * Thrown when adapter initialization or execution fails.
37
+ */
38
+ export declare class AdapterError extends AtabeyBaseError {
39
+ constructor(message: string, adapterId: string, details?: unknown, solution?: string);
40
+ }
41
+ /**
42
+ * Thrown when orchestration or agent communication fails.
43
+ */
44
+ export declare class OrchestrationError extends AtabeyBaseError {
45
+ constructor(message: string, details?: unknown, solution?: string);
46
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Enterprise Base Error class for the Agent Atabey Framework.
3
+ */
4
+ export class AtabeyBaseError extends Error {
5
+ code;
6
+ timestamp;
7
+ details;
8
+ solution;
9
+ constructor(message, code = "ATABEY_INTERNAL_ERROR", details, solution) {
10
+ super(message);
11
+ this.name = this.constructor.name;
12
+ this.code = code;
13
+ this.timestamp = new Date();
14
+ this.details = details;
15
+ this.solution = solution;
16
+ // Ensure proper prototype chain and capture stack trace
17
+ Object.setPrototypeOf(this, new.target.prototype);
18
+ if (Error.captureStackTrace) {
19
+ Error.captureStackTrace(this, this.constructor);
20
+ }
21
+ }
22
+ /**
23
+ * Converts the error into a structured JSON log format.
24
+ */
25
+ toJSON() {
26
+ return {
27
+ name: this.name,
28
+ message: this.message,
29
+ code: this.code,
30
+ timestamp: this.timestamp.toISOString(),
31
+ details: this.details,
32
+ solution: this.solution,
33
+ stack: this.stack,
34
+ };
35
+ }
36
+ }
37
+ /**
38
+ * Thrown when configuration loading or validation fails.
39
+ */
40
+ export class ConfigurationError extends AtabeyBaseError {
41
+ constructor(message, details, solution) {
42
+ super(message, "CONFIGURATION_ERROR", details, solution);
43
+ }
44
+ }
45
+ /**
46
+ * Thrown when data schema or payload validation fails.
47
+ */
48
+ export class ValidationError extends AtabeyBaseError {
49
+ constructor(message, details, solution) {
50
+ super(message, "VALIDATION_ERROR", details, solution);
51
+ }
52
+ }
53
+ /**
54
+ * Thrown when adapter initialization or execution fails.
55
+ */
56
+ export class AdapterError extends AtabeyBaseError {
57
+ constructor(message, adapterId, details, solution) {
58
+ super(`Adapter '${adapterId}' failure: ${message}`, "ADAPTER_ERROR", details, solution);
59
+ }
60
+ }
61
+ /**
62
+ * Thrown when orchestration or agent communication fails.
63
+ */
64
+ export class OrchestrationError extends AtabeyBaseError {
65
+ constructor(message, details, solution) {
66
+ super(message, "ORCHESTRATION_ERROR", details, solution);
67
+ }
68
+ }
69
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACtB,IAAI,CAAS;IACb,SAAS,CAAO;IAChB,OAAO,CAAW;IAClB,QAAQ,CAAU;IAElC,YAAY,OAAe,EAAE,IAAI,GAAG,uBAAuB,EAAE,OAAiB,EAAE,QAAiB;QAC7F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,wDAAwD;QACxD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC;IACL,CAAC;IAED;;OAEG;IACI,MAAM;QACT,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YACvC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;SACpB,CAAC;IACN,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IACnD,YAAY,OAAe,EAAE,OAAiB,EAAE,QAAiB;QAC7D,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,eAAe;IAChD,YAAY,OAAe,EAAE,OAAiB,EAAE,QAAiB;QAC7D,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,eAAe;IAC7C,YAAY,OAAe,EAAE,SAAiB,EAAE,OAAiB,EAAE,QAAiB;QAChF,KAAK,CAAC,YAAY,SAAS,cAAc,OAAO,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC5F,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IACnD,YAAY,OAAe,EAAE,OAAiB,EAAE,QAAiB;QAC7D,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;CACJ"}
package/dist/fs.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare function ensureDir(dirPath: string, dryRun?: boolean): void;
2
+ /**
3
+ * Writes content to a file atomically by using a temporary file.
4
+ * This prevents data corruption during unexpected system failures.
5
+ */
6
+ export declare function writeTextFile(filePath: string, content: string, dryRun?: boolean): void;
7
+ export declare function appendFile(filePath: string, content: string, dryRun?: boolean): void;
8
+ export declare function writeJsonFile(filePath: string, value: unknown, dryRun?: boolean): void;
9
+ export declare function runCommandQuiet(command: string, args: string[], cwd: string): void;
package/dist/fs.js ADDED
@@ -0,0 +1,54 @@
1
+ import { execFileSync } from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { logger } from "./logger.js";
5
+ export function ensureDir(dirPath, dryRun = false) {
6
+ if (!fs.existsSync(dirPath)) {
7
+ if (dryRun) {
8
+ logger.info(`[DRY RUN] Would create directory: ${dirPath}`);
9
+ }
10
+ else {
11
+ fs.mkdirSync(dirPath, { recursive: true });
12
+ }
13
+ }
14
+ }
15
+ /**
16
+ * Writes content to a file atomically by using a temporary file.
17
+ * This prevents data corruption during unexpected system failures.
18
+ */
19
+ export function writeTextFile(filePath, content, dryRun = false) {
20
+ if (dryRun) {
21
+ logger.info(`[DRY RUN] Would write file: ${filePath}`);
22
+ return;
23
+ }
24
+ const dir = path.dirname(filePath);
25
+ ensureDir(dir);
26
+ const tempPath = `${filePath}.${Math.random().toString(36).slice(2, 9)}.tmp`;
27
+ const finalContent = content.endsWith("\n") ? content : `${content}\n`;
28
+ try {
29
+ fs.writeFileSync(tempPath, finalContent, "utf8");
30
+ fs.renameSync(tempPath, filePath);
31
+ }
32
+ catch (err) {
33
+ if (fs.existsSync(tempPath))
34
+ fs.unlinkSync(tempPath);
35
+ throw err;
36
+ }
37
+ }
38
+ export function appendFile(filePath, content, dryRun = false) {
39
+ if (dryRun) {
40
+ logger.info(`[DRY RUN] Would append to file: ${filePath}`);
41
+ return;
42
+ }
43
+ ensureDir(path.dirname(filePath));
44
+ // Atomic append: oku → ekle → atomic yaz
45
+ const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : "";
46
+ writeTextFile(filePath, existing + content);
47
+ }
48
+ export function writeJsonFile(filePath, value, dryRun = false) {
49
+ writeTextFile(filePath, JSON.stringify(value, null, 2), dryRun);
50
+ }
51
+ export function runCommandQuiet(command, args, cwd) {
52
+ execFileSync(command, args, { cwd, stdio: "ignore" });
53
+ }
54
+ //# sourceMappingURL=fs.js.map
package/dist/fs.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,MAAM,GAAG,KAAK;IACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,qCAAqC,OAAO,EAAE,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACJ,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAM,GAAG,KAAK;IAC3E,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;QACvD,OAAO;IACX,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEf,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;IAC7E,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC;IAEvE,IAAI,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,GAAG,CAAC;IACd,CAAC;AACL,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAM,GAAG,KAAK;IACxE,IAAI,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAC3D,OAAO;IACX,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,yCAAyC;IACzC,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,KAAc,EAAE,MAAM,GAAG,KAAK;IAC1E,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW;IACxE,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,11 @@
1
+ export * from "./database.js";
2
+ export * from "./pii.js";
3
+ export * from "./lock.js";
4
+ export * from "./audit.js";
5
+ export * from "./logger.js";
6
+ export * from "./retention.js";
7
+ export * from "./errors.js";
8
+ export * from "./constants.js";
9
+ export * from "./string.js";
10
+ export * from "./types.js";
11
+ export * from "./fs.js";
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export * from "./database.js";
2
+ export * from "./pii.js";
3
+ export * from "./lock.js";
4
+ export * from "./audit.js";
5
+ export * from "./logger.js";
6
+ export * from "./retention.js";
7
+ export * from "./errors.js";
8
+ export * from "./constants.js";
9
+ export * from "./string.js";
10
+ export * from "./types.js";
11
+ export * from "./fs.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
package/dist/lock.d.ts ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * [LOCK] Multi-user Distributed Lock Mechanism
3
+ *
4
+ * Git-based lock system. Enables team members to work on the same
5
+ * files/resources without conflicts.
6
+ *
7
+ * Usage:
8
+ * const lock = new DistributedLock("database/schema.sql");
9
+ * if (lock.acquire("user-123", 60000)) {
10
+ * // Apply changes
11
+ * lock.release("user-123");
12
+ * }
13
+ */
14
+ export type LockStatus = "LOCKED" | "AVAILABLE" | "STALE" | "EXPIRED";
15
+ export interface LockInfo {
16
+ resource: string;
17
+ ownerId: string;
18
+ ownerName: string;
19
+ acquiredAt: string;
20
+ expiresAt: string;
21
+ reason: string;
22
+ traceId?: string;
23
+ }
24
+ export declare class DistributedLock {
25
+ private static TABLE;
26
+ /**
27
+ * Initialize the locks table (run once at startup).
28
+ */
29
+ static initialize(): void;
30
+ /**
31
+ * Attempts to acquire a lock on a resource.
32
+ *
33
+ * @param resource - Lock resource name (e.g., "apps/backend/src/types/user.ts")
34
+ * @param ownerId - Unique owner identifier (e.g., "yusuf", "ci-bot-01")
35
+ * @param options - Optional parameters
36
+ * @returns true if lock acquired, false if already locked
37
+ */
38
+ static acquire(resource: string, ownerId: string, options?: {
39
+ ownerName?: string;
40
+ ttlMs?: number;
41
+ reason?: string;
42
+ traceId?: string;
43
+ force?: boolean;
44
+ }): boolean;
45
+ /**
46
+ * Releases a lock. Only the lock owner can release.
47
+ *
48
+ * @param resource - Lock resource name
49
+ * @param ownerId - Owner identifier for verification
50
+ * @returns true if released successfully
51
+ */
52
+ static release(resource: string, ownerId: string): boolean;
53
+ /**
54
+ * Checks if a resource is locked.
55
+ */
56
+ static isLocked(resource: string): boolean;
57
+ /**
58
+ * Gets lock information for a resource.
59
+ */
60
+ static getLock(resource: string): LockInfo | null;
61
+ /**
62
+ * Lists all active locks.
63
+ */
64
+ static listActiveLocks(): LockInfo[];
65
+ /**
66
+ * Lists all locks owned by a specific owner.
67
+ */
68
+ static listOwnerLocks(ownerId: string): LockInfo[];
69
+ /**
70
+ * Releases all locks owned by a specific owner (e.g., on disconnect).
71
+ */
72
+ static releaseAllByOwner(ownerId: string): number;
73
+ /**
74
+ * Releases all expired/stale locks.
75
+ */
76
+ private static releaseStaleLocks;
77
+ /**
78
+ * Generates a unique owner ID for the current user/machine.
79
+ * Uses git config user.name or hostname as fallback.
80
+ */
81
+ static getLocalOwnerId(): string;
82
+ }
package/dist/lock.js ADDED
@@ -0,0 +1,156 @@
1
+ /**
2
+ * [LOCK] Multi-user Distributed Lock Mechanism
3
+ *
4
+ * Git-based lock system. Enables team members to work on the same
5
+ * files/resources without conflicts.
6
+ *
7
+ * Usage:
8
+ * const lock = new DistributedLock("database/schema.sql");
9
+ * if (lock.acquire("user-123", 60000)) {
10
+ * // Apply changes
11
+ * lock.release("user-123");
12
+ * }
13
+ */
14
+ import { execSync } from "child_process";
15
+ import os from "os";
16
+ import { databaseHolder } from "./database.js";
17
+ export class DistributedLock {
18
+ static TABLE = "distributed_locks";
19
+ /**
20
+ * Initialize the locks table (run once at startup).
21
+ */
22
+ static initialize() {
23
+ const db = databaseHolder.getDB();
24
+ db.exec(`
25
+ CREATE TABLE IF NOT EXISTS ${this.TABLE} (
26
+ resource TEXT PRIMARY KEY,
27
+ ownerId TEXT NOT NULL,
28
+ ownerName TEXT NOT NULL,
29
+ acquiredAt TEXT NOT NULL,
30
+ expiresAt TEXT NOT NULL,
31
+ reason TEXT,
32
+ traceId TEXT
33
+ )
34
+ `);
35
+ }
36
+ /**
37
+ * Attempts to acquire a lock on a resource.
38
+ *
39
+ * @param resource - Lock resource name (e.g., "apps/backend/src/types/user.ts")
40
+ * @param ownerId - Unique owner identifier (e.g., "yusuf", "ci-bot-01")
41
+ * @param options - Optional parameters
42
+ * @returns true if lock acquired, false if already locked
43
+ */
44
+ static acquire(resource, ownerId, options = {}) {
45
+ const db = databaseHolder.getDB();
46
+ const now = new Date();
47
+ const expiresAt = new Date(now.getTime() + (options.ttlMs || 60000)).toISOString();
48
+ const ownerName = options.ownerName || ownerId;
49
+ const reason = options.reason || "No reason provided";
50
+ // Clean up stale locks first
51
+ this.releaseStaleLocks();
52
+ // If force=true, override existing lock directly using INSERT OR REPLACE
53
+ if (options.force) {
54
+ db.prepare(`
55
+ INSERT OR REPLACE INTO ${this.TABLE} (resource, ownerId, ownerName, acquiredAt, expiresAt, reason, traceId)
56
+ VALUES (?, ?, ?, ?, ?, ?, ?)
57
+ `).run(resource, ownerId, ownerName, now.toISOString(), expiresAt, reason, options.traceId || null);
58
+ return true;
59
+ }
60
+ // Acquire new lock atomically using INSERT OR IGNORE.
61
+ // If the resource is already locked, changes will be 0.
62
+ const result = db.prepare(`
63
+ INSERT OR IGNORE INTO ${this.TABLE} (resource, ownerId, ownerName, acquiredAt, expiresAt, reason, traceId)
64
+ VALUES (?, ?, ?, ?, ?, ?, ?)
65
+ `).run(resource, ownerId, ownerName, now.toISOString(), expiresAt, reason, options.traceId || null);
66
+ return result.changes > 0;
67
+ }
68
+ /**
69
+ * Releases a lock. Only the lock owner can release.
70
+ *
71
+ * @param resource - Lock resource name
72
+ * @param ownerId - Owner identifier for verification
73
+ * @returns true if released successfully
74
+ */
75
+ static release(resource, ownerId) {
76
+ const db = databaseHolder.getDB();
77
+ const result = db.prepare(`DELETE FROM ${this.TABLE} WHERE resource = ? AND ownerId = ?`).run(resource, ownerId);
78
+ return result.changes > 0;
79
+ }
80
+ /**
81
+ * Checks if a resource is locked.
82
+ */
83
+ static isLocked(resource) {
84
+ const db = databaseHolder.getDB();
85
+ const lock = db.prepare(`SELECT * FROM ${this.TABLE} WHERE resource = ? AND expiresAt > datetime('now')`).get(resource);
86
+ return !!lock;
87
+ }
88
+ /**
89
+ * Gets lock information for a resource.
90
+ */
91
+ static getLock(resource) {
92
+ const db = databaseHolder.getDB();
93
+ this.releaseStaleLocks();
94
+ const lock = db.prepare(`SELECT * FROM ${this.TABLE} WHERE resource = ?`).get(resource);
95
+ return lock || null;
96
+ }
97
+ /**
98
+ * Lists all active locks.
99
+ */
100
+ static listActiveLocks() {
101
+ const db = databaseHolder.getDB();
102
+ this.releaseStaleLocks();
103
+ return db.prepare(`SELECT * FROM ${this.TABLE} WHERE expiresAt > datetime('now') ORDER BY acquiredAt DESC`).all();
104
+ }
105
+ /**
106
+ * Lists all locks owned by a specific owner.
107
+ */
108
+ static listOwnerLocks(ownerId) {
109
+ const db = databaseHolder.getDB();
110
+ return db.prepare(`SELECT * FROM ${this.TABLE} WHERE ownerId = ? ORDER BY acquiredAt DESC`).all(ownerId);
111
+ }
112
+ /**
113
+ * Releases all locks owned by a specific owner (e.g., on disconnect).
114
+ */
115
+ static releaseAllByOwner(ownerId) {
116
+ const db = databaseHolder.getDB();
117
+ const result = db.prepare(`DELETE FROM ${this.TABLE} WHERE ownerId = ?`).run(ownerId);
118
+ return result.changes;
119
+ }
120
+ /**
121
+ * Releases all expired/stale locks.
122
+ */
123
+ static releaseStaleLocks() {
124
+ const db = databaseHolder.getDB();
125
+ const result = db.prepare(`DELETE FROM ${this.TABLE} WHERE expiresAt < datetime('now')`).run();
126
+ return result.changes;
127
+ }
128
+ /**
129
+ * Generates a unique owner ID for the current user/machine.
130
+ * Uses git config user.name or hostname as fallback.
131
+ */
132
+ static getLocalOwnerId() {
133
+ // Try git config
134
+ try {
135
+ const name = execSync("git config user.name", { encoding: "utf8" }).trim();
136
+ if (name)
137
+ return name;
138
+ }
139
+ catch {
140
+ // Fallback
141
+ }
142
+ // Try environment
143
+ if (process.env.USER)
144
+ return process.env.USER;
145
+ if (process.env.USERNAME)
146
+ return process.env.USERNAME;
147
+ // Fallback to hostname
148
+ try {
149
+ return os.hostname();
150
+ }
151
+ catch {
152
+ return "unknown-user";
153
+ }
154
+ }
155
+ }
156
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export declare enum LogLevel {
2
+ DEBUG = 0,
3
+ INFO = 1,
4
+ WARN = 2,
5
+ ERROR = 3,
6
+ FATAL = 4
7
+ }
8
+ export interface LoggerConfig {
9
+ minLevel: LogLevel;
10
+ enableColors: boolean;
11
+ jsonFormat: boolean;
12
+ logFile?: string;
13
+ enablePiiMasking: boolean;
14
+ piiWarning: boolean;
15
+ }
16
+ export declare class EnterpriseLogger {
17
+ private config;
18
+ private static instance;
19
+ private constructor();
20
+ static getInstance(): EnterpriseLogger;
21
+ configure(config: Partial<LoggerConfig>): void;
22
+ private formatMessage;
23
+ private log;
24
+ debug(message: string, meta?: unknown): void;
25
+ info(message: string, meta?: unknown): void;
26
+ warn(message: string, meta?: unknown): void;
27
+ error(message: string, meta?: unknown): void;
28
+ fatal(message: string, meta?: unknown): void;
29
+ }
30
+ export declare const logger: EnterpriseLogger;
package/dist/logger.js ADDED
@@ -0,0 +1,127 @@
1
+ import chalk from "chalk";
2
+ import path from "path";
3
+ import { appendFile, ensureDir } from "./fs.js";
4
+ import { containsPII, maskObject, maskText } from "./pii.js";
5
+ export var LogLevel;
6
+ (function (LogLevel) {
7
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
8
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
9
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
10
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
11
+ LogLevel[LogLevel["FATAL"] = 4] = "FATAL";
12
+ })(LogLevel || (LogLevel = {}));
13
+ export class EnterpriseLogger {
14
+ config;
15
+ static instance;
16
+ constructor() {
17
+ const isProd = process.env.NODE_ENV === "production";
18
+ this.config = {
19
+ minLevel: isProd ? LogLevel.INFO : LogLevel.DEBUG,
20
+ enableColors: !isProd,
21
+ jsonFormat: isProd,
22
+ enablePiiMasking: true, // KVKK: PII masking ON by default
23
+ piiWarning: true,
24
+ };
25
+ }
26
+ static getInstance() {
27
+ if (!EnterpriseLogger.instance) {
28
+ EnterpriseLogger.instance = new EnterpriseLogger();
29
+ }
30
+ return EnterpriseLogger.instance;
31
+ }
32
+ configure(config) {
33
+ this.config = { ...this.config, ...config };
34
+ if (this.config.logFile) {
35
+ try {
36
+ ensureDir(path.dirname(this.config.logFile));
37
+ }
38
+ catch (err) {
39
+ // Directly write to stderr — using console here would be circular
40
+ process.stderr.write(`[Logger] Failed to create log directory: ${err}\n`);
41
+ }
42
+ }
43
+ }
44
+ formatMessage(level, message, meta) {
45
+ const timestamp = new Date().toISOString();
46
+ const pid = process.pid;
47
+ // [KVKK] PII masking — mask sensitive data before logging
48
+ const safeMessage = this.config.enablePiiMasking ? maskText(message) : message;
49
+ const safeMeta = this.config.enablePiiMasking && meta ? maskObject(meta) : meta;
50
+ // [KVKK] Warn if PII detected in production
51
+ if (this.config.piiWarning && (containsPII(message) || (meta && containsPII(JSON.stringify(meta))))) {
52
+ process.stderr.write(`[PII WARNING] Potential PII detected in log at ${timestamp}\n`);
53
+ }
54
+ if (this.config.jsonFormat) {
55
+ return JSON.stringify({
56
+ timestamp,
57
+ level: LogLevel[level],
58
+ pid,
59
+ message: safeMessage,
60
+ meta: safeMeta,
61
+ });
62
+ }
63
+ const levelName = LogLevel[level].padEnd(5);
64
+ let coloredLevel = levelName;
65
+ if (this.config.enableColors) {
66
+ switch (level) {
67
+ case LogLevel.DEBUG:
68
+ coloredLevel = chalk.blue(levelName);
69
+ break;
70
+ case LogLevel.INFO:
71
+ coloredLevel = chalk.green(levelName);
72
+ break;
73
+ case LogLevel.WARN:
74
+ coloredLevel = chalk.yellow(levelName);
75
+ break;
76
+ case LogLevel.ERROR:
77
+ coloredLevel = chalk.red(levelName);
78
+ break;
79
+ case LogLevel.FATAL:
80
+ coloredLevel = chalk.bgRed.white.bold(levelName);
81
+ break;
82
+ }
83
+ }
84
+ const metaStr = safeMeta ? ` | Meta: ${JSON.stringify(safeMeta)}` : "";
85
+ return `[${timestamp}] [PID:${pid}] [${coloredLevel}]: ${safeMessage}${metaStr}`;
86
+ }
87
+ log(level, message, meta) {
88
+ if (level < this.config.minLevel)
89
+ return;
90
+ const formatted = this.formatMessage(level, message, meta);
91
+ // Route to stderr for ERROR/FATAL, stdout otherwise.
92
+ // Using process.write directly here is intentional — this IS the logger.
93
+ if (level >= LogLevel.ERROR) {
94
+ process.stderr.write(formatted + "\n");
95
+ }
96
+ else {
97
+ process.stdout.write(formatted + "\n");
98
+ }
99
+ // Output to file if configured
100
+ if (this.config.logFile) {
101
+ try {
102
+ appendFile(this.config.logFile, formatted + "\n");
103
+ }
104
+ catch (err) {
105
+ // Directly write to stderr — using console here would be circular
106
+ process.stderr.write(`[Logger] Failed to write to log file: ${err}\n`);
107
+ }
108
+ }
109
+ }
110
+ debug(message, meta) {
111
+ this.log(LogLevel.DEBUG, message, meta);
112
+ }
113
+ info(message, meta) {
114
+ this.log(LogLevel.INFO, message, meta);
115
+ }
116
+ warn(message, meta) {
117
+ this.log(LogLevel.WARN, message, meta);
118
+ }
119
+ error(message, meta) {
120
+ this.log(LogLevel.ERROR, message, meta);
121
+ }
122
+ fatal(message, meta) {
123
+ this.log(LogLevel.FATAL, message, meta);
124
+ }
125
+ }
126
+ export const logger = EnterpriseLogger.getInstance();
127
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}