11import * as assert from 'assert' ;
2+ import * as fs from 'fs' ;
23import * as mpath from 'path' ;
3- import * as fs from 'fs-extra' ;
44
55function bufferAsHex ( v : unknown ) : unknown {
66 // You would think that you could use `Buffer.isBuffer(v)` here but you would be mistaken
@@ -21,16 +21,16 @@ export async function readFixture<T>(path: string, defaultValue: T): Promise<T>
2121 path = path . replace ( 'bitcoinTestnet4' , 'bitcoinPublicSignet' ) ;
2222
2323 try {
24- await fs . access ( mpath . dirname ( path ) ) ;
24+ await fs . promises . access ( mpath . dirname ( path ) ) ;
2525 } catch ( e ) {
26- await fs . mkdirp ( mpath . dirname ( path ) ) ;
26+ await fs . promises . mkdir ( mpath . dirname ( path ) , { recursive : true } ) ;
2727 }
2828
2929 try {
30- return JSON . parse ( await fs . readFile ( path , 'utf8' ) ) as T ;
30+ return JSON . parse ( await fs . promises . readFile ( path , 'utf8' ) ) as T ;
3131 } catch ( e ) {
3232 if ( e . code === 'ENOENT' ) {
33- await fs . writeFile ( path , toPrettyJSON ( defaultValue ) ) ;
33+ await fs . promises . writeFile ( path , toPrettyJSON ( defaultValue ) ) ;
3434 throw new Error ( `wrote defaults, please check contents and re-run tests` ) ;
3535 }
3636
@@ -46,3 +46,96 @@ export async function readFixture<T>(path: string, defaultValue: T): Promise<T>
4646export function assertEqualJSON < T > ( a : T , b : T ) : void {
4747 assert . deepStrictEqual ( JSON . parse ( toPrettyJSON ( a ) ) , JSON . parse ( toPrettyJSON ( b ) ) ) ;
4848}
49+
50+ type FixtureEncoding = 'json' | 'hex' | 'txt' ;
51+
52+ function isNodeJsError ( e : unknown ) : e is NodeJS . ErrnoException {
53+ return e instanceof Error && typeof ( e as NodeJS . ErrnoException ) . code === 'string' ;
54+ }
55+
56+ function fixtureEncoding ( path : string ) : FixtureEncoding {
57+ if ( path . endsWith ( '.json' ) ) {
58+ return 'json' ;
59+ }
60+ if ( path . endsWith ( '.hex' ) ) {
61+ return 'hex' ;
62+ }
63+ if ( path . endsWith ( '.txt' ) ) {
64+ return 'txt' ;
65+ }
66+ throw new Error ( `unknown fixture encoding for ${ path } ` ) ;
67+ }
68+
69+ function decodeFixture ( raw : string , encoding : FixtureEncoding ) : unknown {
70+ switch ( encoding ) {
71+ case 'json' :
72+ return JSON . parse ( raw ) ;
73+ case 'hex' :
74+ return Buffer . from ( raw , 'hex' ) ;
75+ case 'txt' :
76+ return raw ;
77+ }
78+ }
79+
80+ function encodeFixture ( value : unknown , encoding : FixtureEncoding ) : string {
81+ switch ( encoding ) {
82+ case 'json' :
83+ return JSON . stringify ( value , null , 2 ) + '\n' ;
84+ case 'hex' :
85+ if ( ! Buffer . isBuffer ( value ) ) {
86+ throw new Error ( `expected Buffer, got ${ typeof value } ` ) ;
87+ }
88+ return value . toString ( 'hex' ) ;
89+ case 'txt' :
90+ if ( typeof value !== 'string' ) {
91+ throw new Error ( `expected string, got ${ typeof value } ` ) ;
92+ }
93+ return value ;
94+ }
95+ }
96+
97+ /**
98+ * Return fixture described in `path`.
99+ *
100+ * If file does not exist and `defaultValue` is provided, writes defaultValue to `path` and throws an error.
101+ *
102+ * @param path
103+ * @param defaultValue
104+ * @return T - fixture content
105+ */
106+ export async function getFixture < T > ( path : string , defaultValue ?: T | ( ( ) => Promise < T > ) ) : Promise < T > {
107+ try {
108+ await fs . promises . stat ( mpath . dirname ( path ) ) ;
109+ } catch ( e ) {
110+ if ( isNodeJsError ( e ) && e . code === 'ENOENT' ) {
111+ throw new Error ( `fixture directory ${ mpath . dirname ( path ) } not found, please create it first` ) ;
112+ }
113+ throw e ;
114+ }
115+
116+ const encoding = fixtureEncoding ( path ) ;
117+
118+ try {
119+ return decodeFixture ( await fs . promises . readFile ( path , 'utf8' ) , encoding ) as T ;
120+ } catch ( e ) {
121+ if ( isNodeJsError ( e ) && e . code === 'ENOENT' ) {
122+ if ( process . env . WRITE_FIXTURES === '0' ) {
123+ throw new Error ( `fixture ${ path } not found, WRITE_FIXTURES=0` ) ;
124+ }
125+ if ( defaultValue === undefined ) {
126+ throw new Error ( `fixture ${ path } not found and no default value given` ) ;
127+ }
128+ if ( typeof defaultValue === 'function' ) {
129+ defaultValue = await ( defaultValue as ( ) => Promise < T > ) ( ) ;
130+ }
131+ await fs . promises . writeFile ( path , encodeFixture ( defaultValue , encoding ) ) ;
132+ throw new Error ( `wrote default value for ${ path } , please inspect and restart test` ) ;
133+ }
134+
135+ throw e ;
136+ }
137+ }
138+
139+ export function jsonNormalize < T > ( v : T ) : T {
140+ return JSON . parse ( JSON . stringify ( v ) ) as T ;
141+ }
0 commit comments