@aws-amplify/amplify-util-uibuilder 1.5.0-studio-forms.0 → 1.6.0-beta.0
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.
- package/CHANGELOG.md +44 -2
- package/lib/clients/amplify-studio-client.d.ts +2 -2
- package/lib/clients/amplify-studio-client.d.ts.map +1 -1
- package/lib/clients/amplify-studio-client.js +30 -30
- package/lib/clients/amplify-studio-client.js.map +1 -1
- package/lib/commands/generateComponents.d.ts.map +1 -1
- package/lib/commands/generateComponents.js +2 -5
- package/lib/commands/generateComponents.js.map +1 -1
- package/lib/commands/utils/codegenResources.d.ts +2 -1
- package/lib/commands/utils/codegenResources.d.ts.map +1 -1
- package/lib/commands/utils/codegenResources.js +3 -3
- package/lib/commands/utils/codegenResources.js.map +1 -1
- package/lib/commands/utils/featureFlags.d.ts +1 -2
- package/lib/commands/utils/featureFlags.d.ts.map +1 -1
- package/lib/commands/utils/featureFlags.js +5 -4
- package/lib/commands/utils/featureFlags.js.map +1 -1
- package/lib/commands/utils/shouldRenderComponents.d.ts +1 -1
- package/lib/commands/utils/shouldRenderComponents.d.ts.map +1 -1
- package/lib/commands/utils/shouldRenderComponents.js +14 -8
- package/lib/commands/utils/shouldRenderComponents.js.map +1 -1
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.d.ts.map +1 -1
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.js +15 -0
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/cloneComponentsFromEnv.test.ts +11 -11
- package/src/__tests__/createUiBuilderComponent.test.ts +7 -2
- package/src/__tests__/generateComponents.test.ts +27 -32
- package/src/__tests__/getAmplifyDataSchema.test.ts +17 -25
- package/src/__tests__/shouldRenderComponents.test.ts +51 -4
- package/src/__tests__/syncAmplifyUiComponents.test.ts +19 -4
- package/src/clients/amplify-studio-client.ts +31 -26
- package/src/commands/generateComponents.ts +2 -5
- package/src/commands/utils/codegenResources.ts +8 -3
- package/src/commands/utils/featureFlags.ts +6 -5
- package/src/commands/utils/shouldRenderComponents.ts +20 -8
- package/src/commands/utils/syncAmplifyUiBuilderComponents.ts +25 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -6,7 +6,7 @@ const extractArgsDependencyMock = extractArgsDependency as any;
|
|
|
6
6
|
const awsMock = aws as any;
|
|
7
7
|
|
|
8
8
|
jest.mock('../commands/utils/featureFlags', () => ({
|
|
9
|
-
getTransformerVersion: jest.fn().
|
|
9
|
+
getTransformerVersion: jest.fn().mockReturnValue(2),
|
|
10
10
|
}));
|
|
11
11
|
jest.mock('../commands/utils/extractArgs');
|
|
12
12
|
jest.mock('amplify-cli-core');
|
|
@@ -21,7 +21,7 @@ const mockedComponentExport = jest.fn((envName: string) => {
|
|
|
21
21
|
entities: [{}],
|
|
22
22
|
};
|
|
23
23
|
});
|
|
24
|
-
const mockedComponentCreate = jest.fn(
|
|
24
|
+
const mockedComponentCreate = jest.fn().mockReturnValue({ entity: {} });
|
|
25
25
|
|
|
26
26
|
describe('can clone components to new environment', () => {
|
|
27
27
|
let context: any;
|
|
@@ -37,26 +37,26 @@ describe('can clone components to new environment', () => {
|
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
};
|
|
40
|
-
extractArgsDependencyMock.extractArgs = jest.fn().
|
|
40
|
+
extractArgsDependencyMock.extractArgs = jest.fn().mockReturnValue({
|
|
41
41
|
sourceEnvName: 'sourceEnvName',
|
|
42
42
|
newEnvName: 'newEnvName',
|
|
43
43
|
appId: 'appId',
|
|
44
44
|
environmentName: 'environmentName',
|
|
45
|
-
})
|
|
46
|
-
awsMock.AmplifyUIBuilder = jest.fn(
|
|
45
|
+
});
|
|
46
|
+
awsMock.AmplifyUIBuilder = jest.fn().mockReturnValue({
|
|
47
47
|
exportComponents: jest.fn(({ environmentName }) => ({
|
|
48
48
|
promise: () => mockedComponentExport(environmentName),
|
|
49
49
|
})),
|
|
50
|
-
createComponent: jest.fn(
|
|
51
|
-
getMetadata: jest.fn(
|
|
52
|
-
promise: jest.fn(
|
|
50
|
+
createComponent: jest.fn().mockReturnValue({ promise: () => mockedComponentCreate() }),
|
|
51
|
+
getMetadata: jest.fn().mockReturnValue({
|
|
52
|
+
promise: jest.fn().mockReturnValue({
|
|
53
53
|
features: {
|
|
54
54
|
autoGenerateForms: 'true',
|
|
55
55
|
autoGenerateViews: 'true',
|
|
56
56
|
},
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
})
|
|
57
|
+
}),
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
it('clones components to a new env', async () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable spellcheck/spell-checker */
|
|
1
2
|
import * as codegen from '@aws-amplify/codegen-ui'; // eslint-disable-line import/no-extraneous-dependencies
|
|
2
3
|
import {
|
|
3
4
|
generateAmplifyUiBuilderIndexFile,
|
|
@@ -44,9 +45,9 @@ describe('can create a ui builder component', () => {
|
|
|
44
45
|
variants: [],
|
|
45
46
|
};
|
|
46
47
|
const renderSchemaToTemplateMock = jest.fn();
|
|
47
|
-
codegenMock.StudioTemplateRendererManager = jest.fn().
|
|
48
|
+
codegenMock.StudioTemplateRendererManager = jest.fn().mockReturnValue({
|
|
48
49
|
renderSchemaToTemplate: renderSchemaToTemplateMock,
|
|
49
|
-
})
|
|
50
|
+
});
|
|
50
51
|
});
|
|
51
52
|
it('calls the renderManager', () => {
|
|
52
53
|
createUiBuilderComponent(context, schema);
|
|
@@ -56,6 +57,10 @@ describe('can create a ui builder component', () => {
|
|
|
56
57
|
createUiBuilderTheme(context, schema);
|
|
57
58
|
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).toBeCalled();
|
|
58
59
|
});
|
|
60
|
+
it('calls the renderManager for default theme', () => {
|
|
61
|
+
createUiBuilderTheme(context, schema, { renderDefaultTheme: true });
|
|
62
|
+
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).toBeCalled();
|
|
63
|
+
});
|
|
59
64
|
it('calls the renderManager for forms', () => {
|
|
60
65
|
createUiBuilderForm(context, schema);
|
|
61
66
|
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).toBeCalled();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies
|
|
2
|
-
import { CloudformationProviderFacade } from 'amplify-cli-core';
|
|
3
2
|
import * as utils from '../commands/utils';
|
|
4
3
|
import { run } from '../commands/generateComponents';
|
|
5
4
|
|
|
@@ -8,13 +7,10 @@ jest.mock('amplify-cli-core');
|
|
|
8
7
|
const awsMock = aws as any;
|
|
9
8
|
const utilsMock = utils as any;
|
|
10
9
|
|
|
11
|
-
utilsMock.shouldRenderComponents = jest.fn().
|
|
12
|
-
utilsMock.notifyMissingPackages = jest.fn().
|
|
13
|
-
CloudformationProviderFacade.isAmplifyAdminApp = jest.fn().mockImplementation(() => ({
|
|
14
|
-
isAdminApp: true,
|
|
15
|
-
}));
|
|
10
|
+
utilsMock.shouldRenderComponents = jest.fn().mockReturnValue(true);
|
|
11
|
+
utilsMock.notifyMissingPackages = jest.fn().mockReturnValue(true);
|
|
16
12
|
jest.mock('../commands/utils/featureFlags', () => ({
|
|
17
|
-
getTransformerVersion: jest.fn().mockImplementation(() => 2)
|
|
13
|
+
getTransformerVersion: jest.fn().mockImplementation(() => 2),
|
|
18
14
|
}));
|
|
19
15
|
|
|
20
16
|
describe('can generate components', () => {
|
|
@@ -43,37 +39,37 @@ describe('can generate components', () => {
|
|
|
43
39
|
},
|
|
44
40
|
],
|
|
45
41
|
};
|
|
46
|
-
mockedExport = jest.fn(
|
|
42
|
+
mockedExport = jest.fn().mockReturnValue({
|
|
47
43
|
entities: schemas.entities,
|
|
48
|
-
})
|
|
49
|
-
awsMock.AmplifyUIBuilder = jest.fn(
|
|
50
|
-
exportComponents: jest.fn(
|
|
44
|
+
});
|
|
45
|
+
awsMock.AmplifyUIBuilder = jest.fn().mockReturnValue({
|
|
46
|
+
exportComponents: jest.fn().mockReturnValue({
|
|
51
47
|
promise: () => mockedExport(),
|
|
52
|
-
})
|
|
53
|
-
exportThemes: jest.fn(
|
|
48
|
+
}),
|
|
49
|
+
exportThemes: jest.fn().mockReturnValue({
|
|
54
50
|
promise: () => mockedExport(),
|
|
55
|
-
})
|
|
56
|
-
exportForms: jest.fn(
|
|
51
|
+
}),
|
|
52
|
+
exportForms: jest.fn().mockReturnValue({
|
|
57
53
|
promise: () => mockedExport(),
|
|
58
|
-
})
|
|
59
|
-
exportViews: jest.fn(
|
|
54
|
+
}),
|
|
55
|
+
exportViews: jest.fn().mockReturnValue({
|
|
60
56
|
promise: () => mockedExport(),
|
|
61
|
-
})
|
|
62
|
-
getMetadata: jest.fn(
|
|
63
|
-
promise: jest.fn(
|
|
57
|
+
}),
|
|
58
|
+
getMetadata: jest.fn().mockReturnValue({
|
|
59
|
+
promise: jest.fn().mockReturnValue({
|
|
64
60
|
features: {
|
|
65
61
|
autoGenerateForms: 'true',
|
|
66
62
|
autoGenerateViews: 'true',
|
|
67
63
|
},
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
})
|
|
71
|
-
utilsMock.generateUiBuilderComponents = jest.fn().
|
|
72
|
-
utilsMock.generateUiBuilderThemes = jest.fn().
|
|
73
|
-
utilsMock.generateUiBuilderForms = jest.fn().
|
|
74
|
-
utilsMock.getAmplifyDataSchema = jest.fn().
|
|
75
|
-
utilsMock.generateAmplifyUiBuilderIndexFile = jest.fn().
|
|
76
|
-
utilsMock.generateAmplifyUiBuilderUtilFile = jest.fn().
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
utilsMock.generateUiBuilderComponents = jest.fn().mockReturnValue(schemas.entities);
|
|
68
|
+
utilsMock.generateUiBuilderThemes = jest.fn().mockReturnValue(schemas.entities);
|
|
69
|
+
utilsMock.generateUiBuilderForms = jest.fn().mockReturnValue(schemas.entities);
|
|
70
|
+
utilsMock.getAmplifyDataSchema = jest.fn().mockReturnValue(undefined);
|
|
71
|
+
utilsMock.generateAmplifyUiBuilderIndexFile = jest.fn().mockReturnValue(true);
|
|
72
|
+
utilsMock.generateAmplifyUiBuilderUtilFile = jest.fn().mockReturnValue(true);
|
|
77
73
|
});
|
|
78
74
|
|
|
79
75
|
it('runs generateComponents', async () => {
|
|
@@ -83,10 +79,9 @@ describe('can generate components', () => {
|
|
|
83
79
|
expect(utilsMock.generateUiBuilderThemes).toBeCalledTimes(1);
|
|
84
80
|
expect(utilsMock.generateUiBuilderForms).toBeCalledTimes(1);
|
|
85
81
|
});
|
|
82
|
+
|
|
86
83
|
it('does not run generateComponents if not Amplify Admin app', async () => {
|
|
87
|
-
|
|
88
|
-
isAdminApp: false,
|
|
89
|
-
}));
|
|
84
|
+
utilsMock.shouldRenderComponents = jest.fn().mockReturnValue(false);
|
|
90
85
|
await run(context);
|
|
91
86
|
expect(mockedExport).toBeCalledTimes(0);
|
|
92
87
|
expect(utilsMock.generateUiBuilderComponents).toBeCalledTimes(0);
|
|
@@ -81,16 +81,16 @@ describe('should sync amplify backend models', () => {
|
|
|
81
81
|
|
|
82
82
|
mockedFeatureFlags.getNumber.mockReturnValue(2);
|
|
83
83
|
getMockedSchema.mockClear();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
it('should getAmplifyBackendModels', async () => {
|
|
87
|
-
awsMock.AmplifyBackend = jest.fn(() => ({
|
|
88
|
-
getBackendAPIModels: jest.fn(() => ({
|
|
84
|
+
awsMock.AmplifyBackend = jest.fn().mockReturnValue({
|
|
85
|
+
getBackendAPIModels: jest.fn().mockReturnValue({
|
|
89
86
|
promise: () => ({
|
|
90
87
|
Models: getMockedSchema(),
|
|
91
88
|
}),
|
|
92
|
-
})
|
|
93
|
-
})
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should getAmplifyBackendModels', async () => {
|
|
94
94
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
95
95
|
const dataSchema = await getAmplifyDataSchema(client);
|
|
96
96
|
expect(getMockedSchema).toBeCalled();
|
|
@@ -100,14 +100,6 @@ describe('should sync amplify backend models', () => {
|
|
|
100
100
|
|
|
101
101
|
it('should not getAmplifyBackendModels and return undefined if graphQLTransformer version not supported', async () => {
|
|
102
102
|
mockedFeatureFlags.getNumber.mockReturnValue(1);
|
|
103
|
-
|
|
104
|
-
awsMock.AmplifyBackend = jest.fn(() => ({
|
|
105
|
-
getBackendAPIModels: jest.fn(() => ({
|
|
106
|
-
promise: () => ({
|
|
107
|
-
Models: getMockedSchema(),
|
|
108
|
-
}),
|
|
109
|
-
})),
|
|
110
|
-
}));
|
|
111
103
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
112
104
|
const dataSchema = await getAmplifyDataSchema(client);
|
|
113
105
|
expect(getMockedSchema).not.toBeCalled();
|
|
@@ -115,13 +107,13 @@ describe('should sync amplify backend models', () => {
|
|
|
115
107
|
});
|
|
116
108
|
|
|
117
109
|
it('should handle Models not found', async () => {
|
|
118
|
-
awsMock.AmplifyBackend = jest.fn(
|
|
119
|
-
getBackendAPIModels: jest.fn(
|
|
120
|
-
promise:
|
|
110
|
+
awsMock.AmplifyBackend = jest.fn().mockReturnValue({
|
|
111
|
+
getBackendAPIModels: jest.fn().mockReturnValue({
|
|
112
|
+
promise: () => ({
|
|
121
113
|
Models: undefined,
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
})
|
|
114
|
+
}),
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
125
117
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
126
118
|
const dataSchema = await getAmplifyDataSchema(client);
|
|
127
119
|
expect(dataSchema).toBeUndefined();
|
|
@@ -129,11 +121,11 @@ describe('should sync amplify backend models', () => {
|
|
|
129
121
|
});
|
|
130
122
|
|
|
131
123
|
it('should handle network error', async () => {
|
|
132
|
-
awsMock.AmplifyBackend = jest.fn(
|
|
133
|
-
getBackendAPIModels: jest.fn(
|
|
124
|
+
awsMock.AmplifyBackend = jest.fn().mockReturnValue({
|
|
125
|
+
getBackendAPIModels: jest.fn().mockReturnValue({
|
|
134
126
|
promise: jest.fn().mockRejectedValue(new Error('Network Error')),
|
|
135
|
-
})
|
|
136
|
-
})
|
|
127
|
+
}),
|
|
128
|
+
});
|
|
137
129
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
138
130
|
const dataSchema = await getAmplifyDataSchema(client);
|
|
139
131
|
expect(dataSchema).toBeUndefined();
|
|
@@ -1,13 +1,60 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import {
|
|
3
|
+
$TSContext, AmplifyCategories, AmplifySupportedService, CloudformationProviderFacade,
|
|
4
|
+
} from 'amplify-cli-core';
|
|
5
|
+
import aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies
|
|
2
6
|
import { shouldRenderComponents } from '../commands/utils/shouldRenderComponents';
|
|
3
7
|
|
|
8
|
+
const awsMock = aws as any;
|
|
9
|
+
|
|
10
|
+
jest.mock('amplify-cli-core', () => ({
|
|
11
|
+
...jest.requireActual('amplify-cli-core'),
|
|
12
|
+
stateManager: {
|
|
13
|
+
getMeta: jest.fn(() => ({
|
|
14
|
+
[AmplifyCategories.API]: {
|
|
15
|
+
MyResourceName: {
|
|
16
|
+
service: AmplifySupportedService.APPSYNC,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
})),
|
|
20
|
+
// eslint-disable-next-line spellcheck/spell-checker
|
|
21
|
+
getCLIJSON: jest.fn().mockReturnValue({ features: { graphqltransformer: { transformerversion: 2 } } }),
|
|
22
|
+
setCLIJSON: jest.fn(),
|
|
23
|
+
},
|
|
24
|
+
FeatureFlags: {
|
|
25
|
+
getBoolean: () => true,
|
|
26
|
+
getNumber: jest.fn().mockReturnValue(2),
|
|
27
|
+
reloadValues: jest.fn(),
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
CloudformationProviderFacade.isAmplifyAdminApp = jest.fn().mockReturnValue({
|
|
31
|
+
isAdminApp: true,
|
|
32
|
+
});
|
|
33
|
+
|
|
4
34
|
describe('should render components', () => {
|
|
5
35
|
let context: $TSContext | any;
|
|
6
|
-
|
|
36
|
+
|
|
37
|
+
beforeAll(async () => {
|
|
38
|
+
// set metadata response
|
|
39
|
+
awsMock.AmplifyUIBuilder = jest.fn(() => ({
|
|
40
|
+
getMetadata: jest.fn(() => ({
|
|
41
|
+
promise: jest.fn(() => ({
|
|
42
|
+
features: {
|
|
43
|
+
autoGenerateForms: 'true',
|
|
44
|
+
autoGenerateViews: 'true',
|
|
45
|
+
},
|
|
46
|
+
})),
|
|
47
|
+
})),
|
|
48
|
+
}));
|
|
7
49
|
context = {
|
|
50
|
+
amplify: {
|
|
51
|
+
invokePluginMethod: () => ({}),
|
|
52
|
+
},
|
|
8
53
|
input: {
|
|
9
54
|
options: {
|
|
10
55
|
'no-codegen': false,
|
|
56
|
+
appId: 'testAppId',
|
|
57
|
+
envName: 'testEnvName',
|
|
11
58
|
},
|
|
12
59
|
},
|
|
13
60
|
exeInfo: {
|
|
@@ -35,12 +82,12 @@ describe('should render components', () => {
|
|
|
35
82
|
const shouldIt = await shouldRenderComponents(context);
|
|
36
83
|
expect(shouldIt).toBe(false);
|
|
37
84
|
});
|
|
38
|
-
it(
|
|
85
|
+
it('should return false if frontend is ios', async () => {
|
|
39
86
|
context.exeInfo.projectConfig.frontend = 'ios';
|
|
40
87
|
const shouldIt = await shouldRenderComponents(context);
|
|
41
88
|
expect(shouldIt).toBe(false);
|
|
42
89
|
});
|
|
43
|
-
it(
|
|
90
|
+
it('should return false if frontend is vue', async () => {
|
|
44
91
|
context.exeInfo.projectConfig.javascript.framework = 'vue';
|
|
45
92
|
const shouldIt = await shouldRenderComponents(context);
|
|
46
93
|
expect(shouldIt).toBe(false);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable spellcheck/spell-checker */
|
|
1
2
|
import { AmplifyCategories, AmplifySupportedService, stateManager } from 'amplify-cli-core'; // eslint-disable-line import/no-extraneous-dependencies
|
|
2
3
|
import aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies
|
|
3
4
|
import {
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
import { AmplifyStudioClient } from '../clients';
|
|
12
13
|
import * as createUiBuilderComponentDependency from '../commands/utils/codegenResources';
|
|
13
14
|
import { exampleSchema } from './utils';
|
|
14
|
-
import { GenericDataModel, GenericDataSchema } from '@aws-amplify/codegen-ui';
|
|
15
15
|
|
|
16
16
|
jest.mock('amplify-cli-core', () => ({
|
|
17
17
|
...jest.requireActual('amplify-cli-core'),
|
|
@@ -21,7 +21,7 @@ jest.mock('amplify-cli-core', () => ({
|
|
|
21
21
|
},
|
|
22
22
|
}));
|
|
23
23
|
jest.mock('../commands/utils/featureFlags', () => ({
|
|
24
|
-
getTransformerVersion: jest.fn().
|
|
24
|
+
getTransformerVersion: jest.fn().mockReturnValue(2),
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
27
|
const awsMock = aws as any;
|
|
@@ -238,6 +238,18 @@ describe('should sync amplify ui builder components', () => {
|
|
|
238
238
|
const themes = generateUiBuilderThemes(context, [{}, {}]);
|
|
239
239
|
expect(themes.every(theme => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
240
240
|
});
|
|
241
|
+
it('can generate ui builder default theme when no themes are passed', async () => {
|
|
242
|
+
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => ({}));
|
|
243
|
+
const themes = generateUiBuilderThemes(context, []);
|
|
244
|
+
expect(themes.every(theme => theme.resultType === 'SUCCESS')).toBeTruthy();
|
|
245
|
+
});
|
|
246
|
+
it('can handle failed generation generate ui builder default theme when no themes are passed', async () => {
|
|
247
|
+
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => {
|
|
248
|
+
throw new Error('ahh!');
|
|
249
|
+
});
|
|
250
|
+
const themes = generateUiBuilderThemes(context, []);
|
|
251
|
+
expect(themes.every(theme => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
252
|
+
});
|
|
241
253
|
it('can generate ui builder forms', async () => {
|
|
242
254
|
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(() => ({}));
|
|
243
255
|
const forms = generateUiBuilderForms(context, [{}, {}]);
|
|
@@ -259,8 +271,11 @@ describe('should sync amplify ui builder components', () => {
|
|
|
259
271
|
});
|
|
260
272
|
|
|
261
273
|
it('should not autogen forms for join tables or unsupported models', async () => {
|
|
262
|
-
expect(Object.keys(exampleSchema.models)).toStrictEqual(['Author', 'JoinTable', 'EmptyModel'
|
|
263
|
-
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(
|
|
274
|
+
expect(Object.keys(exampleSchema.models)).toStrictEqual(['Author', 'JoinTable', 'EmptyModel']);
|
|
275
|
+
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(
|
|
276
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
277
|
+
(_ctx, schema, _dataSchema) => ({ name: schema.dataType.dataTypeName }),
|
|
278
|
+
);
|
|
264
279
|
const forms = generateUiBuilderForms(context, [], exampleSchema, true);
|
|
265
280
|
expect(forms.every(form => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
266
281
|
// only create & update form for author model
|
|
@@ -57,7 +57,23 @@ export default class AmplifyStudioClient {
|
|
|
57
57
|
#appId: string;
|
|
58
58
|
#envName: string;
|
|
59
59
|
metadata: StudioMetadata;
|
|
60
|
-
|
|
60
|
+
isGraphQLSupported = false;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* static function meant to check if given appId is studio enabled
|
|
64
|
+
*/
|
|
65
|
+
static isAmplifyApp = async (context: $TSContext, appId: string): Promise<boolean> => {
|
|
66
|
+
try {
|
|
67
|
+
const { isAdminApp } = await CloudformationProviderFacade.isAmplifyAdminApp(context, appId);
|
|
68
|
+
return isAdminApp;
|
|
69
|
+
} catch (err) {
|
|
70
|
+
// return false is admin app failed check
|
|
71
|
+
// this means we wont run codegen-ui
|
|
72
|
+
printer.debug(`Failed admin app check: ${err.message}`);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
/**
|
|
62
78
|
* Used to configure the AWS Amplify clients.
|
|
63
79
|
*/
|
|
@@ -72,11 +88,11 @@ export default class AmplifyStudioClient {
|
|
|
72
88
|
|
|
73
89
|
const client = new AmplifyStudioClient(awsConfigInfo, resolvedAppId, resolvedEnvName);
|
|
74
90
|
|
|
75
|
-
if ((await getTransformerVersion(
|
|
91
|
+
if ((await getTransformerVersion()) === 2) {
|
|
76
92
|
await client.loadMetadata();
|
|
77
|
-
client.
|
|
93
|
+
client.isGraphQLSupported = true;
|
|
78
94
|
} else {
|
|
79
|
-
client.
|
|
95
|
+
client.isGraphQLSupported = false;
|
|
80
96
|
}
|
|
81
97
|
|
|
82
98
|
return client;
|
|
@@ -113,9 +129,8 @@ export default class AmplifyStudioClient {
|
|
|
113
129
|
autoGenerateForms: response.features?.autoGenerateForms === 'true',
|
|
114
130
|
autoGenerateViews: response.features?.autoGenerateViews === 'true',
|
|
115
131
|
};
|
|
116
|
-
} catch (
|
|
117
|
-
|
|
118
|
-
throw e;
|
|
132
|
+
} catch (err) {
|
|
133
|
+
throw new Error(`Failed to load metadata: ${err.message}`);
|
|
119
134
|
}
|
|
120
135
|
};
|
|
121
136
|
|
|
@@ -141,9 +156,8 @@ export default class AmplifyStudioClient {
|
|
|
141
156
|
} while (nextToken);
|
|
142
157
|
printer.debug(JSON.stringify(uiBuilderComponents, null, 2));
|
|
143
158
|
return { entities: uiBuilderComponents };
|
|
144
|
-
} catch (
|
|
145
|
-
|
|
146
|
-
throw e;
|
|
159
|
+
} catch (err) {
|
|
160
|
+
throw new Error(`Failed to list components: ${err.message}`);
|
|
147
161
|
}
|
|
148
162
|
};
|
|
149
163
|
|
|
@@ -170,9 +184,8 @@ export default class AmplifyStudioClient {
|
|
|
170
184
|
} while (nextToken);
|
|
171
185
|
printer.debug(JSON.stringify(uiBuilderThemes, null, 2));
|
|
172
186
|
return { entities: uiBuilderThemes };
|
|
173
|
-
} catch (
|
|
174
|
-
|
|
175
|
-
throw e;
|
|
187
|
+
} catch (err) {
|
|
188
|
+
throw new Error(`Failed to list themes: ${err.message}`);
|
|
176
189
|
}
|
|
177
190
|
};
|
|
178
191
|
|
|
@@ -195,9 +208,8 @@ export default class AmplifyStudioClient {
|
|
|
195
208
|
} while (nextToken);
|
|
196
209
|
printer.debug(JSON.stringify(uibuilderForms, null, 2));
|
|
197
210
|
return { entities: uibuilderForms };
|
|
198
|
-
} catch (
|
|
199
|
-
|
|
200
|
-
throw e;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
throw new Error(`Failed to list forms: ${err.message}`);
|
|
201
213
|
}
|
|
202
214
|
};
|
|
203
215
|
|
|
@@ -214,8 +226,7 @@ export default class AmplifyStudioClient {
|
|
|
214
226
|
.promise();
|
|
215
227
|
return response.entity;
|
|
216
228
|
} catch (err) {
|
|
217
|
-
|
|
218
|
-
throw err;
|
|
229
|
+
throw new Error(`Failed to create component: ${err.message}`);
|
|
219
230
|
}
|
|
220
231
|
};
|
|
221
232
|
|
|
@@ -231,14 +242,8 @@ export default class AmplifyStudioClient {
|
|
|
231
242
|
})
|
|
232
243
|
.promise();
|
|
233
244
|
return Models;
|
|
234
|
-
} catch (
|
|
235
|
-
|
|
236
|
-
throw new Error(`Models not found in AmplifyBackend:GetBackendAPIModels response: ${e.message}`);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
throw new Error(`Models not found in AmplifyBackend:GetBackendAPIModels response: ${err.message}`);
|
|
237
247
|
}
|
|
238
248
|
};
|
|
239
|
-
|
|
240
|
-
isAmplifyApp = async (context: $TSContext): Promise<boolean> => {
|
|
241
|
-
const { isAdminApp } = await CloudformationProviderFacade.isAmplifyAdminApp(context, this.#appId);
|
|
242
|
-
return isAdminApp;
|
|
243
|
-
}
|
|
244
249
|
}
|
|
@@ -25,9 +25,6 @@ export const run = async (context: $TSContext): Promise<void> => {
|
|
|
25
25
|
const spinner = ora('');
|
|
26
26
|
try {
|
|
27
27
|
const studioClient = await AmplifyStudioClient.setClientInfo(context);
|
|
28
|
-
if (!(await studioClient.isAmplifyApp(context))) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
28
|
const [componentSchemas, themeSchemas, formSchemas, dataSchema] = await Promise.all([
|
|
32
29
|
studioClient.listComponents(),
|
|
33
30
|
studioClient.listThemes(),
|
|
@@ -35,7 +32,7 @@ export const run = async (context: $TSContext): Promise<void> => {
|
|
|
35
32
|
getAmplifyDataSchema(studioClient),
|
|
36
33
|
]);
|
|
37
34
|
|
|
38
|
-
const nothingWouldAutogen = !dataSchema || !studioClient.metadata.autoGenerateForms || !studioClient.
|
|
35
|
+
const nothingWouldAutogen = !dataSchema || !studioClient.metadata.autoGenerateForms || !studioClient.isGraphQLSupported;
|
|
39
36
|
|
|
40
37
|
if (nothingWouldAutogen && [componentSchemas, themeSchemas, formSchemas].every(group => !group.entities.length)) {
|
|
41
38
|
printer.debug('Skipping UI component generation since none are found.');
|
|
@@ -47,7 +44,7 @@ export const run = async (context: $TSContext): Promise<void> => {
|
|
|
47
44
|
component: generateUiBuilderComponents(context, componentSchemas.entities, dataSchema),
|
|
48
45
|
theme: generateUiBuilderThemes(context, themeSchemas.entities),
|
|
49
46
|
form: generateUiBuilderForms(
|
|
50
|
-
context, formSchemas.entities, dataSchema, studioClient.metadata.autoGenerateForms && studioClient.
|
|
47
|
+
context, formSchemas.entities, dataSchema, studioClient.metadata.autoGenerateForms && studioClient.isGraphQLSupported,
|
|
51
48
|
),
|
|
52
49
|
};
|
|
53
50
|
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
ScriptKind,
|
|
24
24
|
UtilTemplateType,
|
|
25
25
|
ReactUtilsStudioTemplateRenderer,
|
|
26
|
+
ReactThemeStudioTemplateRendererOptions,
|
|
26
27
|
} from '@aws-amplify/codegen-ui-react';
|
|
27
28
|
import { printer } from 'amplify-prompts';
|
|
28
29
|
import {
|
|
@@ -60,10 +61,14 @@ export const createUiBuilderComponent = (context: $TSContext, schema: StudioComp
|
|
|
60
61
|
/**
|
|
61
62
|
* Writes theme file to the work space
|
|
62
63
|
*/
|
|
63
|
-
export const createUiBuilderTheme = (
|
|
64
|
+
export const createUiBuilderTheme = (
|
|
65
|
+
context: $TSContext,
|
|
66
|
+
schema: StudioTheme,
|
|
67
|
+
options?: ReactThemeStudioTemplateRendererOptions,
|
|
68
|
+
): StudioTheme => {
|
|
64
69
|
const uiBuilderComponentsPath = getUiBuilderComponentsPath(context);
|
|
65
70
|
const rendererFactory = new StudioTemplateRendererFactory(
|
|
66
|
-
(component: StudioTheme) => (new ReactThemeStudioTemplateRenderer(component, config) as unknown) as StudioTemplateRenderer<
|
|
71
|
+
(component: StudioTheme) => (new ReactThemeStudioTemplateRenderer(component, config, options) as unknown) as StudioTemplateRenderer<
|
|
67
72
|
unknown,
|
|
68
73
|
StudioTheme,
|
|
69
74
|
FrameworkOutputManager<unknown>,
|
|
@@ -198,7 +203,7 @@ export const generateAmplifyUiBuilderUtilFile = (context: $TSContext, { hasForms
|
|
|
198
203
|
export const getAmplifyDataSchema = async (
|
|
199
204
|
studioClient: AmplifyStudioClient,
|
|
200
205
|
): Promise<GenericDataSchema | undefined> => {
|
|
201
|
-
if (!studioClient.
|
|
206
|
+
if (!studioClient.isGraphQLSupported) {
|
|
202
207
|
return undefined;
|
|
203
208
|
}
|
|
204
209
|
try {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* eslint-disable spellcheck/spell-checker */
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
FeatureFlags, pathManager, stateManager,
|
|
4
4
|
} from 'amplify-cli-core';
|
|
5
|
+
import { printer } from 'amplify-prompts';
|
|
5
6
|
|
|
6
7
|
// This is copy-pasta from the category api until they can expose the method to plugins
|
|
7
8
|
|
|
@@ -15,13 +16,13 @@ const transformerVersionFF = (): number => FeatureFlags.getNumber('graphQLTransf
|
|
|
15
16
|
* Inspect feature flags for the project and determine if this particular project should be using graphql v2 or v1.
|
|
16
17
|
* Coerces feature flags into a sane state if they are out of, and throws error on invalid configuration.
|
|
17
18
|
*/
|
|
18
|
-
export const getTransformerVersion = async (
|
|
19
|
+
export const getTransformerVersion = async (): Promise<number> => {
|
|
19
20
|
if (useExperimentalPipelinedTransformerFF() === false) {
|
|
20
21
|
return 1;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
if (isLegacyFeatureFlagConfiguration()) {
|
|
24
|
-
await migrateToTransformerVersionFeatureFlag(
|
|
25
|
+
await migrateToTransformerVersionFeatureFlag();
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const transformerVersion = transformerVersionFF();
|
|
@@ -40,7 +41,7 @@ const isLegacyFeatureFlagConfiguration = (): boolean => useExperimentalPipelined
|
|
|
40
41
|
/**
|
|
41
42
|
* Update project feature flags and alert the user if they have a deprecated set of feature flags.
|
|
42
43
|
*/
|
|
43
|
-
const migrateToTransformerVersionFeatureFlag = async (
|
|
44
|
+
const migrateToTransformerVersionFeatureFlag = async (): Promise<void> => {
|
|
44
45
|
const projectPath = pathManager.findProjectRoot() ?? process.cwd();
|
|
45
46
|
|
|
46
47
|
const config = stateManager.getCLIJSON(projectPath, undefined, {
|
|
@@ -53,7 +54,7 @@ const migrateToTransformerVersionFeatureFlag = async (context: $TSContext): Prom
|
|
|
53
54
|
stateManager.setCLIJSON(projectPath, config);
|
|
54
55
|
await FeatureFlags.reloadValues();
|
|
55
56
|
// eslint-disable-next-line spellcheck/spell-checker
|
|
56
|
-
|
|
57
|
+
printer.warn(
|
|
57
58
|
`\nThe project is configured with 'transformerVersion': ${transformerVersionFF()}, but 'useExperimentalPipelinedTransformer': ${useExperimentalPipelinedTransformerFF()}. Setting the 'transformerVersion': ${
|
|
58
59
|
config.features.graphqltransformer.transformerversion
|
|
59
60
|
}. 'useExperimentalPipelinedTransformer' is deprecated.`,
|
|
@@ -1,34 +1,46 @@
|
|
|
1
|
+
/* eslint-disable prefer-arrow/prefer-arrow-functions */
|
|
1
2
|
import { $TSContext } from 'amplify-cli-core';
|
|
2
3
|
import { printer } from 'amplify-prompts';
|
|
3
|
-
|
|
4
|
+
import { AmplifyStudioClient } from '../../clients';
|
|
5
|
+
import { getAppId } from './environmentHelpers';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* process to decide if we should render components
|
|
9
|
+
*/
|
|
10
|
+
export const shouldRenderComponents = async (context: $TSContext): Promise<boolean> => {
|
|
4
11
|
if (process.env.FORCE_RENDER) {
|
|
5
12
|
printer.debug('Forcing component render since environment variable flag is set.');
|
|
6
13
|
return true;
|
|
7
14
|
}
|
|
8
15
|
if (context?.input?.options?.['no-codegen']) {
|
|
9
|
-
printer.debug('Not pulling components because --no-codegen flag is set');
|
|
16
|
+
printer.debug('Not pulling components because --no-codegen flag is set.');
|
|
10
17
|
return false;
|
|
11
18
|
}
|
|
12
19
|
|
|
13
20
|
if (!context?.exeInfo?.projectConfig) {
|
|
14
|
-
printer.debug('Not pulling components because there is no projectConfig set for this project');
|
|
21
|
+
printer.debug('Not pulling components because there is no projectConfig set for this project.');
|
|
15
22
|
return false;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
if (!context.exeInfo.projectConfig.providers.includes('awscloudformation')) {
|
|
19
|
-
printer.debug('Not pulling components because there is no "awscloudformation" provider');
|
|
26
|
+
printer.debug('Not pulling components because there is no "awscloudformation" provider.');
|
|
20
27
|
return false;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
if (context.exeInfo.projectConfig.frontend !== 'javascript') {
|
|
24
|
-
printer.debug('Not pulling components because this project is not configured as a javascript frontend');
|
|
31
|
+
printer.debug('Not pulling components because this project is not configured as a javascript frontend.');
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (context.exeInfo.projectConfig.javascript.framework !== 'react') {
|
|
36
|
+
printer.debug('Not pulling components because this project is not configured with the "react" framework.');
|
|
25
37
|
return false;
|
|
26
38
|
}
|
|
27
39
|
|
|
28
|
-
if (context
|
|
29
|
-
printer.debug('Not pulling components because this project is not
|
|
40
|
+
if (!(await AmplifyStudioClient.isAmplifyApp(context, getAppId(context)))) {
|
|
41
|
+
printer.debug('Not pulling components because this project is not Amplify Studio enabled.');
|
|
30
42
|
return false;
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
return true;
|
|
34
|
-
}
|
|
46
|
+
};
|