1+
2+ // Helper to convert Buffer/Uint8Array to ArrayBuffer for UniFFI
3+ function toArrayBuffer ( input : ArrayBuffer | Buffer | Uint8Array | undefined ) : ArrayBuffer | undefined {
4+ if ( input === undefined ) return undefined ;
5+ if ( input instanceof ArrayBuffer ) return input ;
6+ // Buffer and Uint8Array have .buffer property, but may be a view with offset
7+ const view = input as Uint8Array ;
8+ return view . buffer . slice ( view . byteOffset , view . byteOffset + view . byteLength ) as ArrayBuffer ;
9+ }
10+
11+ // Helper to deep parse JSON strings
12+ function deepParse ( value : any ) : any {
13+ if ( typeof value === 'string' ) {
14+ try {
15+ return deepParse ( JSON . parse ( value ) ) ;
16+ } catch {
17+ return value ;
18+ }
19+ }
20+
21+ if ( Array . isArray ( value ) ) {
22+ return value . map ( deepParse ) ;
23+ }
24+
25+ if ( value && typeof value === 'object' ) {
26+ const parsed : any = { } ;
27+ for ( const [ key , nested ] of Object . entries ( value ) ) {
28+ parsed [ key ] = deepParse ( nested ) ;
29+ }
30+ return parsed ;
31+ }
32+
33+ return value ;
34+ }
35+
36+ // Helper to stringify policy/factor params/outputs
37+ function stringifyFactorParams ( value : any ) : any {
38+ if ( value === undefined || value === null || typeof value === 'string' ) {
39+ return value ;
40+ }
41+
42+ const POLICY_ORDER = [ '$id' , '$schema' , 'factors' , 'key' , 'memory' , 'salt' , 'threshold' , 'time' ] ;
43+ const FACTOR_ORDER = [ 'id' , 'pad' , 'params' , 'salt' , 'secret' , 'type' , 'hint' ] ;
44+
45+ const stringifyPolicy = ( input : any ) : string => JSON . stringify ( orderValue ( input , 'policy' ) ) ;
46+
47+ function orderValue ( input : any , context ?: 'policy' | 'factor' ) : any {
48+ if ( Array . isArray ( input ) ) {
49+ if ( context === 'policy' ) {
50+ return input . map ( ( item ) => orderValue ( item , 'factor' ) ) ;
51+ }
52+ return input . map ( ( item ) => orderValue ( item ) ) ;
53+ }
54+
55+ if ( input && typeof input === 'object' ) {
56+ const baseOrder = context === 'policy' ? POLICY_ORDER : context === 'factor' ? FACTOR_ORDER : [ ] ;
57+ const extras = Object . keys ( input ) . filter ( ( key ) => ! baseOrder . includes ( key ) ) . sort ( ) ;
58+ const keys = [ ...baseOrder , ...extras ] ;
59+ const ordered : any = { } ;
60+
61+ for ( const key of keys ) {
62+ if ( ! ( key in input ) ) continue ;
63+
64+ if ( context === 'factor' && key === 'params' ) {
65+ ordered . params = input [ key ] ;
66+ continue ;
67+ }
68+
69+ if ( key === 'factors' && Array . isArray ( input [ key ] ) ) {
70+ ordered . factors = input [ key ] . map ( ( item : any ) => orderValue ( item , 'factor' ) ) ;
71+ continue ;
72+ }
73+
74+ ordered [ key ] = orderValue ( input [ key ] ) ;
75+ }
76+
77+ return ordered ;
78+ }
79+
80+ return input ;
81+ }
82+
83+ return stringifyPolicy ( value ) ;
84+ }
85+
86+ export {
87+ toArrayBuffer ,
88+ deepParse ,
89+ stringifyFactorParams ,
90+ } ;
0 commit comments