@gajae-code/utils 0.13.1 → 0.13.3

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.
@@ -48,7 +48,7 @@ export declare function cleanup(): Promise<void>;
48
48
  /**
49
49
  * Runs all cleanup callbacks and exits.
50
50
  *
51
- * In main thread: waits for stdout drain, then calls process.exit().
51
+ * In main thread: waits for stdout and stderr drain, then calls process.exit().
52
52
  * In workers: runs cleanup only (process.exit would kill entire process).
53
53
  */
54
54
  export declare function quit(code?: number): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/utils",
4
- "version": "0.13.1",
4
+ "version": "0.13.3",
5
5
  "description": "Shared utilities for pi packages",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo",
@@ -31,7 +31,7 @@
31
31
  "fmt": "biome format --write ."
32
32
  },
33
33
  "dependencies": {
34
- "@gajae-code/natives": "0.13.1",
34
+ "@gajae-code/natives": "0.13.3",
35
35
  "beautiful-mermaid": "^1.1.3",
36
36
  "handlebars": "^4.7.9",
37
37
  "winston": "^3.19.0",
package/src/postmortem.ts CHANGED
@@ -654,10 +654,54 @@ export function cleanup(): Promise<void> {
654
654
  return runCleanup(Reason.MANUAL);
655
655
  }
656
656
 
657
+ interface ProcessOutputDrain {
658
+ promise: Promise<void>;
659
+ cancel: () => void;
660
+ }
661
+
662
+ function waitForProcessOutput(stream: NodeJS.WriteStream): ProcessOutputDrain | undefined {
663
+ if (!stream.writable || stream.destroyed || stream.writableFinished) return undefined;
664
+
665
+ const { promise, resolve } = Promise.withResolvers<void>();
666
+ let settled = false;
667
+ const finish = (): void => {
668
+ if (settled) return;
669
+ settled = true;
670
+ stream.off("close", finish);
671
+ stream.off("error", finish);
672
+ resolve();
673
+ };
674
+
675
+ stream.once("close", finish);
676
+ stream.once("error", finish);
677
+ try {
678
+ stream.end(finish);
679
+ } catch {
680
+ finish();
681
+ }
682
+ return { promise, cancel: finish };
683
+ }
684
+
685
+ async function waitForProcessOutputDrain(): Promise<void> {
686
+ const drains = [waitForProcessOutput(process.stdout), waitForProcessOutput(process.stderr)].filter(
687
+ (drain): drain is ProcessOutputDrain => drain !== undefined,
688
+ );
689
+ if (drains.length === 0) return;
690
+
691
+ const { promise: deadline, resolve: resolveDeadline } = Promise.withResolvers<void>();
692
+ const timer = setTimeout(resolveDeadline, 5_000);
693
+ try {
694
+ await Promise.race([Promise.all(drains.map(drain => drain.promise)), deadline]);
695
+ } finally {
696
+ clearTimeout(timer);
697
+ for (const drain of drains) drain.cancel();
698
+ }
699
+ }
700
+
657
701
  /**
658
702
  * Runs all cleanup callbacks and exits.
659
703
  *
660
- * In main thread: waits for stdout drain, then calls process.exit().
704
+ * In main thread: waits for stdout and stderr drain, then calls process.exit().
661
705
  * In workers: runs cleanup only (process.exit would kill entire process).
662
706
  */
663
707
  export async function quit(code: number = 0): Promise<void> {
@@ -672,11 +716,7 @@ export async function quit(code: number = 0): Promise<void> {
672
716
 
673
717
  const exitAfterCleanup = async (): Promise<void> => {
674
718
  await awaitCleanupWithDeadline(Reason.MANUAL);
675
- if (process.stdout.writableLength > 0) {
676
- const { promise, resolve } = Promise.withResolvers<void>();
677
- process.stdout.once("drain", resolve);
678
- await Promise.race([promise, Bun.sleep(5000)]);
679
- }
719
+ await waitForProcessOutputDrain();
680
720
  process.exit(code);
681
721
  };
682
722