@herdctl/core 0.0.1 → 0.0.2
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/config/__tests__/agent.test.js +31 -13
- package/dist/config/__tests__/agent.test.js.map +1 -1
- package/dist/config/__tests__/merge.test.js +9 -2
- package/dist/config/__tests__/merge.test.js.map +1 -1
- package/dist/config/__tests__/schema.test.js +350 -1
- package/dist/config/__tests__/schema.test.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +828 -24
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +118 -6
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet-manager/__tests__/coverage.test.js +11 -332
- package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/errors.test.js +1 -49
- package/dist/fleet-manager/__tests__/errors.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/integration.test.js +109 -0
- package/dist/fleet-manager/__tests__/integration.test.js.map +1 -1
- package/dist/fleet-manager/__tests__/reload.test.js +1 -1
- package/dist/fleet-manager/__tests__/reload.test.js.map +1 -1
- package/dist/fleet-manager/config-reload.d.ts +164 -0
- package/dist/fleet-manager/config-reload.d.ts.map +1 -0
- package/dist/fleet-manager/config-reload.js +445 -0
- package/dist/fleet-manager/config-reload.js.map +1 -0
- package/dist/fleet-manager/context.d.ts +76 -0
- package/dist/fleet-manager/context.d.ts.map +1 -0
- package/dist/fleet-manager/context.js +11 -0
- package/dist/fleet-manager/context.js.map +1 -0
- package/dist/fleet-manager/errors.d.ts +0 -25
- package/dist/fleet-manager/errors.d.ts.map +1 -1
- package/dist/fleet-manager/errors.js +0 -38
- package/dist/fleet-manager/errors.js.map +1 -1
- package/dist/fleet-manager/event-emitters.d.ts +123 -0
- package/dist/fleet-manager/event-emitters.d.ts.map +1 -0
- package/dist/fleet-manager/event-emitters.js +136 -0
- package/dist/fleet-manager/event-emitters.js.map +1 -0
- package/dist/fleet-manager/event-types.d.ts +0 -15
- package/dist/fleet-manager/event-types.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.d.ts +40 -653
- package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.js +95 -1720
- package/dist/fleet-manager/fleet-manager.js.map +1 -1
- package/dist/fleet-manager/index.d.ts +13 -2
- package/dist/fleet-manager/index.d.ts.map +1 -1
- package/dist/fleet-manager/index.js +19 -6
- package/dist/fleet-manager/index.js.map +1 -1
- package/dist/fleet-manager/job-control.d.ts +64 -0
- package/dist/fleet-manager/job-control.d.ts.map +1 -0
- package/dist/fleet-manager/job-control.js +296 -0
- package/dist/fleet-manager/job-control.js.map +1 -0
- package/dist/fleet-manager/log-streaming.d.ts +171 -0
- package/dist/fleet-manager/log-streaming.d.ts.map +1 -0
- package/dist/fleet-manager/log-streaming.js +503 -0
- package/dist/fleet-manager/log-streaming.js.map +1 -0
- package/dist/fleet-manager/schedule-executor.d.ts +63 -0
- package/dist/fleet-manager/schedule-executor.d.ts.map +1 -0
- package/dist/fleet-manager/schedule-executor.js +209 -0
- package/dist/fleet-manager/schedule-executor.js.map +1 -0
- package/dist/fleet-manager/schedule-management.d.ts +71 -0
- package/dist/fleet-manager/schedule-management.d.ts.map +1 -0
- package/dist/fleet-manager/schedule-management.js +171 -0
- package/dist/fleet-manager/schedule-management.js.map +1 -0
- package/dist/fleet-manager/status-queries.d.ts +105 -0
- package/dist/fleet-manager/status-queries.d.ts.map +1 -0
- package/dist/fleet-manager/status-queries.js +247 -0
- package/dist/fleet-manager/status-queries.js.map +1 -0
- package/dist/fleet-manager/types.d.ts +0 -39
- package/dist/fleet-manager/types.d.ts.map +1 -1
- package/dist/runner/__tests__/job-executor.test.js +206 -1
- package/dist/runner/__tests__/job-executor.test.js.map +1 -1
- package/dist/runner/job-executor.d.ts +9 -0
- package/dist/runner/job-executor.d.ts.map +1 -1
- package/dist/runner/job-executor.js +78 -4
- package/dist/runner/job-executor.js.map +1 -1
- package/dist/runner/types.d.ts +2 -0
- package/dist/runner/types.d.ts.map +1 -1
- package/dist/scheduler/__tests__/cron.test.d.ts +2 -0
- package/dist/scheduler/__tests__/cron.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/cron.test.js +867 -0
- package/dist/scheduler/__tests__/cron.test.js.map +1 -0
- package/dist/scheduler/__tests__/scheduler.test.js +164 -5
- package/dist/scheduler/__tests__/scheduler.test.js.map +1 -1
- package/dist/scheduler/cron.d.ts +126 -0
- package/dist/scheduler/cron.d.ts.map +1 -0
- package/dist/scheduler/cron.js +390 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/errors.d.ts +81 -1
- package/dist/scheduler/errors.d.ts.map +1 -1
- package/dist/scheduler/errors.js +81 -6
- package/dist/scheduler/errors.js.map +1 -1
- package/dist/scheduler/index.d.ts +1 -0
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +2 -0
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/schedule-runner.d.ts +2 -2
- package/dist/scheduler/schedule-runner.d.ts.map +1 -1
- package/dist/scheduler/schedule-runner.js +20 -8
- package/dist/scheduler/schedule-runner.js.map +1 -1
- package/dist/scheduler/scheduler.d.ts +4 -4
- package/dist/scheduler/scheduler.d.ts.map +1 -1
- package/dist/scheduler/scheduler.js +86 -20
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/types.d.ts +1 -1
- package/dist/scheduler/types.d.ts.map +1 -1
- package/dist/state/schemas/job-metadata.d.ts +2 -2
- package/package.json +33 -8
- package/.turbo/turbo-build.log +0 -4
- package/.turbo/turbo-test.log +0 -219
- package/.turbo/turbo-typecheck.log +0 -4
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -51
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -251
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/config/index.html +0 -191
- package/coverage/src/config/index.ts.html +0 -442
- package/coverage/src/config/interpolate.ts.html +0 -652
- package/coverage/src/config/loader.ts.html +0 -1501
- package/coverage/src/config/merge.ts.html +0 -823
- package/coverage/src/config/parser.ts.html +0 -1213
- package/coverage/src/config/schema.ts.html +0 -1123
- package/coverage/src/fleet-manager/errors.ts.html +0 -2326
- package/coverage/src/fleet-manager/event-types.ts.html +0 -1219
- package/coverage/src/fleet-manager/fleet-manager.ts.html +0 -7030
- package/coverage/src/fleet-manager/index.html +0 -206
- package/coverage/src/fleet-manager/index.ts.html +0 -469
- package/coverage/src/fleet-manager/job-manager.ts.html +0 -2074
- package/coverage/src/fleet-manager/job-queue.ts.html +0 -2479
- package/coverage/src/fleet-manager/types.ts.html +0 -2602
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -181
- package/coverage/src/runner/errors.ts.html +0 -1006
- package/coverage/src/runner/index.html +0 -191
- package/coverage/src/runner/index.ts.html +0 -256
- package/coverage/src/runner/job-executor.ts.html +0 -1429
- package/coverage/src/runner/message-processor.ts.html +0 -1150
- package/coverage/src/runner/sdk-adapter.ts.html +0 -658
- package/coverage/src/runner/types.ts.html +0 -559
- package/coverage/src/scheduler/errors.ts.html +0 -388
- package/coverage/src/scheduler/index.html +0 -206
- package/coverage/src/scheduler/index.ts.html +0 -244
- package/coverage/src/scheduler/interval.ts.html +0 -652
- package/coverage/src/scheduler/schedule-runner.ts.html +0 -1411
- package/coverage/src/scheduler/schedule-state.ts.html +0 -718
- package/coverage/src/scheduler/scheduler.ts.html +0 -1795
- package/coverage/src/scheduler/types.ts.html +0 -733
- package/coverage/src/state/directory.ts.html +0 -736
- package/coverage/src/state/errors.ts.html +0 -376
- package/coverage/src/state/fleet-state.ts.html +0 -937
- package/coverage/src/state/index.html +0 -221
- package/coverage/src/state/index.ts.html +0 -322
- package/coverage/src/state/job-metadata.ts.html +0 -1420
- package/coverage/src/state/job-output.ts.html +0 -1033
- package/coverage/src/state/schemas/fleet-state.ts.html +0 -445
- package/coverage/src/state/schemas/index.html +0 -176
- package/coverage/src/state/schemas/index.ts.html +0 -286
- package/coverage/src/state/schemas/job-metadata.ts.html +0 -628
- package/coverage/src/state/schemas/job-output.ts.html +0 -616
- package/coverage/src/state/schemas/session-info.ts.html +0 -361
- package/coverage/src/state/session.ts.html +0 -844
- package/coverage/src/state/types.ts.html +0 -262
- package/coverage/src/state/utils/atomic.ts.html +0 -748
- package/coverage/src/state/utils/index.html +0 -146
- package/coverage/src/state/utils/index.ts.html +0 -103
- package/coverage/src/state/utils/reads.ts.html +0 -1621
- package/coverage/src/work-sources/adapters/github.ts.html +0 -3583
- package/coverage/src/work-sources/adapters/index.html +0 -131
- package/coverage/src/work-sources/adapters/index.ts.html +0 -277
- package/coverage/src/work-sources/errors.ts.html +0 -298
- package/coverage/src/work-sources/index.html +0 -176
- package/coverage/src/work-sources/index.ts.html +0 -529
- package/coverage/src/work-sources/manager.ts.html +0 -1324
- package/coverage/src/work-sources/registry.ts.html +0 -619
- package/coverage/src/work-sources/types.ts.html +0 -568
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts +0 -7
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts.map +0 -1
- package/dist/fleet-manager/__tests__/event-helpers.test.js +0 -368
- package/dist/fleet-manager/__tests__/event-helpers.test.js.map +0 -1
- package/src/config/__tests__/agent.test.ts +0 -864
- package/src/config/__tests__/interpolate.test.ts +0 -644
- package/src/config/__tests__/loader.test.ts +0 -784
- package/src/config/__tests__/merge.test.ts +0 -751
- package/src/config/__tests__/parser.test.ts +0 -533
- package/src/config/__tests__/schema.test.ts +0 -873
- package/src/config/index.ts +0 -119
- package/src/config/interpolate.ts +0 -189
- package/src/config/loader.ts +0 -472
- package/src/config/merge.ts +0 -246
- package/src/config/parser.ts +0 -376
- package/src/config/schema.ts +0 -346
- package/src/fleet-manager/__tests__/coverage.test.ts +0 -2869
- package/src/fleet-manager/__tests__/errors.test.ts +0 -660
- package/src/fleet-manager/__tests__/event-helpers.test.ts +0 -448
- package/src/fleet-manager/__tests__/integration.test.ts +0 -1209
- package/src/fleet-manager/__tests__/job-control.test.ts +0 -283
- package/src/fleet-manager/__tests__/job-manager.test.ts +0 -869
- package/src/fleet-manager/__tests__/job-queue.test.ts +0 -401
- package/src/fleet-manager/__tests__/reload.test.ts +0 -751
- package/src/fleet-manager/__tests__/status-queries.test.ts +0 -595
- package/src/fleet-manager/__tests__/trigger.test.ts +0 -601
- package/src/fleet-manager/errors.ts +0 -747
- package/src/fleet-manager/event-types.ts +0 -378
- package/src/fleet-manager/fleet-manager.ts +0 -2315
- package/src/fleet-manager/index.ts +0 -128
- package/src/fleet-manager/job-manager.ts +0 -663
- package/src/fleet-manager/job-queue.ts +0 -798
- package/src/fleet-manager/types.ts +0 -839
- package/src/index.ts +0 -32
- package/src/runner/__tests__/errors.test.ts +0 -382
- package/src/runner/__tests__/job-executor.test.ts +0 -1708
- package/src/runner/__tests__/message-processor.test.ts +0 -960
- package/src/runner/__tests__/sdk-adapter.test.ts +0 -626
- package/src/runner/errors.ts +0 -307
- package/src/runner/index.ts +0 -57
- package/src/runner/job-executor.ts +0 -448
- package/src/runner/message-processor.ts +0 -355
- package/src/runner/sdk-adapter.ts +0 -191
- package/src/runner/types.ts +0 -158
- package/src/scheduler/__tests__/errors.test.ts +0 -159
- package/src/scheduler/__tests__/interval.test.ts +0 -515
- package/src/scheduler/__tests__/schedule-runner.test.ts +0 -798
- package/src/scheduler/__tests__/schedule-state.test.ts +0 -671
- package/src/scheduler/__tests__/scheduler.test.ts +0 -1280
- package/src/scheduler/errors.ts +0 -101
- package/src/scheduler/index.ts +0 -53
- package/src/scheduler/interval.ts +0 -189
- package/src/scheduler/schedule-runner.ts +0 -442
- package/src/scheduler/schedule-state.ts +0 -211
- package/src/scheduler/scheduler.ts +0 -570
- package/src/scheduler/types.ts +0 -216
- package/src/state/__tests__/directory.test.ts +0 -595
- package/src/state/__tests__/fleet-state.test.ts +0 -868
- package/src/state/__tests__/job-metadata-schema.test.ts +0 -414
- package/src/state/__tests__/job-metadata.test.ts +0 -831
- package/src/state/__tests__/job-output.test.ts +0 -856
- package/src/state/__tests__/session-schema.test.ts +0 -378
- package/src/state/__tests__/session.test.ts +0 -604
- package/src/state/directory.ts +0 -217
- package/src/state/errors.ts +0 -97
- package/src/state/fleet-state.ts +0 -284
- package/src/state/index.ts +0 -79
- package/src/state/job-metadata.ts +0 -445
- package/src/state/job-output.ts +0 -316
- package/src/state/schemas/__tests__/job-output.test.ts +0 -338
- package/src/state/schemas/fleet-state.ts +0 -120
- package/src/state/schemas/index.ts +0 -67
- package/src/state/schemas/job-metadata.ts +0 -181
- package/src/state/schemas/job-output.ts +0 -177
- package/src/state/schemas/session-info.ts +0 -92
- package/src/state/session.ts +0 -253
- package/src/state/types.ts +0 -59
- package/src/state/utils/__tests__/atomic.test.ts +0 -723
- package/src/state/utils/__tests__/reads.test.ts +0 -1071
- package/src/state/utils/atomic.ts +0 -221
- package/src/state/utils/index.ts +0 -6
- package/src/state/utils/reads.ts +0 -512
- package/src/work-sources/__tests__/github.test.ts +0 -1800
- package/src/work-sources/__tests__/manager.test.ts +0 -529
- package/src/work-sources/__tests__/registry.test.ts +0 -477
- package/src/work-sources/__tests__/types.test.ts +0 -479
- package/src/work-sources/adapters/github.ts +0 -1166
- package/src/work-sources/adapters/index.ts +0 -64
- package/src/work-sources/errors.ts +0 -71
- package/src/work-sources/index.ts +0 -148
- package/src/work-sources/manager.ts +0 -413
- package/src/work-sources/registry.ts +0 -178
- package/src/work-sources/types.ts +0 -161
- package/tsconfig.json +0 -9
- package/vitest.config.ts +0 -19
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Atomic file write utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides atomic write operations to prevent file corruption during writes.
|
|
5
|
-
* Uses the standard pattern of writing to a temp file then renaming.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { writeFile, rename, unlink, appendFile } from "node:fs/promises";
|
|
9
|
-
import { dirname, basename, join } from "node:path";
|
|
10
|
-
import { randomBytes } from "node:crypto";
|
|
11
|
-
import { stringify as stringifyYaml } from "yaml";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Error thrown when an atomic write operation fails
|
|
15
|
-
*/
|
|
16
|
-
export class AtomicWriteError extends Error {
|
|
17
|
-
public readonly path: string;
|
|
18
|
-
public readonly tempPath?: string;
|
|
19
|
-
|
|
20
|
-
constructor(message: string, path: string, tempPath?: string, cause?: Error) {
|
|
21
|
-
super(message);
|
|
22
|
-
this.name = "AtomicWriteError";
|
|
23
|
-
this.path = path;
|
|
24
|
-
this.tempPath = tempPath;
|
|
25
|
-
this.cause = cause;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Generate a temp file path in the same directory as the target.
|
|
31
|
-
* Uses pattern: .<filename>.tmp.<random>
|
|
32
|
-
*
|
|
33
|
-
* Writing to the same directory ensures the temp file is on the same
|
|
34
|
-
* filesystem, which is required for atomic rename.
|
|
35
|
-
*/
|
|
36
|
-
export function generateTempPath(targetPath: string): string {
|
|
37
|
-
const dir = dirname(targetPath);
|
|
38
|
-
const filename = basename(targetPath);
|
|
39
|
-
const random = randomBytes(8).toString("hex");
|
|
40
|
-
return join(dir, `.${filename}.tmp.${random}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Options for rename with retry
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
export interface RenameRetryOptions {
|
|
48
|
-
maxRetries?: number;
|
|
49
|
-
baseDelayMs?: number;
|
|
50
|
-
/** Injectable rename function for testing */
|
|
51
|
-
renameFn?: (oldPath: string, newPath: string) => Promise<void>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Rename with retry logic for Windows compatibility.
|
|
56
|
-
*
|
|
57
|
-
* On Windows, rename can fail with EACCES or EPERM if another process
|
|
58
|
-
* has the file open. We retry a few times with backoff to handle this.
|
|
59
|
-
*
|
|
60
|
-
* @internal Exported for testing purposes
|
|
61
|
-
*/
|
|
62
|
-
export async function renameWithRetry(
|
|
63
|
-
oldPath: string,
|
|
64
|
-
newPath: string,
|
|
65
|
-
options: RenameRetryOptions = {}
|
|
66
|
-
): Promise<void> {
|
|
67
|
-
const {
|
|
68
|
-
maxRetries = 3,
|
|
69
|
-
baseDelayMs = 50,
|
|
70
|
-
renameFn = rename,
|
|
71
|
-
} = options;
|
|
72
|
-
|
|
73
|
-
let lastError: Error | undefined;
|
|
74
|
-
|
|
75
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
76
|
-
try {
|
|
77
|
-
await renameFn(oldPath, newPath);
|
|
78
|
-
return;
|
|
79
|
-
} catch (error) {
|
|
80
|
-
lastError = error as Error;
|
|
81
|
-
const code = (error as NodeJS.ErrnoException).code;
|
|
82
|
-
|
|
83
|
-
// Only retry on Windows-specific errors
|
|
84
|
-
if (code !== "EACCES" && code !== "EPERM") {
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Don't delay on the last attempt
|
|
89
|
-
if (attempt < maxRetries) {
|
|
90
|
-
const delay = baseDelayMs * Math.pow(2, attempt);
|
|
91
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
throw lastError;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Safely clean up a temp file, ignoring errors if the file doesn't exist.
|
|
101
|
-
*/
|
|
102
|
-
async function cleanupTempFile(tempPath: string): Promise<void> {
|
|
103
|
-
try {
|
|
104
|
-
await unlink(tempPath);
|
|
105
|
-
} catch (error) {
|
|
106
|
-
// Ignore ENOENT - file may not exist if write failed before creating it
|
|
107
|
-
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
108
|
-
// Log but don't throw - cleanup is best-effort
|
|
109
|
-
// In production, we might want to log this
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Write content to a file atomically.
|
|
116
|
-
*
|
|
117
|
-
* Uses the pattern:
|
|
118
|
-
* 1. Write to temp file in same directory (.<filename>.tmp.<random>)
|
|
119
|
-
* 2. Rename temp file to target (atomic on POSIX)
|
|
120
|
-
* 3. Clean up temp file on failure
|
|
121
|
-
*
|
|
122
|
-
* On Windows, uses retry logic for the rename operation for best-effort
|
|
123
|
-
* atomicity.
|
|
124
|
-
*
|
|
125
|
-
* @param filePath - Target file path
|
|
126
|
-
* @param content - Content to write
|
|
127
|
-
* @param encoding - File encoding (default: utf-8)
|
|
128
|
-
*/
|
|
129
|
-
export async function atomicWriteFile(
|
|
130
|
-
filePath: string,
|
|
131
|
-
content: string,
|
|
132
|
-
encoding: BufferEncoding = "utf-8"
|
|
133
|
-
): Promise<void> {
|
|
134
|
-
const tempPath = generateTempPath(filePath);
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
// Step 1: Write to temp file
|
|
138
|
-
await writeFile(tempPath, content, encoding);
|
|
139
|
-
|
|
140
|
-
// Step 2: Atomically rename to target
|
|
141
|
-
await renameWithRetry(tempPath, filePath);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
// Step 3: Clean up temp file on failure
|
|
144
|
-
await cleanupTempFile(tempPath);
|
|
145
|
-
|
|
146
|
-
throw new AtomicWriteError(
|
|
147
|
-
`Failed to atomically write to ${filePath}: ${(error as Error).message}`,
|
|
148
|
-
filePath,
|
|
149
|
-
tempPath,
|
|
150
|
-
error as Error
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Write a JavaScript object to a YAML file atomically.
|
|
157
|
-
*
|
|
158
|
-
* @param filePath - Target file path
|
|
159
|
-
* @param data - Data to serialize as YAML
|
|
160
|
-
* @param options - YAML stringify options
|
|
161
|
-
*/
|
|
162
|
-
export async function atomicWriteYaml(
|
|
163
|
-
filePath: string,
|
|
164
|
-
data: unknown,
|
|
165
|
-
options?: {
|
|
166
|
-
indent?: number;
|
|
167
|
-
lineWidth?: number;
|
|
168
|
-
}
|
|
169
|
-
): Promise<void> {
|
|
170
|
-
const yamlContent = stringifyYaml(data, {
|
|
171
|
-
indent: options?.indent ?? 2,
|
|
172
|
-
lineWidth: options?.lineWidth ?? 120,
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
await atomicWriteFile(filePath, yamlContent);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Write a JavaScript object to a JSON file atomically.
|
|
180
|
-
*
|
|
181
|
-
* @param filePath - Target file path
|
|
182
|
-
* @param data - Data to serialize as JSON
|
|
183
|
-
* @param options - JSON stringify options
|
|
184
|
-
*/
|
|
185
|
-
export async function atomicWriteJson(
|
|
186
|
-
filePath: string,
|
|
187
|
-
data: unknown,
|
|
188
|
-
options?: {
|
|
189
|
-
indent?: number;
|
|
190
|
-
}
|
|
191
|
-
): Promise<void> {
|
|
192
|
-
const jsonContent = JSON.stringify(data, null, options?.indent ?? 2) + "\n";
|
|
193
|
-
await atomicWriteFile(filePath, jsonContent);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Append a line to a JSONL file.
|
|
198
|
-
*
|
|
199
|
-
* Uses fs.appendFile which is atomic at the message level on most systems.
|
|
200
|
-
* Each call appends a single JSON object followed by a newline.
|
|
201
|
-
*
|
|
202
|
-
* @param filePath - Target JSONL file path
|
|
203
|
-
* @param data - Data to serialize as a single JSON line
|
|
204
|
-
*/
|
|
205
|
-
export async function appendJsonl(
|
|
206
|
-
filePath: string,
|
|
207
|
-
data: unknown
|
|
208
|
-
): Promise<void> {
|
|
209
|
-
const line = JSON.stringify(data) + "\n";
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
await appendFile(filePath, line, "utf-8");
|
|
213
|
-
} catch (error) {
|
|
214
|
-
throw new AtomicWriteError(
|
|
215
|
-
`Failed to append to JSONL file ${filePath}: ${(error as Error).message}`,
|
|
216
|
-
filePath,
|
|
217
|
-
undefined,
|
|
218
|
-
error as Error
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|