@goodfoot/claude-code-hooks 1.0.4 → 1.0.6
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/cli.js +54 -58
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import * as crypto from 'node:crypto';
|
|
18
18
|
import * as fs from 'node:fs';
|
|
19
|
+
import * as os from 'node:os';
|
|
19
20
|
import * as path from 'node:path';
|
|
20
21
|
import * as esbuild from 'esbuild';
|
|
21
22
|
import { glob } from 'glob';
|
|
@@ -374,74 +375,69 @@ async function discoverHookFiles(pattern, cwd) {
|
|
|
374
375
|
* @returns Compiled output content as a string
|
|
375
376
|
*/
|
|
376
377
|
async function compileHook(options) {
|
|
377
|
-
const { sourcePath,
|
|
378
|
+
const { sourcePath, logFilePath } = options;
|
|
378
379
|
// Create a temporary wrapper file that imports the hook and executes it
|
|
379
|
-
|
|
380
|
+
// Use system temp directory with deterministic name based on all inputs that affect output
|
|
381
|
+
// This ensures the same inputs always produce the same temp path, making builds deterministic
|
|
382
|
+
const hashInputs = [sourcePath, logFilePath ?? ''].join(':');
|
|
383
|
+
const buildHash = crypto.createHash('sha256').update(hashInputs).digest('hex').substring(0, 16);
|
|
384
|
+
const tempDir = path.join(os.tmpdir(), 'claude-code-hooks-build', buildHash);
|
|
380
385
|
const wrapperPath = path.join(tempDir, 'wrapper.ts');
|
|
381
386
|
const tempOutput = path.join(tempDir, 'output.mjs');
|
|
382
387
|
// Get the path to the runtime module (relative to this CLI)
|
|
383
388
|
const runtimePath = path.resolve(path.dirname(new URL(import.meta.url).pathname), './runtime.js');
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const wrapperContent = `${logFileInjection}
|
|
389
|
+
// Ensure temp directory exists (don't delete - concurrent builds may be using it)
|
|
390
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
391
|
+
// Build log file injection code if specified
|
|
392
|
+
const logFileInjection =
|
|
393
|
+
logFilePath !== undefined
|
|
394
|
+
? `process.env['CLAUDE_CODE_HOOKS_CLI_LOG_FILE'] = ${JSON.stringify(logFilePath)};\n`
|
|
395
|
+
: '';
|
|
396
|
+
// Create wrapper that imports the hook and calls execute
|
|
397
|
+
const wrapperContent = `${logFileInjection}
|
|
394
398
|
import hook from '${sourcePath.replace(/\\/g, '/')}';
|
|
395
399
|
import { execute } from '${runtimePath.replace(/\\/g, '/')}';
|
|
396
400
|
|
|
397
401
|
execute(hook);
|
|
398
402
|
`;
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return content;
|
|
438
|
-
} catch (error) {
|
|
439
|
-
// Clean up temp directory on error
|
|
440
|
-
if (fs.existsSync(tempDir)) {
|
|
441
|
-
fs.rmSync(tempDir, { recursive: true });
|
|
442
|
-
}
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
403
|
+
fs.writeFileSync(wrapperPath, wrapperContent, 'utf-8');
|
|
404
|
+
await esbuild.build({
|
|
405
|
+
entryPoints: [wrapperPath],
|
|
406
|
+
outfile: tempOutput,
|
|
407
|
+
format: 'esm',
|
|
408
|
+
platform: 'node',
|
|
409
|
+
target: 'node20',
|
|
410
|
+
bundle: true,
|
|
411
|
+
sourcemap: 'inline',
|
|
412
|
+
minify: false,
|
|
413
|
+
// Keep node built-ins external
|
|
414
|
+
external: [
|
|
415
|
+
'node:*',
|
|
416
|
+
'http',
|
|
417
|
+
'https',
|
|
418
|
+
'url',
|
|
419
|
+
'stream',
|
|
420
|
+
'zlib',
|
|
421
|
+
'events',
|
|
422
|
+
'buffer',
|
|
423
|
+
'util',
|
|
424
|
+
'path',
|
|
425
|
+
'fs',
|
|
426
|
+
'os',
|
|
427
|
+
'crypto',
|
|
428
|
+
'child_process',
|
|
429
|
+
'perf_hooks',
|
|
430
|
+
'async_hooks',
|
|
431
|
+
'diagnostics_channel'
|
|
432
|
+
],
|
|
433
|
+
// Ensure we get clean ESM output
|
|
434
|
+
mainFields: ['module', 'main'],
|
|
435
|
+
conditions: ['import', 'node']
|
|
436
|
+
});
|
|
437
|
+
// Read and return the compiled content
|
|
438
|
+
// Don't delete temp directory - allows concurrent builds of same source
|
|
439
|
+
// and the OS will clean up /tmp periodically
|
|
440
|
+
return fs.readFileSync(tempOutput, 'utf-8');
|
|
445
441
|
}
|
|
446
442
|
/**
|
|
447
443
|
* Generates a content hash (SHA-256, 8-char prefix) for a compiled hook.
|