@hardkas/core 0.2.2-alpha → 0.3.0-alpha

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/dist/index.d.ts CHANGED
@@ -276,6 +276,136 @@ type UnknownEventPayload = {
276
276
  */
277
277
  type Branded<K, T> = Brand<T, K extends string ? K : string>;
278
278
 
279
+ /**
280
+ * Redacts sensitive information from strings and objects recursively.
281
+ * Masks Kaspa private keys (64 hex chars) and mnemonics.
282
+ */
283
+ declare function maskSecrets(data: any): any;
284
+ /**
285
+ * Legacy single-value redaction for backward compatibility.
286
+ */
287
+ declare function redactSecret(value: string): string;
288
+
289
+ /**
290
+ * Options for atomic file writing.
291
+ */
292
+ interface WriteFileAtomicOptions {
293
+ /** Encoding for string data (default: utf-8) */
294
+ encoding?: BufferEncoding;
295
+ /** File mode (permissions) */
296
+ mode?: number;
297
+ /** If true, calls fsync on the parent directory (Linux/macOS) */
298
+ fsyncParent?: boolean;
299
+ }
300
+ /**
301
+ * Writes a file atomically using the temp-file-and-rename pattern.
302
+ * Ensures that either the entire file is written or no changes are made.
303
+ *
304
+ * Pattern:
305
+ * 1. Write data to a temporary file in the same directory.
306
+ * 2. fsync the temporary file to ensure data is on disk.
307
+ * 3. Close the temporary file.
308
+ * 4. Rename the temporary file to the target path (atomic operation).
309
+ * 5. Optional: fsync the parent directory to ensure metadata is on disk.
310
+ */
311
+ declare function writeFileAtomic(targetPath: string, data: string | Buffer, options?: WriteFileAtomicOptions): Promise<void>;
312
+ /**
313
+ * Synchronous version of writeFileAtomic.
314
+ */
315
+ declare function writeFileAtomicSync(targetPath: string, data: string | Buffer, options?: WriteFileAtomicOptions): void;
316
+
317
+ /**
318
+ * HardKAS Corruption Taxonomy & Issue Reporting
319
+ */
320
+ type CorruptionCode = "ARTIFACT_JSON_INVALID" | "ARTIFACT_SCHEMA_MISSING" | "ARTIFACT_SCHEMA_INVALID" | "ARTIFACT_HASH_MISMATCH" | "ARTIFACT_ID_INVALID" | "ARTIFACT_LINEAGE_INVALID" | "EVENT_JSON_INVALID" | "EVENT_SCHEMA_INVALID" | "EVENT_LINE_CORRUPT" | "STORE_STALE" | "STORE_CORRUPT" | "STORE_REBUILD_REQUIRED" | "DUPLICATE_ARTIFACT" | "DUPLICATE_EVENT" | "SEMANTIC_DIVERGENCE" | "REPLAY_PARTIAL" | "REPLAY_UNSUPPORTED_CHECK" | "LOCK_HELD" | "LOCK_TIMEOUT" | "STALE_LOCK" | "LOCK_RELEASE_FAILED" | "LOCK_OWNER_MISMATCH" | "LOCK_METADATA_INVALID" | "STORE_MIGRATION_REQUIRED" | "STORE_MIGRATION_FAILED" | "STORE_MIGRATION_CHECKSUM_MISMATCH" | "STORE_SCHEMA_UNSUPPORTED" | "STORE_LEGACY_BOOTSTRAPPED";
321
+ type CorruptionSeverity = "warning" | "error";
322
+ interface CorruptionIssue {
323
+ readonly code: CorruptionCode;
324
+ readonly severity: CorruptionSeverity;
325
+ readonly message: string;
326
+ readonly path?: string;
327
+ readonly lineNumber?: number;
328
+ readonly artifactId?: string;
329
+ readonly contentHash?: string;
330
+ readonly suggestion?: string;
331
+ }
332
+ /**
333
+ * Formats a corruption issue for human-readable output.
334
+ */
335
+ declare function formatCorruptionIssue(issue: CorruptionIssue): string;
336
+
337
+ /**
338
+ * HardKAS Lock Metadata schema v1
339
+ */
340
+ interface LockMetadata {
341
+ schema: "hardkas.lock.v1";
342
+ name: string;
343
+ pid: number;
344
+ command: string;
345
+ cwd: string;
346
+ hostname: string;
347
+ createdAt: string;
348
+ expiresAt: string | null;
349
+ }
350
+ interface LockHandle {
351
+ readonly path: string;
352
+ readonly metadata: LockMetadata;
353
+ release(): Promise<void>;
354
+ }
355
+ interface AcquireLockArgs {
356
+ rootDir: string;
357
+ name: string;
358
+ command?: string;
359
+ staleMs?: number;
360
+ wait?: boolean;
361
+ timeoutMs?: number;
362
+ pollMs?: number;
363
+ }
364
+ /**
365
+ * Deterministic lock ordering to avoid deadlocks.
366
+ * workspace > node > accounts > artifacts > events > query-store
367
+ */
368
+ declare const LOCK_ORDER: string[];
369
+ /**
370
+ * Acquires a named lock for the workspace.
371
+ */
372
+ declare function acquireLock(args: AcquireLockArgs): Promise<LockHandle>;
373
+ /**
374
+ * Helper to run a task with a single lock.
375
+ */
376
+ declare function withLock<T>(args: AcquireLockArgs, fn: (handle: LockHandle) => Promise<T>): Promise<T>;
377
+ /**
378
+ * Helper to run a task with multiple locks in deterministic order.
379
+ */
380
+ declare function withLocks<T>(rootDir: string, names: string[], fn: () => Promise<T>, options?: {
381
+ command?: string;
382
+ wait?: boolean;
383
+ timeoutMs?: number;
384
+ }): Promise<T>;
385
+ /**
386
+ * Checks if a process is alive.
387
+ */
388
+ declare function isProcessAlive(pid: number): boolean;
389
+ /**
390
+ * Lists all active locks in the workspace.
391
+ */
392
+ declare function listLocks(rootDir: string): Array<{
393
+ name: string;
394
+ metadata: LockMetadata;
395
+ path: string;
396
+ isAlive: boolean;
397
+ }>;
398
+ /**
399
+ * Safely clears a lock if criteria are met.
400
+ */
401
+ declare function clearLock(rootDir: string, name: string, options?: {
402
+ force?: boolean;
403
+ ifDead?: boolean;
404
+ }): {
405
+ cleared: boolean;
406
+ reason?: string;
407
+ };
408
+
279
409
  declare const SOMPI_PER_KAS = 100000000n;
280
410
  declare const kaspaNetworkIdSchema: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet"]>;
281
411
  type NetworkId = Brand<z.infer<typeof kaspaNetworkIdSchema>, "NetworkId">;
@@ -352,8 +482,18 @@ declare class HardkasError extends Error {
352
482
  cause?: unknown;
353
483
  });
