Skip to content

Commit 737063e

Browse files
Fix parsing secret fields (#69)
1 parent 1dd5cbe commit 737063e

8 files changed

+292
-34
lines changed

etc/plugin-config-ui-lib.api.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function ConfigUIForm({ prepareSubmitValues }: ConfigUIFormProps): JSX_2.
8282
// @public (undocumented)
8383
export interface ConfigUIFormProps {
8484
// (undocumented)
85-
prepareSubmitValues: (values: Record<string, any>, tablesList?: PluginTable[]) => PluginUiMessagePayload['validation_passed']['values'];
85+
prepareSubmitValues: (config: PluginConfig, values: Record<string, any>, tablesList?: PluginTable[]) => PluginUiMessagePayload['validation_passed']['values'];
8686
}
8787

8888
export { Controller }
@@ -91,7 +91,7 @@ export { Controller }
9191
export function convertStringToSlug(value: string): string;
9292

9393
// @public
94-
export function corePrepareSubmitValues(values: any, tablesList?: PluginTable[]): PluginUiMessagePayload['validation_passed']['values'];
94+
export function corePrepareSubmitValues(config: PluginConfig, values: any, tablesList?: PluginTable[]): PluginUiMessagePayload['validation_passed']['values'];
9595

9696
// @public (undocumented)
9797
export interface DestinationConfig extends PluginConfig {
@@ -338,14 +338,19 @@ export interface PluginConfig {
338338
name: string;
339339
// (undocumented)
340340
stateSchema?: Record<string, yup.AnySchema>;
341-
// Warning: (ae-forgotten-export) The symbol "PluginConfigFormStep" needs to be exported by the entry point index.d.ts
342-
//
343341
// (undocumented)
344342
steps: PluginConfigFormStep[];
345343
// (undocumented)
346344
type: 'source' | 'destination';
347345
}
348346

347+
// @public (undocumented)
348+
export type PluginConfigFormStep = {
349+
children: (IterableStepComponent | React_2.FC<any>)[];
350+
title: string;
351+
submitGuard?: (formValues: any) => Promise<boolean>;
352+
};
353+
349354
// @public
350355
export const PluginContextProvider: ({ children, config, teamName, getTablesData, hideStepper, pluginUiMessageHandler, initialValues, }: PluginContextProviderProps) => JSX_2.Element;
351356

@@ -739,6 +744,7 @@ export function writeSecretsToPrepareValues(env?: Record<string, string>): {
739744
// Warnings were encountered during analysis:
740745
//
741746
// src/components/display/setupGuide/section/index.tsx:26:3 - (ae-forgotten-export) The symbol "Section" needs to be exported by the entry point index.d.ts
747+
// src/types.ts:29:3 - (ae-forgotten-export) The symbol "IterableStepComponent" needs to be exported by the entry point index.d.ts
742748

743749
// (No @packageDocumentation comment for this package)
744750

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@cloudquery/plugin-config-ui-lib",
33
"description": "Plugin configuration UI library for CloudQuery Cloud App",
4-
"version": "3.0.7",
4+
"version": "4.0.0",
55
"private": false,
66
"main": "dist/index.cjs.js",
77
"module": "dist/index.esm.js",

src/components/form/configUIForm.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { parseTestConnectionError } from '../../utils/parseTestConnectionError';
2626
import { FormFooter, FormWrapper, GuideComponent } from '../display';
2727
import { PluginTable } from '../inputs';
2828
import { Sections } from './sections/sections';
29+
import { PluginConfig } from '../../types';
2930

3031
const FormStepper = React.lazy(() =>
3132
import('../display/formStepper').then((module) => ({
@@ -38,6 +39,7 @@ const FormStepper = React.lazy(() =>
3839
*/
3940
export interface ConfigUIFormProps {
4041
prepareSubmitValues: (
42+
config: PluginConfig,
4143
values: Record<string, any>,
4244
tablesList?: PluginTable[],
4345
) => PluginUiMessagePayload['validation_passed']['values'];
@@ -61,8 +63,8 @@ export function ConfigUIForm({ prepareSubmitValues }: ConfigUIFormProps) {
6163
const editMode = watch('_editMode');
6264

6365
const getCurrentValues = useCallback(
64-
() => prepareSubmitValues(form.getValues(), tablesList),
65-
[form, tablesList, prepareSubmitValues],
66+
() => prepareSubmitValues(config, form.getValues(), tablesList),
67+
[config, form, tablesList, prepareSubmitValues],
6668
);
6769

6870
useFormCurrentValues(pluginUiMessageHandler, getCurrentValues);

src/types.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ export interface GuideConfig {
2222
sections: RenderGuideProps['sections'];
2323
}
2424

25-
type PluginConfigFormStep = {
25+
/**
26+
* @public
27+
*/
28+
export type PluginConfigFormStep = {
2629
children: (IterableStepComponent | React.FC<any>)[];
2730
title: string;
2831
submitGuard?: (formValues: any) => Promise<boolean>;

src/utils/corePrepareSubmitValues.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { PluginUiMessagePayload } from '@cloudquery/plugin-config-ui-connector';
33
import { prepareOAuthValue } from './prepareOAuthValue';
44
import { prepareSecretValues } from './prepareSecretValues';
55
import { PluginTable } from '../components';
6+
import { PluginConfig } from '../types';
67

78
/**
89
* Prepare values for submit
910
*
1011
* @public
1112
*/
1213
export function corePrepareSubmitValues(
14+
config: PluginConfig,
1315
values: any,
1416
tablesList?: PluginTable[],
1517
): PluginUiMessagePayload['validation_passed']['values'] {
@@ -20,7 +22,7 @@ export function corePrepareSubmitValues(
2022
spec: {} as Record<string, any>,
2123
};
2224

23-
const secrets = prepareSecretValues(values);
25+
const secrets = prepareSecretValues(config.steps, values);
2426
const oauthValue = prepareOAuthValue(values);
2527

2628
return {

src/utils/prepareSecretValues.ts

+65-16
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
import { escapeSingleQuotesAndBackslashes } from './escapeSingleQuotesAndBackslashes';
22
import { isOrHasSecret } from './secretValueHandling';
3-
import { AuthType } from '../types';
3+
import { IterableStepComponent } from '../components/form/renderer/types';
4+
import { PluginConfigFormStep } from '../types';
45

56
/**
67
* Prepare secret values for the deployment
7-
* ONLY valid if the form is using the "OTHER" auth type
88
*/
9-
export function prepareSecretValues(values: Record<string, any>): {
9+
export function prepareSecretValues(
10+
configSteps: PluginConfigFormStep[],
11+
values: Record<string, any>,
12+
): {
1013
envs: { name: string; value: string }[];
11-
spec: Record<string, string>;
14+
spec: Record<string, string | undefined>;
1215
} {
1316
const envs: { name: string; value: string }[] = [];
14-
const spec: Record<string, string> = {};
15-
16-
if (values._authType === AuthType.OTHER) {
17-
for (const name of values._secretKeys ?? []) {
18-
const value = values[name];
19-
if (value !== undefined) {
20-
envs.push({
21-
name,
22-
value: isOrHasSecret(value) ? '' : value,
23-
});
24-
spec[name] = `\${${escapeSingleQuotesAndBackslashes(name)}}`;
25-
}
17+
const spec: Record<string, string | undefined> = {};
18+
19+
for (const name of values._secretKeys ?? []) {
20+
const shouldRenderFns = findShouldRenderFunctions(configSteps, name);
21+
const allVisible = shouldRenderFns.every((fn) => fn(values));
22+
const value = values[name];
23+
if (allVisible && value !== undefined) {
24+
envs.push({
25+
name,
26+
value: isOrHasSecret(value) ? '' : value,
27+
});
28+
spec[name] = `\${${escapeSingleQuotesAndBackslashes(name)}}`;
29+
} else {
30+
spec[name] = undefined;
2631
}
2732
}
2833

@@ -31,3 +36,47 @@ export function prepareSecretValues(values: Record<string, any>): {
3136
spec,
3237
};
3338
}
39+
40+
/**
41+
* Find all the shouldRender functions for a given field name
42+
*/
43+
export function findShouldRenderFunctions(
44+
configSteps: PluginConfigFormStep[],
45+
fieldName: string,
46+
): Array<(formValues: any) => boolean> {
47+
const shouldRenderFunctions: Array<(formValues: any) => boolean> = [];
48+
49+
function traverse(item: IterableStepComponent): any {
50+
if (typeof item.shouldRender === 'function') {
51+
shouldRenderFunctions.push(item.shouldRender);
52+
}
53+
54+
if ('name' in item && item.name === fieldName) {
55+
return true;
56+
}
57+
58+
if ('children' in item && Array.isArray(item.children)) {
59+
for (const child of item.children) {
60+
if (typeof child !== 'function' && traverse(child)) {
61+
return true;
62+
}
63+
}
64+
}
65+
66+
if (typeof item.shouldRender === 'function') {
67+
shouldRenderFunctions.pop();
68+
}
69+
70+
return false;
71+
}
72+
73+
for (const step of configSteps) {
74+
for (const child of step.children) {
75+
if (typeof child !== 'function' && traverse(child)) {
76+
break;
77+
}
78+
}
79+
}
80+
81+
return shouldRenderFunctions;
82+
}

0 commit comments

Comments
 (0)