@periodic/vanadium 1.0.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/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +846 -0
- package/dist/cjs/adapters/memory/index.js +134 -0
- package/dist/cjs/adapters/memory/index.js.map +1 -0
- package/dist/cjs/adapters/mongodb/index.js +189 -0
- package/dist/cjs/adapters/mongodb/index.js.map +1 -0
- package/dist/cjs/adapters/mongoose/index.js +199 -0
- package/dist/cjs/adapters/mongoose/index.js.map +1 -0
- package/dist/cjs/adapters/postgres/index.js +202 -0
- package/dist/cjs/adapters/postgres/index.js.map +1 -0
- package/dist/cjs/adapters/prisma/index.js +176 -0
- package/dist/cjs/adapters/prisma/index.js.map +1 -0
- package/dist/cjs/adapters/redis/index.js +178 -0
- package/dist/cjs/adapters/redis/index.js.map +1 -0
- package/dist/cjs/cleanup/engine.js +100 -0
- package/dist/cjs/cleanup/engine.js.map +1 -0
- package/dist/cjs/core/concurrencyGuard.js +50 -0
- package/dist/cjs/core/concurrencyGuard.js.map +1 -0
- package/dist/cjs/core/metrics.js +39 -0
- package/dist/cjs/core/metrics.js.map +1 -0
- package/dist/cjs/core/stateMachine.js +46 -0
- package/dist/cjs/core/stateMachine.js.map +1 -0
- package/dist/cjs/errors/index.js +127 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/http/express.js +84 -0
- package/dist/cjs/http/express.js.map +1 -0
- package/dist/cjs/http/fastify.js +70 -0
- package/dist/cjs/http/fastify.js.map +1 -0
- package/dist/cjs/idempotency/engine.js +266 -0
- package/dist/cjs/idempotency/engine.js.map +1 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lock/engine.js +187 -0
- package/dist/cjs/lock/engine.js.map +1 -0
- package/dist/cjs/observability/metrics.js +92 -0
- package/dist/cjs/observability/metrics.js.map +1 -0
- package/dist/cjs/resilience/circuitBreaker.js +129 -0
- package/dist/cjs/resilience/circuitBreaker.js.map +1 -0
- package/dist/cjs/types/index.js +13 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/utils/crypto.js +64 -0
- package/dist/cjs/utils/crypto.js.map +1 -0
- package/dist/cjs/utils/keys.js +40 -0
- package/dist/cjs/utils/keys.js.map +1 -0
- package/dist/cjs/utils/sleep.js +25 -0
- package/dist/cjs/utils/sleep.js.map +1 -0
- package/dist/esm/adapters/memory/index.js +129 -0
- package/dist/esm/adapters/memory/index.js.map +1 -0
- package/dist/esm/adapters/mongodb/index.js +184 -0
- package/dist/esm/adapters/mongodb/index.js.map +1 -0
- package/dist/esm/adapters/mongoose/index.js +193 -0
- package/dist/esm/adapters/mongoose/index.js.map +1 -0
- package/dist/esm/adapters/postgres/index.js +197 -0
- package/dist/esm/adapters/postgres/index.js.map +1 -0
- package/dist/esm/adapters/prisma/index.js +171 -0
- package/dist/esm/adapters/prisma/index.js.map +1 -0
- package/dist/esm/adapters/redis/index.js +173 -0
- package/dist/esm/adapters/redis/index.js.map +1 -0
- package/dist/esm/cleanup/engine.js +95 -0
- package/dist/esm/cleanup/engine.js.map +1 -0
- package/dist/esm/core/concurrencyGuard.js +46 -0
- package/dist/esm/core/concurrencyGuard.js.map +1 -0
- package/dist/esm/core/metrics.js +35 -0
- package/dist/esm/core/metrics.js.map +1 -0
- package/dist/esm/core/stateMachine.js +40 -0
- package/dist/esm/core/stateMachine.js.map +1 -0
- package/dist/esm/errors/index.js +114 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/http/express.js +81 -0
- package/dist/esm/http/express.js.map +1 -0
- package/dist/esm/http/fastify.js +67 -0
- package/dist/esm/http/fastify.js.map +1 -0
- package/dist/esm/idempotency/engine.js +261 -0
- package/dist/esm/idempotency/engine.js.map +1 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lock/engine.js +182 -0
- package/dist/esm/lock/engine.js.map +1 -0
- package/dist/esm/observability/metrics.js +89 -0
- package/dist/esm/observability/metrics.js.map +1 -0
- package/dist/esm/resilience/circuitBreaker.js +124 -0
- package/dist/esm/resilience/circuitBreaker.js.map +1 -0
- package/dist/esm/types/index.js +10 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/utils/crypto.js +58 -0
- package/dist/esm/utils/crypto.js.map +1 -0
- package/dist/esm/utils/keys.js +35 -0
- package/dist/esm/utils/keys.js.map +1 -0
- package/dist/esm/utils/sleep.js +20 -0
- package/dist/esm/utils/sleep.js.map +1 -0
- package/dist/types/adapters/memory/index.d.ts +49 -0
- package/dist/types/adapters/memory/index.d.ts.map +1 -0
- package/dist/types/adapters/mongodb/index.d.ts +97 -0
- package/dist/types/adapters/mongodb/index.d.ts.map +1 -0
- package/dist/types/adapters/mongoose/index.d.ts +107 -0
- package/dist/types/adapters/mongoose/index.d.ts.map +1 -0
- package/dist/types/adapters/postgres/index.d.ts +85 -0
- package/dist/types/adapters/postgres/index.d.ts.map +1 -0
- package/dist/types/adapters/prisma/index.d.ts +73 -0
- package/dist/types/adapters/prisma/index.d.ts.map +1 -0
- package/dist/types/adapters/redis/index.d.ts +77 -0
- package/dist/types/adapters/redis/index.d.ts.map +1 -0
- package/dist/types/cleanup/engine.d.ts +41 -0
- package/dist/types/cleanup/engine.d.ts.map +1 -0
- package/dist/types/core/concurrencyGuard.d.ts +28 -0
- package/dist/types/core/concurrencyGuard.d.ts.map +1 -0
- package/dist/types/core/metrics.d.ts +13 -0
- package/dist/types/core/metrics.d.ts.map +1 -0
- package/dist/types/core/stateMachine.d.ts +20 -0
- package/dist/types/core/stateMachine.d.ts.map +1 -0
- package/dist/types/errors/index.d.ts +32 -0
- package/dist/types/errors/index.d.ts.map +1 -0
- package/dist/types/http/express.d.ts +50 -0
- package/dist/types/http/express.d.ts.map +1 -0
- package/dist/types/http/fastify.d.ts +48 -0
- package/dist/types/http/fastify.d.ts.map +1 -0
- package/dist/types/idempotency/engine.d.ts +24 -0
- package/dist/types/idempotency/engine.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lock/engine.d.ts +28 -0
- package/dist/types/lock/engine.d.ts.map +1 -0
- package/dist/types/observability/metrics.d.ts +45 -0
- package/dist/types/observability/metrics.d.ts.map +1 -0
- package/dist/types/resilience/circuitBreaker.d.ts +48 -0
- package/dist/types/resilience/circuitBreaker.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +170 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/utils/crypto.d.ts +20 -0
- package/dist/types/utils/crypto.d.ts.map +1 -0
- package/dist/types/utils/keys.d.ts +15 -0
- package/dist/types/utils/keys.d.ts.map +1 -0
- package/dist/types/utils/sleep.d.ts +13 -0
- package/dist/types/utils/sleep.d.ts.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @periodic/vanadium — Core Type Definitions
|
|
3
|
+
* Deterministic idempotency and distributed lock engine
|
|
4
|
+
*/
|
|
5
|
+
export type ExecutionStatus = 'IN_PROGRESS' | 'COMPLETED' | 'FAILED';
|
|
6
|
+
export interface StoredRecord<T = unknown> {
|
|
7
|
+
/** The idempotency key */
|
|
8
|
+
key: string;
|
|
9
|
+
/** Current execution status */
|
|
10
|
+
status: ExecutionStatus;
|
|
11
|
+
/** Stored result on completion */
|
|
12
|
+
result?: T;
|
|
13
|
+
/** SHA-256 hash of payload for mismatch detection */
|
|
14
|
+
payloadHash?: string;
|
|
15
|
+
/** Lock ownership token (UUID) */
|
|
16
|
+
ownerToken?: string;
|
|
17
|
+
/** Number of execution attempts (for crash recovery) */
|
|
18
|
+
attempts: number;
|
|
19
|
+
/** Unix epoch ms — record creation time */
|
|
20
|
+
createdAt: number;
|
|
21
|
+
/** Unix epoch ms — last update time */
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
/** Unix epoch ms — record expiry time */
|
|
24
|
+
expiresAt?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface StorageAdapter {
|
|
27
|
+
/** Human-readable adapter name for error attribution */
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/** Retrieve a stored record by key. Returns null if not found. */
|
|
30
|
+
get<T = unknown>(key: string): Promise<StoredRecord<T> | null>;
|
|
31
|
+
/** Persist a record. ttlMs controls expiry. */
|
|
32
|
+
set<T = unknown>(key: string, value: StoredRecord<T>, ttlMs?: number): Promise<void>;
|
|
33
|
+
/** Remove a record by key. */
|
|
34
|
+
delete(key: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Atomic compare-and-set. Only updates if the current record's ownerToken
|
|
37
|
+
* matches expectedOwnerToken. Returns true on success, false on mismatch.
|
|
38
|
+
*/
|
|
39
|
+
compareAndSet?<T = unknown>(key: string, expectedOwnerToken: string, newValue: StoredRecord<T>, ttlMs?: number): Promise<boolean>;
|
|
40
|
+
}
|
|
41
|
+
export interface AdapterCapabilities {
|
|
42
|
+
transactions: boolean;
|
|
43
|
+
cas: boolean;
|
|
44
|
+
ttl: boolean;
|
|
45
|
+
advisoryLocks: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface IdempotencyOptions {
|
|
48
|
+
/** Storage adapter to use */
|
|
49
|
+
adapter: StorageAdapter;
|
|
50
|
+
/** Record TTL in milliseconds (default: 24 hours) */
|
|
51
|
+
ttlMs?: number;
|
|
52
|
+
/** How long to treat an IN_PROGRESS record as alive before allowing takeover */
|
|
53
|
+
inProgressExpiryMs?: number;
|
|
54
|
+
/** Called when a duplicate execution attempt is detected */
|
|
55
|
+
onDuplicate?: (context: DuplicateContext) => void;
|
|
56
|
+
/** Whether to hash the payload and detect mismatches */
|
|
57
|
+
hashPayload?: boolean;
|
|
58
|
+
/** Whether to cache function failures (default: false) */
|
|
59
|
+
cacheFailures?: boolean;
|
|
60
|
+
/** Clock function — injectable for deterministic testing */
|
|
61
|
+
clock?: () => number;
|
|
62
|
+
/** Lifecycle event hooks */
|
|
63
|
+
hooks?: IdempotencyHooks;
|
|
64
|
+
}
|
|
65
|
+
export interface LockOptions {
|
|
66
|
+
/** Storage adapter to use */
|
|
67
|
+
adapter: StorageAdapter;
|
|
68
|
+
/** Lock TTL in milliseconds */
|
|
69
|
+
ttlMs: number;
|
|
70
|
+
/** Interval between retry attempts (default: 50ms) */
|
|
71
|
+
retryIntervalMs?: number;
|
|
72
|
+
/** Maximum time to wait for lock acquisition */
|
|
73
|
+
maxWaitMs?: number;
|
|
74
|
+
/** Clock function — injectable for deterministic testing */
|
|
75
|
+
clock?: () => number;
|
|
76
|
+
/** Lifecycle event hooks */
|
|
77
|
+
hooks?: LockHooks;
|
|
78
|
+
}
|
|
79
|
+
export interface DuplicateContext {
|
|
80
|
+
key: string;
|
|
81
|
+
status: ExecutionStatus;
|
|
82
|
+
attempts: number;
|
|
83
|
+
adapterName: string;
|
|
84
|
+
}
|
|
85
|
+
export interface TakeoverContext {
|
|
86
|
+
key: string;
|
|
87
|
+
previousOwnerToken: string | undefined;
|
|
88
|
+
newOwnerToken: string;
|
|
89
|
+
attempts: number;
|
|
90
|
+
adapterName: string;
|
|
91
|
+
}
|
|
92
|
+
export interface ExecutionContext {
|
|
93
|
+
key: string;
|
|
94
|
+
attempt: number;
|
|
95
|
+
adapterName: string;
|
|
96
|
+
startedAt: number;
|
|
97
|
+
}
|
|
98
|
+
export interface LockContext {
|
|
99
|
+
key: string;
|
|
100
|
+
ownerToken: string;
|
|
101
|
+
adapterName: string;
|
|
102
|
+
acquiredAt: number;
|
|
103
|
+
ttlMs: number;
|
|
104
|
+
}
|
|
105
|
+
export interface IdempotencyHooks {
|
|
106
|
+
onBeforeExecute?: (ctx: ExecutionContext) => Promise<void> | void;
|
|
107
|
+
onAfterExecute?: (ctx: ExecutionContext & {
|
|
108
|
+
durationMs: number;
|
|
109
|
+
}) => Promise<void> | void;
|
|
110
|
+
onDuplicateHit?: (ctx: DuplicateContext) => Promise<void> | void;
|
|
111
|
+
onTakeover?: (ctx: TakeoverContext) => Promise<void> | void;
|
|
112
|
+
onStorageError?: (error: Error, key: string) => Promise<void> | void;
|
|
113
|
+
}
|
|
114
|
+
export interface LockHooks {
|
|
115
|
+
onLockAcquired?: (ctx: LockContext) => Promise<void> | void;
|
|
116
|
+
onLockReleased?: (ctx: LockContext & {
|
|
117
|
+
durationMs: number;
|
|
118
|
+
}) => Promise<void> | void;
|
|
119
|
+
onLockFailed?: (key: string, reason: string) => Promise<void> | void;
|
|
120
|
+
}
|
|
121
|
+
export interface VanadiumMetrics {
|
|
122
|
+
totalExecutions: number;
|
|
123
|
+
totalDuplicates: number;
|
|
124
|
+
totalLocksAcquired: number;
|
|
125
|
+
totalLockFailures: number;
|
|
126
|
+
totalPayloadMismatches: number;
|
|
127
|
+
inProgressCount: number;
|
|
128
|
+
totalTakeovers: number;
|
|
129
|
+
totalStorageErrors: number;
|
|
130
|
+
totalFailuresCached: number;
|
|
131
|
+
}
|
|
132
|
+
export type VanadiumErrorType = 'DUPLICATE_EXECUTION' | 'LOCK_ACQUISITION_FAILED' | 'LOCK_TIMEOUT' | 'PAYLOAD_MISMATCH' | 'CONFIGURATION_ERROR' | 'STORAGE_ERROR' | 'IN_PROGRESS' | 'STATE_TRANSITION_ERROR';
|
|
133
|
+
export interface ExecutionResult<T = unknown> {
|
|
134
|
+
result: T;
|
|
135
|
+
fromCache: boolean;
|
|
136
|
+
attempts: number;
|
|
137
|
+
durationMs: number;
|
|
138
|
+
}
|
|
139
|
+
export interface HealthCheckResult {
|
|
140
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
141
|
+
latencyMs: number;
|
|
142
|
+
adapterName: string;
|
|
143
|
+
lastError?: string;
|
|
144
|
+
checkedAt: number;
|
|
145
|
+
}
|
|
146
|
+
export interface IdempotencyEngine {
|
|
147
|
+
execute<T>(key: string, fn: () => Promise<T>, payload?: unknown): Promise<T>;
|
|
148
|
+
getMetrics(): VanadiumMetrics;
|
|
149
|
+
resetMetrics(): void;
|
|
150
|
+
}
|
|
151
|
+
export interface LockEngine {
|
|
152
|
+
acquire<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
153
|
+
getMetrics(): Pick<VanadiumMetrics, 'totalLocksAcquired' | 'totalLockFailures'>;
|
|
154
|
+
}
|
|
155
|
+
export interface CleanupOptions {
|
|
156
|
+
adapter: StorageAdapter;
|
|
157
|
+
intervalMs?: number;
|
|
158
|
+
staleThresholdMs?: number;
|
|
159
|
+
deleteOnClean?: boolean;
|
|
160
|
+
clock?: () => number;
|
|
161
|
+
}
|
|
162
|
+
export type CircuitBreakerState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
|
|
163
|
+
export interface CircuitBreakerOptions {
|
|
164
|
+
failureThreshold?: number;
|
|
165
|
+
resetTimeoutMs?: number;
|
|
166
|
+
halfOpenMaxCalls?: number;
|
|
167
|
+
}
|
|
168
|
+
export type StateTransition = `${ExecutionStatus} -> ${ExecutionStatus}`;
|
|
169
|
+
export declare const VALID_TRANSITIONS: readonly StateTransition[];
|
|
170
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministically hash an arbitrary payload using SHA-256.
|
|
3
|
+
* JSON.stringify order is normalized using sorted keys for determinism.
|
|
4
|
+
*/
|
|
5
|
+
export declare function hashPayload(payload: unknown): string;
|
|
6
|
+
/**
|
|
7
|
+
* Generate a cryptographically secure owner token (UUID v4).
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateOwnerToken(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Safely serialize a value to JSON string.
|
|
12
|
+
* Throws STORAGE_ERROR compatible message on failure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function safeJsonStringify(value: unknown): string;
|
|
15
|
+
/**
|
|
16
|
+
* Safely parse a JSON string.
|
|
17
|
+
* Throws STORAGE_ERROR compatible message on failure.
|
|
18
|
+
*/
|
|
19
|
+
export declare function safeJsonParse<T = unknown>(raw: string, context?: string): T;
|
|
20
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../src/utils/crypto.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGpD;AAmBD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOxD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,SAAW,GAAG,CAAC,CAO7E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate an idempotency key for safety and format correctness.
|
|
3
|
+
* Throws a VanadiumError (CONFIGURATION_ERROR) on invalid input.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateKey(key: string, adapterName: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Build a namespaced key: prefix + namespace + key.
|
|
8
|
+
* Example: "vanadium:payments:order_123"
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildNamespacedKey(key: string, prefix?: string, namespace?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Assert the key is valid and return it unchanged (for chaining).
|
|
13
|
+
*/
|
|
14
|
+
export declare function assertValidKey(key: string, adapterName: string): string;
|
|
15
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/utils/keys.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAmBlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,SAAS,SAAK,GAAG,MAAM,CAGnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAGvE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking async sleep.
|
|
3
|
+
*/
|
|
4
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Add ±jitter to a base delay to prevent thundering herd.
|
|
7
|
+
*/
|
|
8
|
+
export declare function jitter(baseMs: number, factor?: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Sleep with jitter applied.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sleepWithJitter(baseMs: number, factor?: number): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=sleep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../../src/utils/sleep.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,MAAM,CAG3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3E"}
|
package/package.json
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@periodic/vanadium",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Deterministic idempotency and distributed lock engine for backend systems",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"idempotency",
|
|
7
|
+
"distributed-lock",
|
|
8
|
+
"deduplication",
|
|
9
|
+
"webhook",
|
|
10
|
+
"payment",
|
|
11
|
+
"race-condition",
|
|
12
|
+
"exactly-once",
|
|
13
|
+
"distributed-systems",
|
|
14
|
+
"backend",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/udaythakur7469/periodic-vanadium#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/udaythakur7469/periodic-vanadium/issues"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/udaythakur7469/periodic-vanadium.git"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "Uday Thakur <udaythakurwork@gmail.com>",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": "./dist/esm/index.js",
|
|
31
|
+
"require": "./dist/cjs/index.js",
|
|
32
|
+
"types": "./dist/types/index.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./adapters/redis": {
|
|
35
|
+
"import": "./dist/esm/adapters/redis/index.js",
|
|
36
|
+
"require": "./dist/cjs/adapters/redis/index.js",
|
|
37
|
+
"types": "./dist/types/adapters/redis/index.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./adapters/postgres": {
|
|
40
|
+
"import": "./dist/esm/adapters/postgres/index.js",
|
|
41
|
+
"require": "./dist/cjs/adapters/postgres/index.js",
|
|
42
|
+
"types": "./dist/types/adapters/postgres/index.d.ts"
|
|
43
|
+
},
|
|
44
|
+
"./adapters/mongodb": {
|
|
45
|
+
"import": "./dist/esm/adapters/mongodb/index.js",
|
|
46
|
+
"require": "./dist/cjs/adapters/mongodb/index.js",
|
|
47
|
+
"types": "./dist/types/adapters/mongodb/index.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./adapters/mongoose": {
|
|
50
|
+
"import": "./dist/esm/adapters/mongoose/index.js",
|
|
51
|
+
"require": "./dist/cjs/adapters/mongoose/index.js",
|
|
52
|
+
"types": "./dist/types/adapters/mongoose/index.d.ts"
|
|
53
|
+
},
|
|
54
|
+
"./adapters/prisma": {
|
|
55
|
+
"import": "./dist/esm/adapters/prisma/index.js",
|
|
56
|
+
"require": "./dist/cjs/adapters/prisma/index.js",
|
|
57
|
+
"types": "./dist/types/adapters/prisma/index.d.ts"
|
|
58
|
+
},
|
|
59
|
+
"./http/express": {
|
|
60
|
+
"import": "./dist/esm/http/express.js",
|
|
61
|
+
"require": "./dist/cjs/http/express.js",
|
|
62
|
+
"types": "./dist/types/http/express.d.ts"
|
|
63
|
+
},
|
|
64
|
+
"./http/fastify": {
|
|
65
|
+
"import": "./dist/esm/http/fastify.js",
|
|
66
|
+
"require": "./dist/cjs/http/fastify.js",
|
|
67
|
+
"types": "./dist/types/http/fastify.d.ts"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"main": "./dist/cjs/index.js",
|
|
71
|
+
"module": "./dist/esm/index.js",
|
|
72
|
+
"types": "./dist/types/index.d.ts",
|
|
73
|
+
"files": [
|
|
74
|
+
"dist",
|
|
75
|
+
"README.md",
|
|
76
|
+
"CHANGELOG.md",
|
|
77
|
+
"LICENSE"
|
|
78
|
+
],
|
|
79
|
+
"scripts": {
|
|
80
|
+
"build": "npm run build:esm && npm run build:cjs && npm run build:types",
|
|
81
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
82
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
83
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
84
|
+
"clean": "rm -rf dist",
|
|
85
|
+
"prebuild": "npm run clean",
|
|
86
|
+
"test": "jest --coverage",
|
|
87
|
+
"test:ci": "jest --coverage --ci --forceExit",
|
|
88
|
+
"lint": "eslint src --ext .ts",
|
|
89
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
90
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
91
|
+
"typecheck": "tsc --noEmit",
|
|
92
|
+
"prepublishOnly": "npm run format && npm run build && npm run test:ci"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"@opentelemetry/api": ">=1.0.0",
|
|
96
|
+
"@prisma/client": ">=5.0.0",
|
|
97
|
+
"mongodb": ">=5.0.0",
|
|
98
|
+
"mongoose": ">=7.0.0",
|
|
99
|
+
"pg": ">=8.0.0",
|
|
100
|
+
"redis": ">=4.0.0"
|
|
101
|
+
},
|
|
102
|
+
"peerDependenciesMeta": {
|
|
103
|
+
"redis": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"pg": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"mongodb": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"mongoose": {
|
|
113
|
+
"optional": true
|
|
114
|
+
},
|
|
115
|
+
"@prisma/client": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"@opentelemetry/api": {
|
|
119
|
+
"optional": true
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"devDependencies": {
|
|
123
|
+
"@types/jest": "^29.5.12",
|
|
124
|
+
"@types/node": "^20.12.7",
|
|
125
|
+
"@types/pg": "^8.11.5",
|
|
126
|
+
"@typescript-eslint/eslint-plugin": "^7.7.1",
|
|
127
|
+
"@typescript-eslint/parser": "^7.7.1",
|
|
128
|
+
"eslint": "^8.57.0",
|
|
129
|
+
"eslint-config-prettier": "^9.1.0",
|
|
130
|
+
"eslint-plugin-prettier": "^5.1.2",
|
|
131
|
+
"jest": "^29.7.0",
|
|
132
|
+
"prettier": "^3.2.5",
|
|
133
|
+
"ts-jest": "^29.1.2",
|
|
134
|
+
"typescript": "^5.4.5"
|
|
135
|
+
},
|
|
136
|
+
"engines": {
|
|
137
|
+
"node": ">=18.0.0"
|
|
138
|
+
},
|
|
139
|
+
"sideEffects": false
|
|
140
|
+
}
|