354
484
  }
485
+ type InvariantDomain = "semantic" | "replay" | "provenance" | "structural" | "operational";
486
+ type InvariantSeverity = "warning" | "error" | "fatal";
487
+ declare class InvariantViolationError extends HardkasError {
488
+ readonly domain: InvariantDomain;
489
+ readonly severity: InvariantSeverity;
490
+ constructor(domain: InvariantDomain, message: string, options?: {
491
+ severity?: InvariantSeverity;
492
+ cause?: unknown;
493
+ });
494
+ }
355
495
  declare function parseHardkasConfig(input: unknown): HardkasConfig;
356
496
  declare function parseKasToSompi(input: string): bigint;
357
497
  declare function formatSompi(amountSompi: bigint): string;
358
498
 
359
- export { type ArtifactId, type ArtifactType, ArtifactTypeSchema, type Brand, type Branded, type ContentHash, type CoreEvent, type CoreEventListener, type CorrelationId, type DaaScore, type EventDomain, type EventEnvelope, type EventId, type EventKind, type EventPayloadByKind, type EventSequence, type ExecutionMode, ExecutionModeSchema, type HardkasConfig, HardkasError, type KaspaAddress, type LineageId, type NetworkId, NetworkIdSchema, type RpcEndpointId, SOMPI_PER_KAS, type StampedEvent, type TxId, type UnknownEventPayload, type WorkflowId, artifactTypeSchema, asArtifactId, asContentHash, asCorrelationId, asDaaScore, asEventId, asEventSequence, asKaspaAddress, asLineageId, asNetworkId, asRpcEndpointId, asTxId, asWorkflowId, coreEvents, createEventEnvelope, executionModeSchema, formatSompi, hardkasConfigSchema, kaspaNetworkIdSchema, parseHardkasConfig, parseKasToSompi, validateEventEnvelope };
499
+ export { type AcquireLockArgs, type ArtifactId, type ArtifactType, ArtifactTypeSchema, type Brand, type Branded, type ContentHash, type CoreEvent, type CoreEventListener, type CorrelationId, type CorruptionCode, type CorruptionIssue, type CorruptionSeverity, type DaaScore, type EventDomain, type EventEnvelope, type EventId, type EventKind, type EventPayloadByKind, type EventSequence, type ExecutionMode, ExecutionModeSchema, type HardkasConfig, HardkasError, type InvariantDomain, type InvariantSeverity, InvariantViolationError, type KaspaAddress, LOCK_ORDER, type LineageId, type LockHandle, type LockMetadata, type NetworkId, NetworkIdSchema, type RpcEndpointId, SOMPI_PER_KAS, type StampedEvent, type TxId, type UnknownEventPayload, type WorkflowId, type WriteFileAtomicOptions, acquireLock, artifactTypeSchema, asArtifactId, asContentHash, asCorrelationId, asDaaScore, asEventId, asEventSequence, asKaspaAddress, asLineageId, asNetworkId, asRpcEndpointId, asTxId, asWorkflowId, clearLock, coreEvents, createEventEnvelope, executionModeSchema, formatCorruptionIssue, formatSompi, hardkasConfigSchema, isProcessAlive, kaspaNetworkIdSchema, listLocks, maskSecrets, parseHardkasConfig, parseKasToSompi, redactSecret, validateEventEnvelope, withLock, withLocks, writeFileAtomic, writeFileAtomicSync };
package/dist/index.js CHANGED
@@ -77,6 +77,349 @@ var asNetworkId = (id) => id;
77
77
  var asEventSequence = (seq) => seq;
