atabey-shared 0.0.37 → 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/README.md +64 -25
- package/dist/agent-identity.d.ts +1 -0
- package/dist/agent-identity.js +2 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/api-catalog.d.ts +1 -0
- package/dist/api-catalog.js +2 -0
- package/dist/api-catalog.js.map +1 -0
- package/dist/audit-chain.d.ts +1 -51
- package/dist/audit-chain.js +1 -84
- package/dist/audit-chain.js.map +1 -1
- package/dist/audit.d.ts +1 -113
- package/dist/audit.js +1 -284
- package/dist/audit.js.map +1 -1
- package/dist/constants.d.ts +1 -152
- package/dist/constants.js +1 -215
- package/dist/constants.js.map +1 -1
- package/dist/database.d.ts +1 -5
- package/dist/database.js +1 -12
- package/dist/database.js.map +1 -1
- package/dist/errors.d.ts +1 -46
- package/dist/errors.js +1 -68
- package/dist/errors.js.map +1 -1
- package/dist/file-lock.d.ts +1 -88
- package/dist/file-lock.js +1 -250
- package/dist/file-lock.js.map +1 -1
- package/dist/fs.d.ts +1 -9
- package/dist/fs.js +1 -53
- package/dist/fs.js.map +1 -1
- package/dist/index.d.ts +2 -22
- package/dist/index.js +2 -22
- package/dist/index.js.map +1 -1
- package/dist/job-queue.d.ts +1 -53
- package/dist/job-queue.js +1 -126
- package/dist/job-queue.js.map +1 -1
- package/dist/lock.d.ts +1 -82
- package/dist/lock.js +1 -158
- package/dist/lock.js.map +1 -1
- package/dist/logger.d.ts +1 -30
- package/dist/logger.js +1 -126
- package/dist/logger.js.map +1 -1
- package/dist/memory-prune.d.ts +1 -0
- package/dist/memory-prune.js +2 -0
- package/dist/memory-prune.js.map +1 -0
- package/dist/migrations.d.ts +1 -0
- package/dist/migrations.js +2 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modules/agent/agent-identity.d.ts +34 -0
- package/dist/modules/agent/agent-identity.js +77 -0
- package/dist/modules/agent/agent-identity.js.map +1 -0
- package/dist/modules/agent/api-catalog.d.ts +57 -0
- package/dist/modules/agent/api-catalog.js +254 -0
- package/dist/modules/agent/api-catalog.js.map +1 -0
- package/dist/modules/agent/index.d.ts +3 -0
- package/dist/modules/agent/index.js +4 -0
- package/dist/modules/agent/index.js.map +1 -0
- package/dist/modules/agent/tokenizer.d.ts +54 -0
- package/dist/modules/agent/tokenizer.js +272 -0
- package/dist/modules/agent/tokenizer.js.map +1 -0
- package/dist/modules/concurrency/file-lock.d.ts +93 -0
- package/dist/modules/concurrency/file-lock.js +240 -0
- package/dist/modules/concurrency/file-lock.js.map +1 -0
- package/dist/modules/concurrency/index.d.ts +6 -0
- package/dist/modules/concurrency/index.js +7 -0
- package/dist/modules/concurrency/index.js.map +1 -0
- package/dist/modules/concurrency/job-queue.d.ts +76 -0
- package/dist/modules/concurrency/job-queue.js +200 -0
- package/dist/modules/concurrency/job-queue.js.map +1 -0
- package/dist/modules/concurrency/lock.d.ts +82 -0
- package/dist/modules/concurrency/lock.js +159 -0
- package/dist/modules/concurrency/lock.js.map +1 -0
- package/dist/modules/concurrency/resilience.d.ts +84 -0
- package/dist/modules/concurrency/resilience.js +217 -0
- package/dist/modules/concurrency/resilience.js.map +1 -0
- package/dist/modules/concurrency/worker-pool.d.ts +52 -0
- package/dist/modules/concurrency/worker-pool.js +229 -0
- package/dist/modules/concurrency/worker-pool.js.map +1 -0
- package/dist/modules/concurrency/worker-thread.d.ts +21 -0
- package/dist/modules/concurrency/worker-thread.js +67 -0
- package/dist/modules/concurrency/worker-thread.js.map +1 -0
- package/dist/modules/index.d.ts +14 -0
- package/dist/modules/index.js +15 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/observability/audit-chain.d.ts +80 -0
- package/dist/modules/observability/audit-chain.js +262 -0
- package/dist/modules/observability/audit-chain.js.map +1 -0
- package/dist/modules/observability/audit.d.ts +121 -0
- package/dist/modules/observability/audit.js +322 -0
- package/dist/modules/observability/audit.js.map +1 -0
- package/dist/modules/observability/index.d.ts +4 -0
- package/dist/modules/observability/index.js +5 -0
- package/dist/modules/observability/index.js.map +1 -0
- package/dist/modules/observability/logger.d.ts +31 -0
- package/dist/modules/observability/logger.js +153 -0
- package/dist/modules/observability/logger.js.map +1 -0
- package/dist/modules/observability/otel.d.ts +39 -0
- package/dist/modules/observability/otel.js +93 -0
- package/dist/modules/observability/otel.js.map +1 -0
- package/dist/modules/primitives/constants.d.ts +150 -0
- package/dist/modules/primitives/constants.js +212 -0
- package/dist/modules/primitives/constants.js.map +1 -0
- package/dist/modules/primitives/errors.d.ts +46 -0
- package/dist/modules/primitives/errors.js +69 -0
- package/dist/modules/primitives/errors.js.map +1 -0
- package/dist/modules/primitives/fs.d.ts +9 -0
- package/dist/modules/primitives/fs.js +54 -0
- package/dist/modules/primitives/fs.js.map +1 -0
- package/dist/modules/primitives/index.d.ts +7 -0
- package/dist/modules/primitives/index.js +8 -0
- package/dist/modules/primitives/index.js.map +1 -0
- package/dist/modules/primitives/outbound-http.d.ts +32 -0
- package/dist/modules/primitives/outbound-http.js +88 -0
- package/dist/modules/primitives/outbound-http.js.map +1 -0
- package/dist/modules/primitives/string.d.ts +1 -0
- package/dist/modules/primitives/string.js +30 -0
- package/dist/modules/primitives/string.js.map +1 -0
- package/dist/modules/primitives/time.d.ts +5 -0
- package/dist/modules/primitives/time.js +35 -0
- package/dist/modules/primitives/time.js.map +1 -0
- package/dist/modules/primitives/types.d.ts +27 -0
- package/dist/modules/primitives/types.js +17 -0
- package/dist/modules/primitives/types.js.map +1 -0
- package/dist/modules/sandbox/index.d.ts +3 -0
- package/dist/modules/sandbox/index.js +4 -0
- package/dist/modules/sandbox/index.js.map +1 -0
- package/dist/modules/sandbox/sandbox-fs.d.ts +28 -0
- package/dist/modules/sandbox/sandbox-fs.js +143 -0
- package/dist/modules/sandbox/sandbox-fs.js.map +1 -0
- package/dist/modules/sandbox/sandbox-runtime.d.ts +78 -0
- package/dist/modules/sandbox/sandbox-runtime.js +282 -0
- package/dist/modules/sandbox/sandbox-runtime.js.map +1 -0
- package/dist/modules/sandbox/sandbox.d.ts +54 -0
- package/dist/modules/sandbox/sandbox.js +179 -0
- package/dist/modules/sandbox/sandbox.js.map +1 -0
- package/dist/modules/security/index.d.ts +5 -0
- package/dist/modules/security/index.js +6 -0
- package/dist/modules/security/index.js.map +1 -0
- package/dist/modules/security/pii.d.ts +70 -0
- package/dist/modules/security/pii.js +276 -0
- package/dist/modules/security/pii.js.map +1 -0
- package/dist/modules/security/policy-gate.d.ts +42 -0
- package/dist/modules/security/policy-gate.js +172 -0
- package/dist/modules/security/policy-gate.js.map +1 -0
- package/dist/modules/security/retention.d.ts +68 -0
- package/dist/modules/security/retention.js +218 -0
- package/dist/modules/security/retention.js.map +1 -0
- package/dist/modules/security/secrets.d.ts +99 -0
- package/dist/modules/security/secrets.js +371 -0
- package/dist/modules/security/secrets.js.map +1 -0
- package/dist/modules/security/tls.d.ts +87 -0
- package/dist/modules/security/tls.js +154 -0
- package/dist/modules/security/tls.js.map +1 -0
- package/dist/modules/storage/database.d.ts +6 -0
- package/dist/modules/storage/database.js +16 -0
- package/dist/modules/storage/database.js.map +1 -0
- package/dist/modules/storage/index.d.ts +4 -0
- package/dist/modules/storage/index.js +5 -0
- package/dist/modules/storage/index.js.map +1 -0
- package/dist/modules/storage/memory-prune.d.ts +18 -0
- package/dist/modules/storage/memory-prune.js +48 -0
- package/dist/modules/storage/memory-prune.js.map +1 -0
- package/dist/modules/storage/migrations.d.ts +69 -0
- package/dist/modules/storage/migrations.js +394 -0
- package/dist/modules/storage/migrations.js.map +1 -0
- package/dist/modules/storage/storage.d.ts +341 -0
- package/dist/modules/storage/storage.js +1004 -0
- package/dist/modules/storage/storage.js.map +1 -0
- package/dist/otel.d.ts +1 -0
- package/dist/otel.js +2 -0
- package/dist/otel.js.map +1 -0
- package/dist/outbound-http.d.ts +1 -0
- package/dist/outbound-http.js +2 -0
- package/dist/outbound-http.js.map +1 -0
- package/dist/pii.d.ts +1 -69
- package/dist/pii.js +1 -219
- package/dist/pii.js.map +1 -1
- package/dist/policy-gate.d.ts +1 -42
- package/dist/policy-gate.js +1 -147
- package/dist/policy-gate.js.map +1 -1
- package/dist/resilience.d.ts +1 -84
- package/dist/resilience.js +1 -216
- package/dist/resilience.js.map +1 -1
- package/dist/retention.d.ts +1 -63
- package/dist/retention.js +1 -170
- package/dist/retention.js.map +1 -1
- package/dist/sandbox-fs.d.ts +1 -28
- package/dist/sandbox-fs.js +1 -149
- package/dist/sandbox-fs.js.map +1 -1
- package/dist/sandbox-runtime.d.ts +1 -85
- package/dist/sandbox-runtime.js +1 -249
- package/dist/sandbox-runtime.js.map +1 -1
- package/dist/sandbox.d.ts +1 -54
- package/dist/sandbox.js +1 -178
- package/dist/sandbox.js.map +1 -1
- package/dist/secrets.d.ts +1 -0
- package/dist/secrets.js +2 -0
- package/dist/secrets.js.map +1 -0
- package/dist/storage.d.ts +1 -274
- package/dist/storage.js +1 -723
- package/dist/storage.js.map +1 -1
- package/dist/string.d.ts +1 -1
- package/dist/string.js +1 -29
- package/dist/string.js.map +1 -1
- package/dist/time.d.ts +1 -5
- package/dist/time.js +1 -30
- package/dist/time.js.map +1 -1
- package/dist/tls.d.ts +1 -0
- package/dist/tls.js +2 -0
- package/dist/tls.js.map +1 -0
- package/dist/tokenizer.d.ts +1 -0
- package/dist/tokenizer.js +2 -0
- package/dist/tokenizer.js.map +1 -0
- package/dist/types.d.ts +1 -27
- package/dist/types.js +1 -16
- package/dist/types.js.map +1 -1
- package/dist/worker-pool.d.ts +1 -52
- package/dist/worker-pool.js +1 -209
- package/dist/worker-pool.js.map +1 -1
- package/dist/worker-thread.d.ts +1 -21
- package/dist/worker-thread.js +1 -66
- package/dist/worker-thread.js.map +1 -1
- package/package.json +51 -29
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,cAAc,mCAAmC,CAAC"}
|
package/dist/database.d.ts
CHANGED
package/dist/database.js
CHANGED
|
@@ -1,13 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export const databaseHolder = {
|
|
3
|
-
setDB(db) {
|
|
4
|
-
globalDB = db;
|
|
5
|
-
},
|
|
6
|
-
getDB() {
|
|
7
|
-
if (!globalDB) {
|
|
8
|
-
throw new Error("Atabey Shared Database has not been initialized. Please call databaseHolder.setDB(db) at startup.");
|
|
9
|
-
}
|
|
10
|
-
return globalDB;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
1
|
+
export * from "./modules/storage/database.js";
|
|
13
2
|
//# sourceMappingURL=database.js.map
|
package/dist/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,46 +1 @@
|
|
|
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
|
-
}
|
|
1
|
+
export * from "./modules/primitives/errors.js";
|
package/dist/errors.js
CHANGED
|
@@ -1,69 +1,2 @@
|
|
|
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
|
-
}
|
|
1
|
+
export * from "./modules/primitives/errors.js";
|
|
69
2
|
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC"}
|
package/dist/file-lock.d.ts
CHANGED
|
@@ -1,88 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Atomic File-Based Locking — OS-level exclusive create via open('wx').
|
|
3
|
-
*
|
|
4
|
-
* Replaces check-then-act lock races. No Redis/Redlock required.
|
|
5
|
-
*
|
|
6
|
-
* Pattern:
|
|
7
|
-
* resource → .atabey/locks/<relative>.lock (created with O_EXCL / 'wx')
|
|
8
|
-
* holder writes JSON metadata after exclusive create
|
|
9
|
-
* release unlinks the lock file
|
|
10
|
-
*
|
|
11
|
-
* Stale locks (TTL exceeded) are reclaimed atomically when possible.
|
|
12
|
-
*/
|
|
13
|
-
export interface FileLockOptions {
|
|
14
|
-
/** Base directory for lock files. Default: `.atabey/locks` under cwd or projectRoot. */
|
|
15
|
-
locksDir?: string;
|
|
16
|
-
/** Project root used to relativize resource paths. Default: process.cwd(). */
|
|
17
|
-
projectRoot?: string;
|
|
18
|
-
/** Lock TTL in ms. Stale locks may be stolen after this. Default: 5 minutes. */
|
|
19
|
-
ttlMs?: number;
|
|
20
|
-
/** Retry interval when waiting for a lock. Default: 50ms. */
|
|
21
|
-
retryMs?: number;
|
|
22
|
-
/** Max wait when using acquireAsync. Default: 10s. */
|
|
23
|
-
timeoutMs?: number;
|
|
24
|
-
}
|
|
25
|
-
export interface FileLockMeta {
|
|
26
|
-
ownerId: string;
|
|
27
|
-
resource: string;
|
|
28
|
-
acquiredAt: string;
|
|
29
|
-
expiresAt: string;
|
|
30
|
-
reason?: string;
|
|
31
|
-
pid: number;
|
|
32
|
-
hostname: string;
|
|
33
|
-
}
|
|
34
|
-
export declare class AtomicFileLock {
|
|
35
|
-
private readonly locksDir;
|
|
36
|
-
private readonly projectRoot;
|
|
37
|
-
private readonly ttlMs;
|
|
38
|
-
private readonly retryMs;
|
|
39
|
-
private readonly timeoutMs;
|
|
40
|
-
constructor(options?: FileLockOptions);
|
|
41
|
-
/** Absolute path of the lock file for a resource. */
|
|
42
|
-
getLockPath(resource: string): string;
|
|
43
|
-
/**
|
|
44
|
-
* Try to acquire a lock once (non-blocking).
|
|
45
|
-
* Uses atomic exclusive file create (`wx` = O_CREAT | O_EXCL | O_WRONLY).
|
|
46
|
-
*/
|
|
47
|
-
tryAcquire(resource: string, ownerId: string, reason?: string, _reclaimDepth?: number): {
|
|
48
|
-
acquired: boolean;
|
|
49
|
-
meta?: FileLockMeta;
|
|
50
|
-
heldBy?: FileLockMeta;
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Acquire with async retry until timeout.
|
|
54
|
-
*/
|
|
55
|
-
acquireAsync(resource: string, ownerId: string, options?: {
|
|
56
|
-
reason?: string;
|
|
57
|
-
timeoutMs?: number;
|
|
58
|
-
retryMs?: number;
|
|
59
|
-
}): Promise<FileLockMeta>;
|
|
60
|
-
/**
|
|
61
|
-
* Release lock only if owned by ownerId (or force=true).
|
|
62
|
-
*/
|
|
63
|
-
release(resource: string, ownerId: string, force?: boolean): boolean;
|
|
64
|
-
isLocked(resource: string): FileLockMeta | null;
|
|
65
|
-
/**
|
|
66
|
-
* Run `fn` while holding the lock.
|
|
67
|
-
* ALWAYS releases in `finally` even if `fn` throws (disk full, parse errors, etc.).
|
|
68
|
-
* Without this, a leftover `.lock` file would deadlock every subsequent writer until TTL.
|
|
69
|
-
*
|
|
70
|
-
* Prefer this API over bare acquire/release for any mutating work.
|
|
71
|
-
*/
|
|
72
|
-
withLock<T>(resource: string, ownerId: string, fn: () => Promise<T> | T, options?: {
|
|
73
|
-
reason?: string;
|
|
74
|
-
timeoutMs?: number;
|
|
75
|
-
}): Promise<T>;
|
|
76
|
-
/**
|
|
77
|
-
* Synchronous withLock — same try/finally release guarantee.
|
|
78
|
-
*/
|
|
79
|
-
withLockSync<T>(resource: string, ownerId: string, fn: () => T, options?: {
|
|
80
|
-
reason?: string;
|
|
81
|
-
}): T;
|
|
82
|
-
private reclaimIfStale;
|
|
83
|
-
private isExpired;
|
|
84
|
-
private readMeta;
|
|
85
|
-
private forceRemove;
|
|
86
|
-
}
|
|
87
|
-
/** Convenience: lock under project `.atabey/locks`. */
|
|
88
|
-
export declare function createProjectFileLock(projectRoot: string, options?: Omit<FileLockOptions, "projectRoot">): AtomicFileLock;
|
|
1
|
+
export * from "./modules/concurrency/file-lock.js";
|
package/dist/file-lock.js
CHANGED
|
@@ -1,251 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Atomic File-Based Locking — OS-level exclusive create via open('wx').
|
|
3
|
-
*
|
|
4
|
-
* Replaces check-then-act lock races. No Redis/Redlock required.
|
|
5
|
-
*
|
|
6
|
-
* Pattern:
|
|
7
|
-
* resource → .atabey/locks/<relative>.lock (created with O_EXCL / 'wx')
|
|
8
|
-
* holder writes JSON metadata after exclusive create
|
|
9
|
-
* release unlinks the lock file
|
|
10
|
-
*
|
|
11
|
-
* Stale locks (TTL exceeded) are reclaimed atomically when possible.
|
|
12
|
-
*/
|
|
13
|
-
import fs from "fs";
|
|
14
|
-
import os from "os";
|
|
15
|
-
import path from "path";
|
|
16
|
-
export class AtomicFileLock {
|
|
17
|
-
locksDir;
|
|
18
|
-
projectRoot;
|
|
19
|
-
ttlMs;
|
|
20
|
-
retryMs;
|
|
21
|
-
timeoutMs;
|
|
22
|
-
constructor(options = {}) {
|
|
23
|
-
this.projectRoot = options.projectRoot ?? process.cwd();
|
|
24
|
-
this.locksDir = options.locksDir
|
|
25
|
-
? path.resolve(options.locksDir)
|
|
26
|
-
: path.join(this.projectRoot, ".atabey", "locks");
|
|
27
|
-
this.ttlMs = options.ttlMs ?? 5 * 60 * 1000;
|
|
28
|
-
this.retryMs = options.retryMs ?? 50;
|
|
29
|
-
this.timeoutMs = options.timeoutMs ?? 10_000;
|
|
30
|
-
}
|
|
31
|
-
/** Absolute path of the lock file for a resource. */
|
|
32
|
-
getLockPath(resource) {
|
|
33
|
-
const abs = path.isAbsolute(resource)
|
|
34
|
-
? resource
|
|
35
|
-
: path.resolve(this.projectRoot, resource);
|
|
36
|
-
let relative = path.relative(this.projectRoot, abs);
|
|
37
|
-
if (relative.startsWith("..")) {
|
|
38
|
-
// Outside project root — hash path to avoid escaping locks dir
|
|
39
|
-
relative = `_ext/${Buffer.from(abs).toString("base64url")}`;
|
|
40
|
-
}
|
|
41
|
-
// Normalize separators for cross-platform lock paths
|
|
42
|
-
relative = relative.split(path.sep).join("/");
|
|
43
|
-
return path.join(this.locksDir, `${relative}.lock`);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Try to acquire a lock once (non-blocking).
|
|
47
|
-
* Uses atomic exclusive file create (`wx` = O_CREAT | O_EXCL | O_WRONLY).
|
|
48
|
-
*/
|
|
49
|
-
tryAcquire(resource, ownerId, reason, _reclaimDepth = 0) {
|
|
50
|
-
const lockPath = this.getLockPath(resource);
|
|
51
|
-
fs.mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
52
|
-
// Reclaim stale lock first (best-effort, still atomic on create)
|
|
53
|
-
this.reclaimIfStale(lockPath);
|
|
54
|
-
const now = Date.now();
|
|
55
|
-
const meta = {
|
|
56
|
-
ownerId,
|
|
57
|
-
resource,
|
|
58
|
-
acquiredAt: new Date(now).toISOString(),
|
|
59
|
-
expiresAt: new Date(now + this.ttlMs).toISOString(),
|
|
60
|
-
reason,
|
|
61
|
-
pid: process.pid,
|
|
62
|
-
hostname: os.hostname(),
|
|
63
|
-
};
|
|
64
|
-
let fd;
|
|
65
|
-
try {
|
|
66
|
-
// Atomic exclusive create — fails if file already exists
|
|
67
|
-
fd = fs.openSync(lockPath, "wx");
|
|
68
|
-
try {
|
|
69
|
-
fs.writeFileSync(fd, JSON.stringify(meta, null, 2), "utf8");
|
|
70
|
-
}
|
|
71
|
-
catch (writeErr) {
|
|
72
|
-
// CRITICAL: meta write failed after wx create (e.g. ENOSPC) — remove orphan lock
|
|
73
|
-
try {
|
|
74
|
-
if (fd !== undefined)
|
|
75
|
-
fs.closeSync(fd);
|
|
76
|
-
}
|
|
77
|
-
catch { /* ignore */ }
|
|
78
|
-
fd = undefined;
|
|
79
|
-
this.forceRemove(lockPath, null);
|
|
80
|
-
throw writeErr;
|
|
81
|
-
}
|
|
82
|
-
fs.closeSync(fd);
|
|
83
|
-
fd = undefined;
|
|
84
|
-
return { acquired: true, meta };
|
|
85
|
-
}
|
|
86
|
-
catch (err) {
|
|
87
|
-
if (fd !== undefined) {
|
|
88
|
-
try {
|
|
89
|
-
fs.closeSync(fd);
|
|
90
|
-
}
|
|
91
|
-
catch { /* ignore */ }
|
|
92
|
-
}
|
|
93
|
-
const code = err.code;
|
|
94
|
-
if (code === "EEXIST") {
|
|
95
|
-
// Race: another process created the lock between reclaim and open
|
|
96
|
-
const heldBy = this.readMeta(lockPath) ?? undefined;
|
|
97
|
-
// Corrupt lock (unreadable JSON) or expired → reclaim and retry once
|
|
98
|
-
if ((!heldBy || this.isExpired(heldBy)) && _reclaimDepth < 1) {
|
|
99
|
-
this.forceRemove(lockPath, heldBy ?? null);
|
|
100
|
-
return this.tryAcquire(resource, ownerId, reason, _reclaimDepth + 1);
|
|
101
|
-
}
|
|
102
|
-
return { acquired: false, heldBy };
|
|
103
|
-
}
|
|
104
|
-
throw err;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Acquire with async retry until timeout.
|
|
109
|
-
*/
|
|
110
|
-
async acquireAsync(resource, ownerId, options) {
|
|
111
|
-
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
112
|
-
const retryMs = options?.retryMs ?? this.retryMs;
|
|
113
|
-
const start = Date.now();
|
|
114
|
-
while (true) {
|
|
115
|
-
const result = this.tryAcquire(resource, ownerId, options?.reason);
|
|
116
|
-
if (result.acquired && result.meta) {
|
|
117
|
-
return result.meta;
|
|
118
|
-
}
|
|
119
|
-
if (Date.now() - start >= timeoutMs) {
|
|
120
|
-
const holder = result.heldBy?.ownerId ?? "unknown";
|
|
121
|
-
throw new Error(`[AtomicFileLock] Timeout acquiring lock for "${resource}" after ${timeoutMs}ms (held by ${holder})`);
|
|
122
|
-
}
|
|
123
|
-
await sleep(retryMs);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Release lock only if owned by ownerId (or force=true).
|
|
128
|
-
*/
|
|
129
|
-
release(resource, ownerId, force = false) {
|
|
130
|
-
const lockPath = this.getLockPath(resource);
|
|
131
|
-
if (!fs.existsSync(lockPath))
|
|
132
|
-
return true;
|
|
133
|
-
const meta = this.readMeta(lockPath);
|
|
134
|
-
if (!meta) {
|
|
135
|
-
this.forceRemove(lockPath, null);
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
if (!force && meta.ownerId !== ownerId) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
this.forceRemove(lockPath, meta);
|
|
142
|
-
return true;
|
|
143
|
-
}
|
|
144
|
-
isLocked(resource) {
|
|
145
|
-
const lockPath = this.getLockPath(resource);
|
|
146
|
-
if (!fs.existsSync(lockPath))
|
|
147
|
-
return null;
|
|
148
|
-
const meta = this.readMeta(lockPath);
|
|
149
|
-
if (!meta)
|
|
150
|
-
return null;
|
|
151
|
-
if (this.isExpired(meta)) {
|
|
152
|
-
this.forceRemove(lockPath, meta);
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
return meta;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Run `fn` while holding the lock.
|
|
159
|
-
* ALWAYS releases in `finally` even if `fn` throws (disk full, parse errors, etc.).
|
|
160
|
-
* Without this, a leftover `.lock` file would deadlock every subsequent writer until TTL.
|
|
161
|
-
*
|
|
162
|
-
* Prefer this API over bare acquire/release for any mutating work.
|
|
163
|
-
*/
|
|
164
|
-
async withLock(resource, ownerId, fn, options) {
|
|
165
|
-
await this.acquireAsync(resource, ownerId, options);
|
|
166
|
-
try {
|
|
167
|
-
return await fn();
|
|
168
|
-
}
|
|
169
|
-
finally {
|
|
170
|
-
// Never let release errors mask the original failure or leave a lock.
|
|
171
|
-
try {
|
|
172
|
-
this.release(resource, ownerId);
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
this.forceRemove(this.getLockPath(resource), null);
|
|
176
|
-
}
|
|
177
|
-
// Belt-and-suspenders: if our lock is somehow still present, force drop it.
|
|
178
|
-
const stillHeld = this.isLocked(resource);
|
|
179
|
-
if (stillHeld && stillHeld.ownerId === ownerId) {
|
|
180
|
-
this.forceRemove(this.getLockPath(resource), stillHeld);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Synchronous withLock — same try/finally release guarantee.
|
|
186
|
-
*/
|
|
187
|
-
withLockSync(resource, ownerId, fn, options) {
|
|
188
|
-
const result = this.tryAcquire(resource, ownerId, options?.reason);
|
|
189
|
-
if (!result.acquired) {
|
|
190
|
-
const holder = result.heldBy?.ownerId ?? "unknown";
|
|
191
|
-
throw new Error(`[AtomicFileLock] Could not acquire lock for "${resource}" (held by ${holder})`);
|
|
192
|
-
}
|
|
193
|
-
try {
|
|
194
|
-
return fn();
|
|
195
|
-
}
|
|
196
|
-
finally {
|
|
197
|
-
try {
|
|
198
|
-
this.release(resource, ownerId);
|
|
199
|
-
}
|
|
200
|
-
catch {
|
|
201
|
-
this.forceRemove(this.getLockPath(resource), null);
|
|
202
|
-
}
|
|
203
|
-
const stillHeld = this.isLocked(resource);
|
|
204
|
-
if (stillHeld && stillHeld.ownerId === ownerId) {
|
|
205
|
-
this.forceRemove(this.getLockPath(resource), stillHeld);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
reclaimIfStale(lockPath) {
|
|
210
|
-
if (!fs.existsSync(lockPath))
|
|
211
|
-
return;
|
|
212
|
-
const meta = this.readMeta(lockPath);
|
|
213
|
-
if (!meta || this.isExpired(meta)) {
|
|
214
|
-
this.forceRemove(lockPath, meta);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
isExpired(meta) {
|
|
218
|
-
const exp = Date.parse(meta.expiresAt);
|
|
219
|
-
if (Number.isNaN(exp)) {
|
|
220
|
-
// Fallback: acquiredAt + ttl
|
|
221
|
-
const acq = Date.parse(meta.acquiredAt);
|
|
222
|
-
return Number.isNaN(acq) ? true : Date.now() - acq > this.ttlMs;
|
|
223
|
-
}
|
|
224
|
-
return Date.now() > exp;
|
|
225
|
-
}
|
|
226
|
-
readMeta(lockPath) {
|
|
227
|
-
try {
|
|
228
|
-
const raw = fs.readFileSync(lockPath, "utf8");
|
|
229
|
-
return JSON.parse(raw);
|
|
230
|
-
}
|
|
231
|
-
catch {
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
forceRemove(lockPath, _meta) {
|
|
236
|
-
try {
|
|
237
|
-
fs.unlinkSync(lockPath);
|
|
238
|
-
}
|
|
239
|
-
catch {
|
|
240
|
-
// ignore ENOENT races
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function sleep(ms) {
|
|
245
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
246
|
-
}
|
|
247
|
-
/** Convenience: lock under project `.atabey/locks`. */
|
|
248
|
-
export function createProjectFileLock(projectRoot, options) {
|
|
249
|
-
return new AtomicFileLock({ ...options, projectRoot });
|
|
250
|
-
}
|
|
1
|
+
export * from "./modules/concurrency/file-lock.js";
|
|
251
2
|
//# sourceMappingURL=file-lock.js.map
|
package/dist/file-lock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC"}
|
package/dist/fs.d.ts
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
export
|
|
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;
|
|
1
|
+
export * from "./modules/primitives/fs.js";
|
package/dist/fs.js
CHANGED
|
@@ -1,54 +1,2 @@
|
|
|
1
|
-
|
|
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
|
-
}
|
|
1
|
+
export * from "./modules/primitives/fs.js";
|
|
54
2
|
//# sourceMappingURL=fs.js.map
|
package/dist/fs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./lock.js";
|
|
4
|
-
export * from "./audit.js";
|
|
5
|
-
export * from "./audit-chain.js";
|
|
6
|
-
export * from "./logger.js";
|
|
7
|
-
export * from "./retention.js";
|
|
8
|
-
export * from "./errors.js";
|
|
9
|
-
export * from "./constants.js";
|
|
10
|
-
export * from "./string.js";
|
|
11
|
-
export * from "./types.js";
|
|
12
|
-
export * from "./fs.js";
|
|
13
|
-
export * from "./job-queue.js";
|
|
14
|
-
export * from "./worker-pool.js";
|
|
15
|
-
export * from "./file-lock.js";
|
|
16
|
-
export * from "./sandbox.js";
|
|
17
|
-
export * from "./sandbox-runtime.js";
|
|
18
|
-
export * from "./sandbox-fs.js";
|
|
19
|
-
export * from "./resilience.js";
|
|
20
|
-
export * from "./policy-gate.js";
|
|
21
|
-
export * from "./storage.js";
|
|
22
|
-
export * from "./time.js";
|
|
1
|
+
export * from "./modules/index.js";
|
|
2
|
+
export * as Modules from "./modules/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./lock.js";
|
|
4
|
-
export * from "./audit.js";
|
|
5
|
-
export * from "./audit-chain.js";
|
|
6
|
-
export * from "./logger.js";
|
|
7
|
-
export * from "./retention.js";
|
|
8
|
-
export * from "./errors.js";
|
|
9
|
-
export * from "./constants.js";
|
|
10
|
-
export * from "./string.js";
|
|
11
|
-
export * from "./types.js";
|
|
12
|
-
export * from "./fs.js";
|
|
13
|
-
export * from "./job-queue.js";
|
|
14
|
-
export * from "./worker-pool.js";
|
|
15
|
-
export * from "./file-lock.js";
|
|
16
|
-
export * from "./sandbox.js";
|
|
17
|
-
export * from "./sandbox-runtime.js";
|
|
18
|
-
export * from "./sandbox-fs.js";
|
|
19
|
-
export * from "./resilience.js";
|
|
20
|
-
export * from "./policy-gate.js";
|
|
21
|
-
export * from "./storage.js";
|
|
22
|
-
export * from "./time.js";
|
|
1
|
+
export * from "./modules/index.js";
|
|
2
|
+
export * as Modules from "./modules/index.js";
|
|
23
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC"}
|