-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprocessBlocks.ts
105 lines (87 loc) · 3.2 KB
/
processBlocks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { $ } from 'bun';
import type { Block } from './Block';
import fs from 'fs';
import processStdoutBlock from './processStdoutBlock';
import processStderrBlock from './processStderrBlock';
import processJavaScriptBlock from './processJavaScriptBlock';
import processTypeScriptBlock from './processTypeScriptBlock';
import processShellBlock from './processShellBlock';
const HANDLERS_WITHOUT_META = {
txt: processStdoutBlock,
stdout: processStdoutBlock,
stderr: processStderrBlock,
js: processJavaScriptBlock,
javascript: processJavaScriptBlock,
ts: processTypeScriptBlock,
typescript: processTypeScriptBlock,
sh: processShellBlock,
};
const HANDLERS_WITH_META = {};
export default async function processBlocks(blocks: Block[]) {
for (const block of blocks) {
if (!block.tag) {
if (!block.path) {
continue;
}
block.tag = 'txt';
}
const tag = block.tag.toLowerCase();
const handlerWithMeta = HANDLERS_WITH_META[tag];
const handlerWithoutMeta = HANDLERS_WITHOUT_META[tag];
if (handlerWithMeta && handlerWithoutMeta) {
throw new Error(`Duplicate handlers for the ${tag} language tag`);
}
if (!handlerWithMeta && !handlerWithoutMeta && block.tag !== 'diff' && block.tag !== 'patch') {
continue;
}
// Bypass the handlers if the block mode is 'match' and just check the text
if (block.path && block.mode === 'match') {
const file = Bun.file(block.path);
const text = await file.text();
if (block.code !== text) {
console.error(`'${block.path} does not match the expected content`);
}
continue;
}
// Bypass the handlers if the block mode is `diff` or `patch` and apply it
if (block.tag === 'diff' || block.tag === 'patch') {
if (!(await Bun.file(block.meta).exists())) {
console.error(`'${block.meta}' does not exist to patch changes to`);
}
const { stdout: stdoutBuffer, stderr: stderrBuffer } = await $`echo ${block.code} | patch ${block.meta}`.quiet();
const stdout = stdoutBuffer.toString();
const stderr = stderrBuffer.toString();
if (stdout !== `patching file ${block.meta}\n`) {
console.error(stdout);
}
if (stderr) {
console.error(stderr);
}
continue;
}
try {
// See /~https://github.com/oven-sh/bun/issues/14874 for a better option
const originalConsoleLog = console.log;
const originalConsoleError = console.error;
if (block.path) {
const file = fs.createWriteStream(block.path, { flags: block.mode === 'append' ? 'a' : undefined });
console.log = (...args: any[]) => file.write(args.join(' ') + '\n');
console.error = (...args: any[]) => file.write(args.join(' ') + '\n');
}
if (handlerWithMeta) {
await handlerWithMeta(block.meta, block.code);
}
else {
if (block.meta) {
console.error(`'${tag}' language tag handler does not support block meta`);
}
await handlerWithoutMeta(block.code);
}
console.log = originalConsoleLog;
console.error = originalConsoleError;
}
catch (error) {
throw new Error(`Error processing ${tag} block: ${error.message}`);
}
}
}