78
78
  var asDaaScore = (score) => score;
79
79
 
80
+ // src/security.ts
81
+ function maskSecrets(data) {
82
+ if (data === null || data === void 0) return data;
83
+ if (typeof data === "string") {
84
+ let redacted = data.replace(/\b[0-9a-fA-F]{64}\b/g, (match) => {
85
+ return `${match.slice(0, 6)}...${match.slice(-4)} [REDACTED]`;
86
+ });
87
+ redacted = redacted.replace(/\b([a-z]{3,10}\s+){11,23}[a-z]{3,10}\b/g, "[MNEMONIC REDACTED]");
88
+ return redacted;
89
+ }
90
+ if (Array.isArray(data)) {
91
+ return data.map((item) => maskSecrets(item));
92
+ }
93
+ if (typeof data === "object") {
94
+ const redactedObj = {};
95
+ for (const key in data) {
96
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
97
+ if (key.toLowerCase().includes("secret") || key.toLowerCase().includes("privatekey") || key.toLowerCase().includes("mnemonic") || key.toLowerCase().includes("password")) {
98
+ redactedObj[key] = "[REDACTED]";
99
+ } else {
100
+ redactedObj[key] = maskSecrets(data[key]);
101
+ }
102
+ }
103
+ }
104
+ return redactedObj;
105
+ }
106
+ return data;
107
+ }
108
+ function redactSecret(value) {
109
+ if (!value) return "";
110
+ if (value.length <= 10) return "***";
111
+ return `${value.slice(0, 6)}...${value.slice(-4)}`;
112
+ }
113
+
114
+ // src/fs.ts
115
+ import fs from "fs";
116
+ import path from "path";
117
+ async function writeFileAtomic(targetPath, data, options = {}) {
118
+ const dir = path.dirname(targetPath);
119
+ const base = path.basename(targetPath);
120
+ const tempPath = path.join(dir, `.tmp.${base}.${Math.random().toString(36).slice(2)}`);
121
+ let fd = null;
122
+ try {
123
+ if (!fs.existsSync(dir)) {
124
+ fs.mkdirSync(dir, { recursive: true });
125
+ }
126
+ fd = fs.openSync(tempPath, "w", options.mode);
127
+ const buffer = typeof data === "string" ? Buffer.from(data, options.encoding || "utf-8") : data;
128
+ fs.writeSync(fd, buffer, 0, buffer.length);
129
+ fs.fsyncSync(fd);
130
+ fs.closeSync(fd);
131
+ fd = null;
132
+ let attempts = 0;
133
+ const maxAttempts = process.platform === "win32" ? 5 : 1;
134
+ while (attempts < maxAttempts) {
135
+ try {
136
+ fs.renameSync(tempPath, targetPath);
137
+ break;
138
+ } catch (e) {
139
+ attempts++;
140
+ if (attempts >= maxAttempts) throw e;
141
+ if (e.code === "EPERM" || e.code === "EBUSY") {
142
+ await new Promise((resolve) => setTimeout(resolve, 10 * attempts));
143
+ continue;
144
+ }
145
+ throw e;
146
+ }
147
+ }
148
+ if (options.fsyncParent && process.platform !== "win32") {
149
+ let dirFd = null;
150
+ try {
151
+ dirFd = fs.openSync(dir, "r");
152
+ fs.fsyncSync(dirFd);
153
+ } catch (e) {
154
+ } finally {
155
+ if (dirFd !== null) fs.closeSync(dirFd);
156
+ }
157
+ }
158
+ } catch (err) {
159
+ throw new HardkasError(
160
+ "IO_ERROR",
161
+ `Failed to write file atomically: ${targetPath}`,
162
+ { cause: err }
163
+ );
164
+ } finally {
165
+ if (fs.existsSync(tempPath)) {
166
+ try {
167
+ fs.unlinkSync(tempPath);
168
+ } catch (e) {
169
+ }
170
+ }
171
+ if (fd !== null) {
172
+ try {
173
+ fs.closeSync(fd);
174
+ } catch (e) {
175
+ }
176
+ }
177
+ }
178
+ }
179
+ function writeFileAtomicSync(targetPath, data, options = {}) {
180
+ const dir = path.dirname(targetPath);
181
+ const base = path.basename(targetPath);
182
+ const tempPath = path.join(dir, `.tmp.${base}.${Math.random().toString(36).slice(2)}`);
183
+ let fd = null;
184
+ try {
185
+ if (!fs.existsSync(dir)) {
186
+ fs.mkdirSync(dir, { recursive: true });
187
+ }
188
+ fd = fs.openSync(tempPath, "w", options.mode);
189
+ const buffer = typeof data === "string" ? Buffer.from(data, options.encoding || "utf-8") : data;
190
+ fs.writeSync(fd, buffer, 0, buffer.length);
191
+ fs.fsyncSync(fd);
192
+ fs.closeSync(fd);
193
+ fd = null;
194
+ let attempts = 0;
195
+ const maxAttempts = process.platform === "win32" ? 5 : 1;
196
+ while (attempts < maxAttempts) {
197
+ try {
198
+ fs.renameSync(tempPath, targetPath);
199
+ break;
200
+ } catch (e) {
201
+ attempts++;
202
+ if (attempts >= maxAttempts) throw e;
203
+ if (e.code === "EPERM" || e.code === "EBUSY") {
204
+ continue;
205
+ }
206
+ throw e;
207
+ }
208
+ }
209
+ if (options.fsyncParent && process.platform !== "win32") {
210
+ let dirFd = null;
211
+ try {
212
+ dirFd = fs.openSync(dir, "r");
213
+ fs.fsyncSync(dirFd);
214
+ } catch (e) {
215
+ } finally {
216
+ if (dirFd !== null) fs.closeSync(dirFd);
217
+ }
218
+ }
219
+ } catch (err) {
220
+ throw new HardkasError(
221
+ "IO_ERROR",
222
+ `Failed to write file atomically (sync): ${targetPath}`,
223
+ { cause: err }
224
+ );
225
+ } finally {
226
+ if (fs.existsSync(tempPath)) {
227
+ try {
228
+ fs.unlinkSync(tempPath);
229
+ } catch (e) {
230
+ }
231
+ }
232
+ if (fd !== null) {
233
+ try {
234
+ fs.closeSync(fd);
235
+ } catch (e) {
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ // src/corruption.ts
242
+ function formatCorruptionIssue(issue) {
243
+ const parts = [];
244
+ const icon = issue.severity === "error" ? "\u274C" : "\u26A0\uFE0F";
245
+ parts.push(`${icon} [${issue.code}] ${issue.message}`);
246
+ if (issue.path) {
247
+ const loc = issue.lineNumber ? `${issue.path}:${issue.lineNumber}` : issue.path;
248
+ parts.push(` Location: ${loc}`);
249
+ }
250
+ if (issue.artifactId) {
251
+ parts.push(` Artifact: ${issue.artifactId}`);
252
+ }
253
+ if (issue.suggestion) {
254
+ parts.push(` Suggestion: ${issue.suggestion}`);
255
+ }
256
+ return parts.join("\n");
257
+ }
258
+
259
+ // src/lock.ts
260
+ import fs2 from "fs";
261
+ import path2 from "path";
262
+ import os from "os";
263
+ var LOCK_ORDER = [
264
+ "workspace",
265
+ "node",
266
+ "accounts",
267
+ "artifacts",
268
+ "events",
269
+ "query-store"
270
+ ];
271
+ async function acquireLock(args) {
272
+ const lockDir = path2.join(args.rootDir, ".hardkas", "locks");
273
+ const lockPath = path2.join(lockDir, `${args.name}.lock`);
274
+ const timeoutMs = args.timeoutMs ?? 3e4;
275
+ const pollMs = args.pollMs ?? 250;
276
+ const start = Date.now();
277
+ if (!fs2.existsSync(lockDir)) {
278
+ fs2.mkdirSync(lockDir, { recursive: true });
279
+ }
280
+ while (true) {
281
+ try {
282
+ const metadata = {
283
+ schema: "hardkas.lock.v1",
284
+ name: args.name,
285
+ pid: process.pid,
286
+ command: args.command || process.argv.join(" "),
287
+ cwd: process.cwd(),
288
+ hostname: os.hostname(),
289
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
290
+ expiresAt: null
291
+ };
292
+ const fd = fs2.openSync(lockPath, "wx");
293
+ fs2.writeSync(fd, JSON.stringify(metadata, null, 2));
294
+ fs2.closeSync(fd);
295
+ return {
296
+ path: lockPath,
297
+ metadata,
298
+ release: async () => {
299
+ if (fs2.existsSync(lockPath)) {
300
+ try {
301
+ const current = JSON.parse(fs2.readFileSync(lockPath, "utf-8"));
302
+ if (current.pid === process.pid) {
303
+ fs2.unlinkSync(lockPath);
304
+ }
305
+ } catch (e) {
306
+ }
307
+ }
308
+ }
309
+ };
310
+ } catch (e) {
311
+ if (e.code === "EEXIST") {
312
+ let existingMetadata = null;
313
+ try {
314
+ existingMetadata = JSON.parse(fs2.readFileSync(lockPath, "utf-8"));
315
+ } catch (err) {
316
+ throw new HardkasError("LOCK_METADATA_INVALID", `Lock file at ${lockPath} is corrupted.`, { cause: err });
317
+ }
318
+ if (existingMetadata) {
319
+ const isAlive = isProcessAlive(existingMetadata.pid);
320
+ if (!isAlive) {
321
+ throw new HardkasError(
322
+ "STALE_LOCK",
323
+ `Workspace is locked by a dead process (PID: ${existingMetadata.pid}).`,
324
+ { cause: existingMetadata }
325
+ );
326
+ }
327
+ if (args.wait && Date.now() - start < timeoutMs) {
328
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
329
+ continue;
330
+ }
331
+ throw new HardkasError(
332
+ args.wait ? "LOCK_TIMEOUT" : "LOCK_HELD",
333
+ `Workspace is locked by another HardKAS process (PID: ${existingMetadata.pid}).`,
334
+ { cause: existingMetadata }
335
+ );
336
+ }
337
+ }
338
+ throw e;
339
+ }
340
+ }
341
+ }
342
+ async function withLock(args, fn) {
343
+ const handle = await acquireLock(args);
344
+ try {
345
+ return await fn(handle);
346
+ } finally {
347
+ await handle.release();
348
+ }
349
+ }
350
+ async function withLocks(rootDir, names, fn, options = {}) {
351
+ const sortedNames = [...names].sort((a, b) => {
352
+ const idxA = LOCK_ORDER.indexOf(a);
353
+ const idxB = LOCK_ORDER.indexOf(b);
354
+ return idxA - idxB;
355
+ });
356
+ const handles = [];
357
+ try {
358
+ for (const name of sortedNames) {
359
+ handles.push(await acquireLock({ rootDir, name, ...options }));
360
+ }
361
+ return await fn();
362
+ } finally {
363
+ for (const handle of handles.reverse()) {
364
+ await handle.release();
365
+ }
366
+ }
367
+ }
368
+ function isProcessAlive(pid) {
369
+ try {
370
+ process.kill(pid, 0);
371
+ return true;
372
+ } catch (e) {
373
+ return e.code !== "ESRCH";
374
+ }
375
+ }
376
+ function listLocks(rootDir) {
377
+ const lockDir = path2.join(rootDir, ".hardkas", "locks");
378
+ if (!fs2.existsSync(lockDir)) return [];
379
+ const files = fs2.readdirSync(lockDir).filter((f) => f.endsWith(".lock"));
380
+ const result = [];
381
+ for (const file of files) {
382
+ const lockPath = path2.join(lockDir, file);
383
+ try {
384
+ const metadata = JSON.parse(fs2.readFileSync(lockPath, "utf-8"));
385
+ result.push({
386
+ name: path2.basename(file, ".lock"),
387
+ metadata,
388
+ path: lockPath,
389
+ isAlive: metadata.hostname === os.hostname() ? isProcessAlive(metadata.pid) : true
390
+ // Assume alive if remote
391
+ });
392
+ } catch (e) {
393
+ }
394
+ }
395
+ return result;
396
+ }
397
+ function clearLock(rootDir, name, options = {}) {
398
+ const lockDir = path2.join(rootDir, ".hardkas", "locks");
399
+ const lockPath = path2.join(lockDir, `${name}.lock`);
400
+ if (!fs2.existsSync(lockPath)) return { cleared: false, reason: "Lock not found" };
401
+ let metadata;
402
+ try {
403
+ metadata = JSON.parse(fs2.readFileSync(lockPath, "utf-8"));
404
+ } catch (e) {
405
+ if (options.force) {
406
+ fs2.unlinkSync(lockPath);
407
+ return { cleared: true };
408
+ }
409
+ return { cleared: false, reason: "Corrupt metadata (use --force to clear)" };
410
+ }
411
+ const isLocal = metadata.hostname === os.hostname();
412
+ const isAlive = isLocal ? isProcessAlive(metadata.pid) : true;
413
+ if (options.ifDead) {
414
+ if (!isLocal) return { cleared: false, reason: "Cannot verify liveness of remote lock (host: " + metadata.hostname + ")" };
415
+ if (isAlive) return { cleared: false, reason: `Process (PID: ${metadata.pid}) is still alive` };
416
+ } else if (!options.force) {
417
+ return { cleared: false, reason: "Lock is potentially active. Use --force or --if-dead." };
418
+ }
419
+ fs2.unlinkSync(lockPath);
420
+ return { cleared: true };
421
+ }
422
+
80
423
  // src/index.ts
81
424
  var SOMPI_PER_KAS = 100000000n;
82
425
  var kaspaNetworkIdSchema = z.enum([
@@ -127,6 +470,16 @@ var HardkasError = class extends Error {
127
470
  this.cause = options?.cause;
128
471
  }
129
472
  };
473
+ var InvariantViolationError = class extends HardkasError {
474
+ domain;
475
+ severity;
476
+ constructor(domain, message, options) {
477
+ super(`INVARIANT_VIOLATION_${domain.toUpperCase()}`, message, { cause: options?.cause });
478
+ this.name = "InvariantViolationError";
479
+ this.domain = domain;
480
+ this.severity = options?.severity || "fatal";
481
+ }
482
+ };
130
483
  function parseHardkasConfig(input) {
131
484
  const result = hardkasConfigSchema.safeParse(input);
132
485
  if (!result.success) {
@@ -160,8 +513,11 @@ export {
160
513
  ArtifactTypeSchema,
161
514
  ExecutionModeSchema,
162
515
  HardkasError,
516
+ InvariantViolationError,
517
+ LOCK_ORDER,
163
518
  NetworkIdSchema,
164
519
  SOMPI_PER_KAS,
520
+ acquireLock,
165
521
  artifactTypeSchema,
166
522
  asArtifactId,
167
523
  asContentHash,
@@ -175,13 +531,23 @@ export {
175
531
  asRpcEndpointId,
176
532
  asTxId,
177
533
  asWorkflowId,
534
+ clearLock,
178
535
  coreEvents,
179
536
  createEventEnvelope,
180
537
  executionModeSchema,
538
+ formatCorruptionIssue,
181
539
  formatSompi,
182
540
  hardkasConfigSchema,
541
+ isProcessAlive,
183
542
  kaspaNetworkIdSchema,
543
+ listLocks,
544
+ maskSecrets,
184
545
  parseHardkasConfig,
185
546
  parseKasToSompi,
186
- validateEventEnvelope
547
+ redactSecret,
548
+ validateEventEnvelope,
549
+ withLock,
550
+ withLocks,
551
+ writeFileAtomic,
552
+ writeFileAtomicSync
187
553
  };
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@hardkas/core",
3
- "version": "0.2.2-alpha",
3
+ "version": "0.3.0-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "exports": {
8
- ".": "./dist/index.js"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
9
12
  },
10
13
  "dependencies": {
11
14
  "pino": "^9.5.0",