1
1
import { goSync } from '@api3/promise-utils' ;
2
- import template from 'lodash/template' ;
3
- import reduce from 'lodash/reduce' ;
2
+ import { interpolateSecretsIntoConfig } from '@api3/commons' ;
4
3
import { z } from 'zod' ;
5
4
import { Config , configSchema } from '../config' ;
6
5
import { Receipt , receiptSchema } from '../receipt' ;
@@ -18,7 +17,9 @@ export function parseConfigWithSecrets(config: unknown, secrets: unknown): Valid
18
17
const parsedSecrets = parseSecrets ( secrets ) ;
19
18
if ( ! parsedSecrets . success ) return parsedSecrets ;
20
19
21
- const interpolateConfigRes = interpolateSecrets ( config , parsedSecrets . data ) ;
20
+ const interpolateConfigRes = goSync ( ( ) =>
21
+ interpolateSecretsIntoConfig ( config , parsedSecrets . data , { allowBlankSecretValue : false , validateSecretName : true } )
22
+ ) ;
22
23
if ( ! interpolateConfigRes . success ) {
23
24
return {
24
25
success : false ,
@@ -59,56 +60,16 @@ export function parseReceipt(receipt: unknown): ValidationResult<Receipt> {
59
60
return receiptSchema . safeParse ( receipt ) ;
60
61
}
61
62
62
- // Regular expression that does not match anything, ensuring no escaping or interpolation happens
63
- // https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L199
64
- const NO_MATCH_REGEXP = / ( $ ^ ) / ;
65
- // Regular expression matching ES template literal delimiter (${}) with escaping
66
- // https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L175
67
- const ES_MATCH_REGEXP = / (?< ! \\ ) \$ \{ ( [ ^ \\ } ] * (?: \\ .[ ^ \\ } ] * ) * ) \} / g;
68
- // Regular expression matching the escaped ES template literal delimiter (${}). We need to use "\\\\" (four backslashes)
69
- // because "\\" becomes "\\\\" when converted to string
70
- const ESCAPED_ES_MATCH_REGEXP = / \\ \\ ( \$ \{ ( [ ^ \\ } ] * (?: \\ .[ ^ \\ } ] * ) * ) \} ) / g;
71
-
72
- function interpolateSecrets ( config : unknown , secrets : Secrets ) : ValidationResult < unknown > {
73
- const stringifiedSecrets = reduce (
74
- secrets ,
75
- ( acc , value , key ) => {
76
- return {
77
- ...acc ,
78
- // Convert to value to JSON to encode new lines as "\n". The resulting value will be a JSON string with quotes
79
- // which are sliced off.
80
- [ key ] : JSON . stringify ( value ) . slice ( 1 , - 1 ) ,
81
- } ;
82
- } ,
83
- { } as Secrets
84
- ) ;
85
-
86
- const interpolationRes = goSync ( ( ) =>
87
- JSON . parse (
88
- template ( JSON . stringify ( config ) , {
89
- escape : NO_MATCH_REGEXP ,
90
- evaluate : NO_MATCH_REGEXP ,
91
- interpolate : ES_MATCH_REGEXP ,
92
- } ) ( stringifiedSecrets )
93
- )
94
- ) ;
95
-
96
- if ( ! interpolationRes . success ) return interpolationRes ;
97
-
98
- const interpolatedConfig = JSON . stringify ( interpolationRes . data ) ;
99
- // Un-escape the escaped config interpolations (e.g. to enable interpolation in processing snippets)
100
- return goSync ( ( ) => JSON . parse ( interpolatedConfig . replace ( ESCAPED_ES_MATCH_REGEXP , '$1' ) ) ) ;
101
- }
102
-
103
63
/**
104
64
* Used to interpolate secrets into config. This function only interpolates the secrets and does not perform any
105
65
* validation. Only use this function when you are sure the interpolation result is a valid Airnode config.
106
66
*
107
67
* In case there is an error when interpolating secrets the function throws an error.
108
68
*/
109
69
export function unsafeParseConfigWithSecrets ( config : unknown , secrets : Secrets ) : Config {
110
- const interpolationResult = interpolateSecrets ( config , secrets ) ;
111
- if ( ! interpolationResult . success ) throw interpolationResult . error ;
112
-
113
- return interpolationResult . data as Config ;
70
+ // System and docker secrets passed via process.env do not necessarily obey the expected secret name pattern
71
+ return interpolateSecretsIntoConfig ( config , secrets , {
72
+ allowBlankSecretValue : true ,
73
+ validateSecretName : false ,
74
+ } ) as Config ;
114
75
}
0 commit comments