@aws-amplify/amplify-util-uibuilder 1.6.8-beta.1 → 1.6.8-beta.2
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 +11 -0
- package/amplify-plugin.json +2 -11
- package/lib/clients/amplify-studio-client.d.ts.map +1 -1
- package/lib/clients/amplify-studio-client.js +1 -3
- package/lib/clients/amplify-studio-client.js.map +1 -1
- package/lib/commands/cloneComponentsFromEnv.d.ts.map +1 -1
- package/lib/commands/cloneComponentsFromEnv.js +2 -1
- package/lib/commands/cloneComponentsFromEnv.js.map +1 -1
- package/lib/commands/generateComponents.js +9 -9
- package/lib/commands/generateComponents.js.map +1 -1
- package/lib/commands/utils/codegenResources.d.ts.map +1 -1
- package/lib/commands/utils/codegenResources.js +2 -2
- package/lib/commands/utils/codegenResources.js.map +1 -1
- package/lib/commands/utils/detachedFormCleanup.d.ts.map +1 -1
- package/lib/commands/utils/detachedFormCleanup.js +1 -2
- package/lib/commands/utils/detachedFormCleanup.js.map +1 -1
- package/lib/commands/utils/featureFlags.d.ts.map +1 -1
- package/lib/commands/utils/featureFlags.js.map +1 -1
- package/lib/commands/utils/notifyMissingPackages.d.ts.map +1 -1
- package/lib/commands/utils/notifyMissingPackages.js.map +1 -1
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.d.ts.map +1 -1
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.js +9 -6
- package/lib/commands/utils/syncAmplifyUiBuilderComponents.js.map +1 -1
- package/lib/utils/prePushHandler.d.ts.map +1 -1
- package/lib/utils/prePushHandler.js +2 -5
- package/lib/utils/prePushHandler.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/createUiBuilderComponent.test.ts +4 -2
- package/src/__tests__/detachedFormCleanup.test.ts +3 -6
- package/src/__tests__/generateComponents.test.ts +1 -1
- package/src/__tests__/getAmplifyDataSchema.test.ts +2 -1
- package/src/__tests__/package.json +2 -2
- package/src/__tests__/prePushHandler.test.ts +3 -1
- package/src/__tests__/shouldRenderComponents.test.ts +8 -8
- package/src/__tests__/syncAmplifyUiComponents.test.ts +54 -53
- package/src/__tests__/utils.ts +2 -3
- package/src/clients/amplify-studio-client.ts +4 -8
- package/src/commands/cloneComponentsFromEnv.ts +4 -6
- package/src/commands/generateComponents.ts +11 -11
- package/src/commands/utils/codegenResources.ts +14 -15
- package/src/commands/utils/detachedFormCleanup.ts +6 -6
- package/src/commands/utils/featureFlags.ts +3 -4
- package/src/commands/utils/notifyMissingPackages.ts +1 -3
- package/src/commands/utils/syncAmplifyUiBuilderComponents.ts +12 -18
- package/src/utils/prePushHandler.ts +15 -15
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
-
import {$TSContext} from 'amplify-cli-core';
|
|
2
|
+
import { $TSContext } from 'amplify-cli-core';
|
|
3
3
|
import aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies
|
|
4
4
|
import { shouldRenderComponents } from '../commands/utils/shouldRenderComponents';
|
|
5
5
|
|
|
@@ -14,14 +14,14 @@ jest.mock('amplify-cli-core', () => ({
|
|
|
14
14
|
javascript: {
|
|
15
15
|
framework: 'react',
|
|
16
16
|
},
|
|
17
|
-
})
|
|
17
|
+
}),
|
|
18
18
|
},
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
21
|
jest.mock('../clients', () => ({
|
|
22
22
|
AmplifyStudioClient: {
|
|
23
|
-
isAmplifyApp: jest.fn().mockReturnValue(true)
|
|
24
|
-
}
|
|
23
|
+
isAmplifyApp: jest.fn().mockReturnValue(true),
|
|
24
|
+
},
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
27
|
describe('should render components', () => {
|
|
@@ -70,8 +70,8 @@ describe('should render components', () => {
|
|
|
70
70
|
javascript: {
|
|
71
71
|
framework: 'react',
|
|
72
72
|
},
|
|
73
|
-
})
|
|
74
|
-
}
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
75
|
}));
|
|
76
76
|
const shouldIt = await shouldRenderComponents(context);
|
|
77
77
|
expect(shouldIt).toBe(false);
|
|
@@ -83,7 +83,7 @@ describe('should render components', () => {
|
|
|
83
83
|
getProjectConfig: jest.fn().mockReturnValue({
|
|
84
84
|
providers: [],
|
|
85
85
|
frontend: 'ios',
|
|
86
|
-
})
|
|
86
|
+
}),
|
|
87
87
|
},
|
|
88
88
|
}));
|
|
89
89
|
const shouldIt = await shouldRenderComponents(context);
|
|
@@ -99,7 +99,7 @@ describe('should render components', () => {
|
|
|
99
99
|
javascript: {
|
|
100
100
|
framework: 'vue',
|
|
101
101
|
},
|
|
102
|
-
})
|
|
102
|
+
}),
|
|
103
103
|
},
|
|
104
104
|
}));
|
|
105
105
|
const shouldIt = await shouldRenderComponents(context);
|
|
@@ -90,44 +90,48 @@ describe('should sync amplify ui builder components', () => {
|
|
|
90
90
|
})),
|
|
91
91
|
exportForms: jest.fn(() => ({
|
|
92
92
|
promise: jest.fn(() => ({
|
|
93
|
-
entities: [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
entities: [
|
|
94
|
+
{
|
|
95
|
+
name: 'BasicFormCreate',
|
|
96
|
+
formActionType: 'create',
|
|
97
|
+
dataType: {
|
|
98
|
+
dataSourceType: 'Custom',
|
|
99
|
+
dataTypeName: 'Post',
|
|
100
|
+
},
|
|
101
|
+
fields: {
|
|
102
|
+
name: {
|
|
103
|
+
inputType: {
|
|
104
|
+
required: true,
|
|
105
|
+
type: 'TextField',
|
|
106
|
+
name: 'name',
|
|
107
|
+
defaultValue: 'John Doe',
|
|
108
|
+
},
|
|
109
|
+
label: 'name',
|
|
107
110
|
},
|
|
108
|
-
label: 'name',
|
|
109
111
|
},
|
|
112
|
+
sectionalElements: {},
|
|
113
|
+
style: {},
|
|
110
114
|
},
|
|
111
|
-
|
|
112
|
-
style: {},
|
|
113
|
-
}],
|
|
115
|
+
],
|
|
114
116
|
})),
|
|
115
117
|
})),
|
|
116
118
|
exportViews: jest.fn(() => ({
|
|
117
119
|
promise: jest.fn(() => ({
|
|
118
|
-
entities: [
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
entities: [
|
|
121
|
+
{
|
|
122
|
+
appId: '23342',
|
|
123
|
+
dataSource: { type: 'Custom' },
|
|
124
|
+
environmentName: 'staging',
|
|
125
|
+
id: 'id',
|
|
126
|
+
name: 'ProductTable',
|
|
127
|
+
// TODO: replace with export when Codegen updated
|
|
128
|
+
schemaVersion: '1.0',
|
|
129
|
+
style: {},
|
|
130
|
+
viewConfiguration: {
|
|
131
|
+
type: 'Table',
|
|
132
|
+
},
|
|
129
133
|
},
|
|
130
|
-
|
|
134
|
+
],
|
|
131
135
|
})),
|
|
132
136
|
})),
|
|
133
137
|
getMetadata: jest.fn(() => ({
|
|
@@ -168,18 +172,15 @@ describe('should sync amplify ui builder components', () => {
|
|
|
168
172
|
process.env.UI_BUILDER_ENDPOINT = 'https://mock-endpoint.com';
|
|
169
173
|
process.env.UI_BUILDER_REGION = 'mock-region';
|
|
170
174
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
171
|
-
expect(Object.keys(client)).toEqual(
|
|
172
|
-
'listComponents',
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
autoGenerateForms: true,
|
|
181
|
-
autoGenerateViews: true,
|
|
182
|
-
}));
|
|
175
|
+
expect(Object.keys(client)).toEqual(
|
|
176
|
+
expect.arrayContaining(['listComponents', 'listThemes', 'listForms', 'getModels', 'loadMetadata', 'createComponent']),
|
|
177
|
+
);
|
|
178
|
+
expect(client.metadata).toEqual(
|
|
179
|
+
expect.objectContaining({
|
|
180
|
+
autoGenerateForms: true,
|
|
181
|
+
autoGenerateViews: true,
|
|
182
|
+
}),
|
|
183
|
+
);
|
|
183
184
|
});
|
|
184
185
|
it('can list components', async () => {
|
|
185
186
|
const client = await AmplifyStudioClient.setClientInfo(context);
|
|
@@ -217,55 +218,55 @@ describe('should sync amplify ui builder components', () => {
|
|
|
217
218
|
it('can generate ui builder components', async () => {
|
|
218
219
|
createUiBuilderComponentDependencyMock.createUiBuilderComponent = jest.fn().mockImplementation(() => ({}));
|
|
219
220
|
const components = generateUiBuilderComponents(context, [{}, {}]);
|
|
220
|
-
expect(components.every(component => component.resultType === 'SUCCESS')).toBeTruthy();
|
|
221
|
+
expect(components.every((component) => component.resultType === 'SUCCESS')).toBeTruthy();
|
|
221
222
|
});
|
|
222
223
|
it('can handle failed generation generate ui builder components', async () => {
|
|
223
224
|
createUiBuilderComponentDependencyMock.createUiBuilderComponent = jest.fn().mockImplementation(() => {
|
|
224
225
|
throw new Error('ahh!');
|
|
225
226
|
});
|
|
226
227
|
const components = generateUiBuilderComponents(context, [{}, {}]);
|
|
227
|
-
expect(components.every(component => component.resultType === 'FAILURE')).toBeTruthy();
|
|
228
|
+
expect(components.every((component) => component.resultType === 'FAILURE')).toBeTruthy();
|
|
228
229
|
});
|
|
229
230
|
it('can generate ui builder themes', async () => {
|
|
230
231
|
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => ({}));
|
|
231
232
|
const themes = generateUiBuilderThemes(context, [{}, {}]);
|
|
232
|
-
expect(themes.every(theme => theme.resultType === 'SUCCESS')).toBeTruthy();
|
|
233
|
+
expect(themes.every((theme) => theme.resultType === 'SUCCESS')).toBeTruthy();
|
|
233
234
|
});
|
|
234
235
|
it('can handle failed generation generate ui builder themes', async () => {
|
|
235
236
|
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => {
|
|
236
237
|
throw new Error('ahh!');
|
|
237
238
|
});
|
|
238
239
|
const themes = generateUiBuilderThemes(context, [{}, {}]);
|
|
239
|
-
expect(themes.every(theme => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
240
|
+
expect(themes.every((theme) => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
240
241
|
});
|
|
241
242
|
it('can generate ui builder default theme when no themes are passed', async () => {
|
|
242
243
|
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => ({}));
|
|
243
244
|
const themes = generateUiBuilderThemes(context, []);
|
|
244
|
-
expect(themes.every(theme => theme.resultType === 'SUCCESS')).toBeTruthy();
|
|
245
|
+
expect(themes.every((theme) => theme.resultType === 'SUCCESS')).toBeTruthy();
|
|
245
246
|
});
|
|
246
247
|
it('can handle failed generation generate ui builder default theme when no themes are passed', async () => {
|
|
247
248
|
createUiBuilderComponentDependencyMock.createUiBuilderTheme = jest.fn().mockImplementation(() => {
|
|
248
249
|
throw new Error('ahh!');
|
|
249
250
|
});
|
|
250
251
|
const themes = generateUiBuilderThemes(context, []);
|
|
251
|
-
expect(themes.every(theme => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
252
|
+
expect(themes.every((theme) => theme.resultType === 'FAILURE')).toBeTruthy();
|
|
252
253
|
});
|
|
253
254
|
it('can generate ui builder forms', async () => {
|
|
254
255
|
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(() => ({}));
|
|
255
256
|
const forms = generateUiBuilderForms(context, [{}, {}]);
|
|
256
|
-
expect(forms.every(form => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
257
|
+
expect(forms.every((form) => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
257
258
|
});
|
|
258
259
|
it('can handle failed generation generate ui builder forms', async () => {
|
|
259
260
|
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(() => {
|
|
260
261
|
throw new Error('ahh!');
|
|
261
262
|
});
|
|
262
263
|
const forms = generateUiBuilderForms(context, [{}, {}]);
|
|
263
|
-
expect(forms.every(form => form.resultType === 'FAILURE')).toBeTruthy();
|
|
264
|
+
expect(forms.every((form) => form.resultType === 'FAILURE')).toBeTruthy();
|
|
264
265
|
});
|
|
265
266
|
it('can generate uibuilder forms from data schema if autogenerate true', async () => {
|
|
266
267
|
createUiBuilderComponentDependencyMock.createUiBuilderForm = jest.fn().mockImplementation(() => ({}));
|
|
267
268
|
const forms = generateUiBuilderForms(context, [], exampleSchema, true);
|
|
268
|
-
expect(forms.every(form => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
269
|
+
expect(forms.every((form) => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
269
270
|
// create & update form for author model
|
|
270
271
|
expect(forms.length).toEqual(2);
|
|
271
272
|
});
|
|
@@ -277,9 +278,9 @@ describe('should sync amplify ui builder components', () => {
|
|
|
277
278
|
(_ctx, schema, _dataSchema) => ({ name: schema.dataType.dataTypeName }),
|
|
278
279
|
);
|
|
279
280
|
const forms = generateUiBuilderForms(context, [], exampleSchema, true);
|
|
280
|
-
expect(forms.every(form => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
281
|
+
expect(forms.every((form) => form.resultType === 'SUCCESS')).toBeTruthy();
|
|
281
282
|
// only create & update form for author model
|
|
282
|
-
expect(forms.map(f => (f.schema as any).name)).toStrictEqual(['Author', 'Author']);
|
|
283
|
+
expect(forms.map((f) => (f.schema as any).name)).toStrictEqual(['Author', 'Author']);
|
|
283
284
|
});
|
|
284
285
|
|
|
285
286
|
it('does not generate uibuilder forms from data schema if autogenerate false', async () => {
|
package/src/__tests__/utils.ts
CHANGED
|
@@ -60,12 +60,11 @@ export const exampleSchema: GenericDataSchema = {
|
|
|
60
60
|
isArray: false,
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
-
isJoinTable: true
|
|
63
|
+
isJoinTable: true,
|
|
64
64
|
},
|
|
65
65
|
EmptyModel: {
|
|
66
66
|
primaryKeys: ['id'],
|
|
67
|
-
fields: {
|
|
68
|
-
},
|
|
67
|
+
fields: {},
|
|
69
68
|
},
|
|
70
69
|
},
|
|
71
70
|
enums: {}, // eslint-disable-line spellcheck/spell-checker
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { $TSContext, CloudformationProviderFacade } from 'amplify-cli-core';
|
|
2
2
|
import type { ServiceConfigurationOptions } from 'aws-sdk/lib/service';
|
|
3
|
-
import type {
|
|
4
|
-
CreateComponentData, Component, Theme, Form,
|
|
5
|
-
} from 'aws-sdk/clients/amplifyuibuilder';
|
|
3
|
+
import type { CreateComponentData, Component, Theme, Form } from 'aws-sdk/clients/amplifyuibuilder';
|
|
6
4
|
import { AmplifyUIBuilder, AmplifyBackend } from 'aws-sdk';
|
|
7
5
|
import { printer } from 'amplify-prompts';
|
|
8
6
|
import { getAppId, getEnvName } from '../commands/utils/environmentHelpers';
|
|
@@ -72,7 +70,7 @@ export default class AmplifyStudioClient {
|
|
|
72
70
|
printer.debug(`Failed admin app check: ${err.message}`);
|
|
73
71
|
return false;
|
|
74
72
|
}
|
|
75
|
-
}
|
|
73
|
+
};
|
|
76
74
|
|
|
77
75
|
/**
|
|
78
76
|
* Used to configure the AWS Amplify clients.
|
|
@@ -234,14 +232,12 @@ export default class AmplifyStudioClient {
|
|
|
234
232
|
const environmentName = envName || this.#envName;
|
|
235
233
|
const resolvedAppId = appId || this.#appId;
|
|
236
234
|
try {
|
|
237
|
-
await this.#amplifyUiBuilder
|
|
238
|
-
.deleteForm({ id: formId, environmentName, appId: resolvedAppId })
|
|
239
|
-
.promise();
|
|
235
|
+
await this.#amplifyUiBuilder.deleteForm({ id: formId, environmentName, appId: resolvedAppId }).promise();
|
|
240
236
|
} catch (err) {
|
|
241
237
|
printer.debug(err.toString());
|
|
242
238
|
throw err;
|
|
243
239
|
}
|
|
244
|
-
}
|
|
240
|
+
};
|
|
245
241
|
|
|
246
242
|
getModels = async (resourceName: string, envName?: string, appId?: string): Promise<string | undefined> => {
|
|
247
243
|
try {
|
|
@@ -15,7 +15,9 @@ export const run = async (context: $TSContext): Promise<void> => {
|
|
|
15
15
|
const studioClient = await AmplifyStudioClient.setClientInfo(context, sourceEnvName, appId);
|
|
16
16
|
|
|
17
17
|
const [existingComponents, existingComponentsNewEnv] = await Promise.all([
|
|
18
|
-
studioClient.listComponents(sourceEnvName),
|
|
18
|
+
studioClient.listComponents(sourceEnvName),
|
|
19
|
+
studioClient.listComponents(newEnvName),
|
|
20
|
+
]);
|
|
19
21
|
if (existingComponents.entities.length === 0) {
|
|
20
22
|
printer.debug(`${existingComponents.entities.length} components exist in source env. Skipping creation of local components.`);
|
|
21
23
|
return;
|
|
@@ -42,11 +44,7 @@ export const run = async (context: $TSContext): Promise<void> => {
|
|
|
42
44
|
modifiedAt, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
43
45
|
...componentCreateData
|
|
44
46
|
} = components[i];
|
|
45
|
-
await studioClient.createComponent(
|
|
46
|
-
componentCreateData,
|
|
47
|
-
newEnvName,
|
|
48
|
-
appId,
|
|
49
|
-
);
|
|
47
|
+
await studioClient.createComponent(componentCreateData, newEnvName, appId);
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
printer.info(
|
|
@@ -37,7 +37,7 @@ export const run = async (context: $TSContext, eventType: 'PostPush' | 'PostPull
|
|
|
37
37
|
|
|
38
38
|
const nothingWouldAutogenerate = !dataSchema || !studioClient.metadata.autoGenerateForms || !studioClient.isGraphQLSupported;
|
|
39
39
|
|
|
40
|
-
if (nothingWouldAutogenerate && [componentSchemas, themeSchemas, formSchemas].every(group => !group.entities.length)) {
|
|
40
|
+
if (nothingWouldAutogenerate && [componentSchemas, themeSchemas, formSchemas].every((group) => !group.entities.length)) {
|
|
41
41
|
printer.debug('Skipping UI component generation since none are found.');
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
@@ -55,13 +55,13 @@ export const run = async (context: $TSContext, eventType: 'PostPush' | 'PostPull
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
const successfulSchemas: StudioSchema[] = [];
|
|
58
|
-
const detachedForms: {id: string
|
|
58
|
+
const detachedForms: { id: string; name: string }[] = [];
|
|
59
59
|
let hasSuccessfulForm = false;
|
|
60
60
|
const failedResponseNames: string[] = [];
|
|
61
61
|
const modelNames = dataSchema?.models ? new Set(Object.keys(dataSchema.models)) : new Set<string>();
|
|
62
62
|
|
|
63
63
|
Object.entries(generatedResults).forEach(([key, results]) => {
|
|
64
|
-
results.forEach(result => {
|
|
64
|
+
results.forEach((result) => {
|
|
65
65
|
if (result.resultType === 'SUCCESS') {
|
|
66
66
|
successfulSchemas.push(result.schema);
|
|
67
67
|
if (key === 'form') {
|
|
@@ -74,14 +74,14 @@ export const run = async (context: $TSContext, eventType: 'PostPush' | 'PostPull
|
|
|
74
74
|
* no longer exists.
|
|
75
75
|
*/
|
|
76
76
|
if (
|
|
77
|
-
isStudioForm(failedSchema)
|
|
78
|
-
|
|
79
|
-
&&
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
isStudioForm(failedSchema) &&
|
|
78
|
+
failedSchema.id &&
|
|
79
|
+
dataSchema &&
|
|
80
|
+
eventType === 'PostPush' &&
|
|
81
|
+
isFormDetachedFromModel(failedSchema, modelNames)
|
|
82
82
|
) {
|
|
83
83
|
// Don't need to add form to failedResponseNames if it is going to be deleted
|
|
84
|
-
detachedForms.push({id: failedSchema.id, name: failedSchema.name});
|
|
84
|
+
detachedForms.push({ id: failedSchema.id, name: failedSchema.name });
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
87
|
failedResponseNames.push(result.schemaName);
|
|
@@ -100,8 +100,8 @@ export const run = async (context: $TSContext, eventType: 'PostPush' | 'PostPull
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const invalidComponentNames = [
|
|
103
|
-
...componentSchemas.entities.filter(component => !component.schemaVersion).map(component => component.name),
|
|
104
|
-
...formSchemas.entities.filter(form => !form.schemaVersion).map(form => form.name),
|
|
103
|
+
...componentSchemas.entities.filter((component) => !component.schemaVersion).map((component) => component.name),
|
|
104
|
+
...formSchemas.entities.filter((form) => !form.schemaVersion).map((form) => form.name),
|
|
105
105
|
];
|
|
106
106
|
if (invalidComponentNames.length) {
|
|
107
107
|
printer.warn(
|
|
@@ -26,9 +26,7 @@ import {
|
|
|
26
26
|
ReactThemeStudioTemplateRendererOptions,
|
|
27
27
|
} from '@aws-amplify/codegen-ui-react';
|
|
28
28
|
import { printer } from 'amplify-prompts';
|
|
29
|
-
import {
|
|
30
|
-
$TSContext, AmplifyCategories, AmplifySupportedService, stateManager,
|
|
31
|
-
} from 'amplify-cli-core';
|
|
29
|
+
import { $TSContext, AmplifyCategories, AmplifySupportedService, stateManager } from 'amplify-cli-core';
|
|
32
30
|
import { getUiBuilderComponentsPath } from './getUiBuilderComponentsPath';
|
|
33
31
|
import { AmplifyStudioClient } from '../../clients';
|
|
34
32
|
|
|
@@ -68,7 +66,8 @@ export const createUiBuilderTheme = (
|
|
|
68
66
|
): StudioTheme => {
|
|
69
67
|
const uiBuilderComponentsPath = getUiBuilderComponentsPath(context);
|
|
70
68
|
const rendererFactory = new StudioTemplateRendererFactory(
|
|
71
|
-
(component: StudioTheme) =>
|
|
69
|
+
(component: StudioTheme) =>
|
|
70
|
+
new ReactThemeStudioTemplateRenderer(component, config, options) as unknown as StudioTemplateRenderer<
|
|
72
71
|
unknown,
|
|
73
72
|
StudioTheme,
|
|
74
73
|
FrameworkOutputManager<unknown>,
|
|
@@ -99,7 +98,8 @@ export const createUiBuilderTheme = (
|
|
|
99
98
|
export const createUiBuilderForm = (context: $TSContext, schema: StudioForm, dataSchema?: GenericDataSchema): StudioForm => {
|
|
100
99
|
const uiBuilderComponentsPath = getUiBuilderComponentsPath(context);
|
|
101
100
|
const rendererFactory = new StudioTemplateRendererFactory(
|
|
102
|
-
(form: StudioForm) =>
|
|
101
|
+
(form: StudioForm) =>
|
|
102
|
+
new AmplifyFormRenderer(form, dataSchema, config) as unknown as StudioTemplateRenderer<
|
|
103
103
|
unknown,
|
|
104
104
|
StudioForm,
|
|
105
105
|
FrameworkOutputManager<unknown>,
|
|
@@ -130,7 +130,8 @@ export const createUiBuilderForm = (context: $TSContext, schema: StudioForm, dat
|
|
|
130
130
|
export const generateAmplifyUiBuilderIndexFile = (context: $TSContext, schemas: StudioSchema[]): void => {
|
|
131
131
|
const uiBuilderComponentsPath = getUiBuilderComponentsPath(context);
|
|
132
132
|
const rendererFactory = new StudioTemplateRendererFactory(
|
|
133
|
-
(schema: StudioSchema[]) =>
|
|
133
|
+
(schema: StudioSchema[]) =>
|
|
134
|
+
new ReactIndexStudioTemplateRenderer(schema, config) as unknown as StudioTemplateRenderer<
|
|
134
135
|
unknown,
|
|
135
136
|
StudioSchema[],
|
|
136
137
|
FrameworkOutputManager<unknown>,
|
|
@@ -145,7 +146,7 @@ export const generateAmplifyUiBuilderIndexFile = (context: $TSContext, schemas:
|
|
|
145
146
|
});
|
|
146
147
|
|
|
147
148
|
try {
|
|
148
|
-
if(schemas.length) {
|
|
149
|
+
if (schemas.length) {
|
|
149
150
|
rendererManager.renderSchemaToTemplate(schemas);
|
|
150
151
|
}
|
|
151
152
|
} catch (e) {
|
|
@@ -166,7 +167,7 @@ type UtilFileChecks = {
|
|
|
166
167
|
export const generateAmplifyUiBuilderUtilFile = (context: $TSContext, { hasForms, hasViews }: UtilFileChecks): void => {
|
|
167
168
|
const uiBuilderComponentsPath = getUiBuilderComponentsPath(context);
|
|
168
169
|
const rendererFactory = new StudioTemplateRendererFactory(
|
|
169
|
-
(utils: UtilTemplateType[]) =>
|
|
170
|
+
(utils: UtilTemplateType[]) => new ReactUtilsStudioTemplateRenderer(utils, config),
|
|
170
171
|
);
|
|
171
172
|
|
|
172
173
|
const outputPathDir = uiBuilderComponentsPath;
|
|
@@ -202,9 +203,7 @@ export const generateAmplifyUiBuilderUtilFile = (context: $TSContext, { hasForms
|
|
|
202
203
|
* If models are available, they will be populated in the models field of the returned object.
|
|
203
204
|
* If they're not available, it will return undefined
|
|
204
205
|
*/
|
|
205
|
-
export const getAmplifyDataSchema = async (
|
|
206
|
-
studioClient: AmplifyStudioClient,
|
|
207
|
-
): Promise<GenericDataSchema | undefined> => {
|
|
206
|
+
export const getAmplifyDataSchema = async (studioClient: AmplifyStudioClient): Promise<GenericDataSchema | undefined> => {
|
|
208
207
|
if (!studioClient.isGraphQLSupported) {
|
|
209
208
|
return undefined;
|
|
210
209
|
}
|
|
@@ -231,8 +230,8 @@ export const getAmplifyDataSchema = async (
|
|
|
231
230
|
/**
|
|
232
231
|
* generates base create/update froms from names
|
|
233
232
|
*/
|
|
234
|
-
export const generateBaseForms = (modelMap: {[model: string]: Set<'create' | 'update'>}): StudioForm[] => {
|
|
235
|
-
const getSchema = (name: string, type: 'create' | 'update')
|
|
233
|
+
export const generateBaseForms = (modelMap: { [model: string]: Set<'create' | 'update'> }): StudioForm[] => {
|
|
234
|
+
const getSchema = (name: string, type: 'create' | 'update'): StudioForm => ({
|
|
236
235
|
name: `${name}${type === 'create' ? 'CreateForm' : 'UpdateForm'}`,
|
|
237
236
|
formActionType: type,
|
|
238
237
|
dataType: { dataSourceType: 'DataStore', dataTypeName: name },
|
|
@@ -242,10 +241,10 @@ export const generateBaseForms = (modelMap: {[model: string]: Set<'create' | 'up
|
|
|
242
241
|
cta: {},
|
|
243
242
|
});
|
|
244
243
|
|
|
245
|
-
const schemas
|
|
244
|
+
const schemas: StudioForm[] = [];
|
|
246
245
|
|
|
247
246
|
Object.entries(modelMap).forEach(([name, set]) => {
|
|
248
|
-
set.forEach(type => schemas.push(getSchema(name, type)));
|
|
247
|
+
set.forEach((type) => schemas.push(getSchema(name, type)));
|
|
249
248
|
});
|
|
250
249
|
return schemas;
|
|
251
250
|
};
|
|
@@ -25,7 +25,7 @@ export const isFormSchemaCustomized = (formSchema: StudioForm | Form): boolean =
|
|
|
25
25
|
|
|
26
26
|
// Check style
|
|
27
27
|
// If not empty, at least one style must be defined
|
|
28
|
-
return Object.values(style).some(styleConfig => styleConfig !== undefined);
|
|
28
|
+
return Object.values(style).some((styleConfig) => styleConfig !== undefined);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -36,19 +36,19 @@ export const isStudioForm = (schema: StudioSchema | undefined): schema is Studio
|
|
|
36
36
|
return 'formActionType' in schema;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
export const deleteDetachedForms = async (detachedForms: {id: string
|
|
40
|
-
const deleteForm = async ({id, name}: {id: string
|
|
39
|
+
export const deleteDetachedForms = async (detachedForms: { id: string; name: string }[], studioClient: AmplifyStudioClient) => {
|
|
40
|
+
const deleteForm = async ({ id, name }: { id: string; name: string }) => {
|
|
41
41
|
try {
|
|
42
42
|
// Try to delete the form but don't stop any other operations if it fails
|
|
43
43
|
await studioClient.deleteForm(id);
|
|
44
|
-
return {status: 'SUCCESS', message: `Deleted detached form ${name}`};
|
|
44
|
+
return { status: 'SUCCESS', message: `Deleted detached form ${name}` };
|
|
45
45
|
} catch (error) {
|
|
46
|
-
return {status: 'FAIL', message: `Failed to delete detached form ${name}`}
|
|
46
|
+
return { status: 'FAIL', message: `Failed to delete detached form ${name}` };
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
for await (const status of asyncPool(5, detachedForms, deleteForm)) {
|
|
50
50
|
printer.debug(status.message);
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/* eslint-disable spellcheck/spell-checker */
|
|
2
|
-
import {
|
|
3
|
-
FeatureFlags, pathManager, stateManager,
|
|
4
|
-
} from 'amplify-cli-core';
|
|
2
|
+
import { FeatureFlags, pathManager, stateManager } from 'amplify-cli-core';
|
|
5
3
|
import { printer } from 'amplify-prompts';
|
|
6
4
|
|
|
7
5
|
// This is copy-pasta from the category api until they can expose the method to plugins
|
|
@@ -9,7 +7,8 @@ import { printer } from 'amplify-prompts';
|
|
|
9
7
|
/**
|
|
10
8
|
* Shorthand for Feature flag retrieval.
|
|
11
9
|
*/
|
|
12
|
-
const useExperimentalPipelinedTransformerFF = (): boolean =>
|
|
10
|
+
const useExperimentalPipelinedTransformerFF = (): boolean =>
|
|
11
|
+
FeatureFlags.getBoolean('graphQLTransformer.useExperimentalPipelinedTransformer');
|
|
13
12
|
const transformerVersionFF = (): number => FeatureFlags.getNumber('graphQLTransformer.transformerVersion');
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
pathManager, JSONUtilities, $TSContext, $TSAny,
|
|
3
|
-
} from 'amplify-cli-core';
|
|
1
|
+
import { pathManager, JSONUtilities, $TSContext, $TSAny } from 'amplify-cli-core';
|
|
4
2
|
import { printer } from 'amplify-prompts';
|
|
5
3
|
import fs from 'fs-extra';
|
|
6
4
|
import path from 'path';
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { printer } from 'amplify-prompts';
|
|
2
2
|
import { $TSContext } from 'amplify-cli-core';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
} from '@aws-amplify/codegen-ui';
|
|
6
|
-
import {
|
|
7
|
-
createUiBuilderComponent,
|
|
8
|
-
createUiBuilderForm,
|
|
9
|
-
createUiBuilderTheme,
|
|
10
|
-
generateBaseForms,
|
|
11
|
-
} from './codegenResources';
|
|
3
|
+
import { StudioComponent, StudioTheme, GenericDataSchema, StudioForm, StudioSchema, checkIsSupportedAsForm } from '@aws-amplify/codegen-ui';
|
|
4
|
+
import { createUiBuilderComponent, createUiBuilderForm, createUiBuilderTheme, generateBaseForms } from './codegenResources';
|
|
12
5
|
import { getUiBuilderComponentsPath } from './getUiBuilderComponentsPath';
|
|
13
6
|
|
|
14
7
|
type CodegenResponse<T extends StudioSchema> =
|
|
@@ -34,7 +27,7 @@ export const generateUiBuilderComponents = (
|
|
|
34
27
|
componentSchemas: any[], // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
35
28
|
dataSchema?: GenericDataSchema,
|
|
36
29
|
): CodegenResponse<StudioComponent>[] => {
|
|
37
|
-
const componentResults = componentSchemas.map<CodegenResponse<StudioComponent>>(schema => {
|
|
30
|
+
const componentResults = componentSchemas.map<CodegenResponse<StudioComponent>>((schema) => {
|
|
38
31
|
try {
|
|
39
32
|
const component = createUiBuilderComponent(context, schema, dataSchema);
|
|
40
33
|
return { resultType: 'SUCCESS', schema: component };
|
|
@@ -46,7 +39,7 @@ export const generateUiBuilderComponents = (
|
|
|
46
39
|
});
|
|
47
40
|
|
|
48
41
|
printer.debug(
|
|
49
|
-
`Generated ${componentResults.filter(result => result.resultType === 'SUCCESS').length} components in ${getUiBuilderComponentsPath(
|
|
42
|
+
`Generated ${componentResults.filter((result) => result.resultType === 'SUCCESS').length} components in ${getUiBuilderComponentsPath(
|
|
50
43
|
context,
|
|
51
44
|
)}`,
|
|
52
45
|
);
|
|
@@ -61,7 +54,7 @@ export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]
|
|
|
61
54
|
if (themeSchemas.length === 0) {
|
|
62
55
|
return [generateDefaultTheme(context)];
|
|
63
56
|
}
|
|
64
|
-
const themeResults = themeSchemas.map<CodegenResponse<StudioTheme>>(schema => {
|
|
57
|
+
const themeResults = themeSchemas.map<CodegenResponse<StudioTheme>>((schema) => {
|
|
65
58
|
try {
|
|
66
59
|
const theme = createUiBuilderTheme(context, schema);
|
|
67
60
|
return { resultType: 'SUCCESS', schema: theme };
|
|
@@ -73,7 +66,7 @@ export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]
|
|
|
73
66
|
});
|
|
74
67
|
|
|
75
68
|
printer.debug(
|
|
76
|
-
`Generated ${themeResults.filter(result => result.resultType === 'SUCCESS').length} themes in ${getUiBuilderComponentsPath(context)}`,
|
|
69
|
+
`Generated ${themeResults.filter((result) => result.resultType === 'SUCCESS').length} themes in ${getUiBuilderComponentsPath(context)}`,
|
|
77
70
|
);
|
|
78
71
|
return themeResults;
|
|
79
72
|
};
|
|
@@ -84,9 +77,7 @@ export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]
|
|
|
84
77
|
const generateDefaultTheme = (context: $TSContext): CodegenResponse<StudioTheme> => {
|
|
85
78
|
try {
|
|
86
79
|
const theme = createUiBuilderTheme(context, { name: 'studioTheme', values: [] }, { renderDefaultTheme: true });
|
|
87
|
-
printer.debug(
|
|
88
|
-
`Generated default theme in ${getUiBuilderComponentsPath(context)}`,
|
|
89
|
-
);
|
|
80
|
+
printer.debug(`Generated default theme in ${getUiBuilderComponentsPath(context)}`);
|
|
90
81
|
return { resultType: 'SUCCESS', schema: theme };
|
|
91
82
|
} catch (e) {
|
|
92
83
|
printer.debug(`Failure caught rendering default theme`);
|
|
@@ -121,7 +112,10 @@ export const generateUiBuilderForms = (
|
|
|
121
112
|
printer.debug(`Failure caught processing ${schema.name}`);
|
|
122
113
|
printer.debug(e);
|
|
123
114
|
return {
|
|
124
|
-
resultType: 'FAILURE',
|
|
115
|
+
resultType: 'FAILURE',
|
|
116
|
+
schemaName: schema.name,
|
|
117
|
+
schema,
|
|
118
|
+
error: e,
|
|
125
119
|
};
|
|
126
120
|
}
|
|
127
121
|
};
|
|
@@ -136,7 +130,7 @@ export const generateUiBuilderForms = (
|
|
|
136
130
|
formResults.push(...generateBaseForms(modelMap).map(codegenForm));
|
|
137
131
|
|
|
138
132
|
printer.debug(
|
|
139
|
-
`Generated ${formResults.filter(result => result.resultType === 'SUCCESS').length} forms in ${getUiBuilderComponentsPath(context)}`,
|
|
133
|
+
`Generated ${formResults.filter((result) => result.resultType === 'SUCCESS').length} forms in ${getUiBuilderComponentsPath(context)}`,
|
|
140
134
|
);
|
|
141
135
|
return formResults;
|
|
142
136
|
};
|