@aws-amplify/amplify-util-uibuilder 1.6.8 → 1.6.9-mxp.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 +12 -0
- package/amplify-plugin.json +2 -11
- package/lib/clients/amplify-studio-client.d.ts +8 -8
- package/lib/clients/amplify-studio-client.d.ts.map +1 -1
- package/lib/clients/amplify-studio-client.js +19 -21
- 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 +10 -10
- package/lib/commands/generateComponents.js.map +1 -1
- package/lib/commands/utils/codegenResources.d.ts +4 -4
- 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/environmentHelpers.d.ts +2 -2
- package/lib/commands/utils/environmentHelpers.d.ts.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/index.js +5 -1
- package/lib/commands/utils/index.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 +3 -3
- 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/commands/version.js +7 -2
- package/lib/commands/version.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 +6 -6
- 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__/notifyMissingPackages.test.ts +5 -4
- package/src/__tests__/package.json +2 -2
- package/src/__tests__/prePushHandler.test.ts +7 -7
- 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 +12 -12
- 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/event-handlers/handle-PrePush.ts +1 -1
- package/src/utils/prePushHandler.ts +20 -16
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prePushHandler.d.ts","sourceRoot":"","sources":["../../src/utils/prePushHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"prePushHandler.d.ts","sourceRoot":"","sources":["../../src/utils/prePushHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAc9C,eAAO,MAAM,cAAc,YAAmB,UAAU,KAAG,QAAQ,IAAI,CAmBtE,CAAC"}
|
|
@@ -9,10 +9,7 @@ const prePushHandler = async (context) => {
|
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const studioClient = await clients_1.AmplifyStudioClient.setClientInfo(context);
|
|
12
|
-
const [formSchemas, localSchema] = await Promise.all([
|
|
13
|
-
studioClient.listForms(),
|
|
14
|
-
context.amplify.invokePluginMethod(context, 'codegen', undefined, 'getModelIntrospection', [context]),
|
|
15
|
-
]);
|
|
12
|
+
const [formSchemas, localSchema] = await Promise.all([studioClient.listForms(), context.amplify.invokePluginMethod(context, 'codegen', undefined, 'getModelIntrospection', [context])]);
|
|
16
13
|
if (!localSchema) {
|
|
17
14
|
amplify_prompts_1.printer.debug('Local schema not found');
|
|
18
15
|
return;
|
|
@@ -23,7 +20,7 @@ exports.prePushHandler = prePushHandler;
|
|
|
23
20
|
const printDetachedFormsWarning = (formSchemas, localSchema) => {
|
|
24
21
|
const modelNames = new Set(Object.keys(localSchema.models));
|
|
25
22
|
const detachedCustomForms = [];
|
|
26
|
-
formSchemas.entities.forEach(form => {
|
|
23
|
+
formSchemas.entities.forEach((form) => {
|
|
27
24
|
if ((0, utils_1.isFormDetachedFromModel)(form, modelNames) && (0, utils_1.isFormSchemaCustomized)(form)) {
|
|
28
25
|
detachedCustomForms.push(form.name);
|
|
29
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prePushHandler.js","sourceRoot":"","sources":["../../src/utils/prePushHandler.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"prePushHandler.js","sourceRoot":"","sources":["../../src/utils/prePushHandler.ts"],"names":[],"mappings":";;;AACA,qDAA0C;AAE1C,wCAAiD;AACjD,6CAA4G;AAUrG,MAAM,cAAc,GAAG,KAAK,EAAE,OAAmB,EAAiB,EAAE;IACzE,IAAI,CAAC,CAAC,MAAM,IAAA,8BAAsB,EAAC,OAAO,CAAC,CAAC,EAAE;QAC5C,OAAO;KACR;IACD,MAAM,YAAY,GAAG,MAAM,6BAAmB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtE,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAOlD,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAErI,IAAI,CAAC,WAAW,EAAE;QAChB,yBAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,OAAO;KACR;IACD,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AACtD,CAAC,CAAC;AAnBW,QAAA,cAAc,kBAmBzB;AAEF,MAAM,yBAAyB,GAAG,CAAC,WAAkD,EAAE,WAAmB,EAAQ,EAAE;IAClH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,mBAAmB,GAAa,EAAE,CAAC;IAEzC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAGpC,IAAI,IAAA,+BAAuB,EAAC,IAAI,EAAE,UAAU,CAAC,IAAI,IAAA,8BAAsB,EAAC,IAAI,CAAC,EAAE;YAC7E,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACrC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE;QAClC,yBAAO,CAAC,IAAI,CACV,qBACE,mBAAmB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC1C,mFAAmF,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpH,CAAC;KACH;AACH,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-amplify/amplify-util-uibuilder",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.9-mxp.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@aws-amplify/codegen-ui": "2.
|
|
18
|
-
"@aws-amplify/codegen-ui-react": "2.
|
|
19
|
-
"amplify-cli-core": "3.
|
|
20
|
-
"amplify-prompts": "2.6.
|
|
17
|
+
"@aws-amplify/codegen-ui": "2.8.0",
|
|
18
|
+
"@aws-amplify/codegen-ui-react": "2.8.0",
|
|
19
|
+
"amplify-cli-core": "3.7.0-mxp.0",
|
|
20
|
+
"amplify-prompts": "2.6.4-mxp.0",
|
|
21
21
|
"aws-sdk": "^2.1233.0",
|
|
22
22
|
"fs-extra": "^8.1.0",
|
|
23
23
|
"ora": "^4.0.3",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"usePathForSuiteName": "true",
|
|
72
72
|
"addFileAttribute": "true"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "365285713b1fbea6891ae6ce792142c9ebc7cc22"
|
|
75
75
|
}
|
|
@@ -72,10 +72,12 @@ describe('can create a ui builder component', () => {
|
|
|
72
72
|
it('does not call renderSchemaToTemplate for index file if no schema', () => {
|
|
73
73
|
generateAmplifyUiBuilderIndexFile(context, []);
|
|
74
74
|
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).not.toBeCalled();
|
|
75
|
-
})
|
|
75
|
+
});
|
|
76
76
|
it('calls the renderManager for utils file w/ validation, formatter, and fetchByPath helpers if there is a form', () => {
|
|
77
77
|
generateAmplifyUiBuilderUtilFile(context, { hasForms: true, hasViews: false });
|
|
78
|
-
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).toBeCalledWith(
|
|
78
|
+
expect(new codegenMock.StudioTemplateRendererManager().renderSchemaToTemplate).toBeCalledWith(
|
|
79
|
+
expect.arrayContaining(['validation', 'formatter', 'fetchByPath']),
|
|
80
|
+
);
|
|
79
81
|
});
|
|
80
82
|
it('calls the renderManager for utils file w/ formatter helper if there is a view', () => {
|
|
81
83
|
generateAmplifyUiBuilderUtilFile(context, { hasForms: false, hasViews: true });
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
// @aws-amplify/codegen-ui is in project dependencies
|
|
2
2
|
import { StudioSchema } from '@aws-amplify/codegen-ui'; // eslint-disable-line import/no-extraneous-dependencies
|
|
3
|
-
import {AmplifyStudioClient} from '../clients'; // eslint-disable-line import/no-extraneous-dependencies
|
|
4
|
-
import {
|
|
5
|
-
isFormDetachedFromModel, isFormSchemaCustomized, isStudioForm, deleteDetachedForms
|
|
6
|
-
} from '../commands/utils';
|
|
3
|
+
import { AmplifyStudioClient } from '../clients'; // eslint-disable-line import/no-extraneous-dependencies
|
|
4
|
+
import { isFormDetachedFromModel, isFormSchemaCustomized, isStudioForm, deleteDetachedForms } from '../commands/utils';
|
|
7
5
|
|
|
8
6
|
const amplifyStudioClientMock = AmplifyStudioClient as any;
|
|
9
7
|
|
|
@@ -38,7 +36,6 @@ const formWithFields: StudioSchema = {
|
|
|
38
36
|
};
|
|
39
37
|
|
|
40
38
|
describe('detachedFormCleanup', () => {
|
|
41
|
-
|
|
42
39
|
it('isStudioForm should return true', () => {
|
|
43
40
|
expect(isStudioForm(formWithNoCustomization)).toBe(true);
|
|
44
41
|
});
|
|
@@ -71,7 +68,7 @@ describe('detachedFormCleanup', () => {
|
|
|
71
68
|
it('should delete detached forms', async () => {
|
|
72
69
|
const mockedDeleteForm = jest.fn().mockReturnValue(undefined);
|
|
73
70
|
amplifyStudioClientMock.deleteForm = mockedDeleteForm;
|
|
74
|
-
await deleteDetachedForms([{id: '12345', name: 'BlogCreateForm'}], amplifyStudioClientMock);
|
|
71
|
+
await deleteDetachedForms([{ id: '12345', name: 'BlogCreateForm' }], amplifyStudioClientMock);
|
|
75
72
|
expect(mockedDeleteForm).toBeCalledTimes(1);
|
|
76
73
|
expect(mockedDeleteForm).toHaveBeenCalledWith('12345');
|
|
77
74
|
});
|
|
@@ -9,7 +9,7 @@ const utilsMock = utils as any;
|
|
|
9
9
|
|
|
10
10
|
utilsMock.shouldRenderComponents = jest.fn().mockReturnValue(true);
|
|
11
11
|
utilsMock.notifyMissingPackages = jest.fn().mockReturnValue(true);
|
|
12
|
-
utilsMock.getAmplifyDataSchema = jest.fn().mockReturnValue(
|
|
12
|
+
utilsMock.getAmplifyDataSchema = jest.fn().mockReturnValue({});
|
|
13
13
|
|
|
14
14
|
jest.mock('../commands/utils/featureFlags', () => ({
|
|
15
15
|
getTransformerVersion: jest.fn().mockReturnValue(2),
|
|
@@ -33,7 +33,8 @@ const mockedFeatureFlags = mocked(FeatureFlags);
|
|
|
33
33
|
|
|
34
34
|
const getMockedSchema = jest.fn(
|
|
35
35
|
// eslint-disable-next-line no-useless-escape, spellcheck/spell-checker
|
|
36
|
-
() =>
|
|
36
|
+
() =>
|
|
37
|
+
`export const schema = {\n \"models\": {\n \"Blog\": {\n \"name\": \"Blog\",\n \"fields\": {\n \"id\": {\n \"name\": \"id\",\n \"isArray\": false,\n \"type\": \"ID\",\n \"isRequired\": true,\n \"attributes\": []\n },\n \"title\": {\n \"name\": \"title\",\n \"isArray\": false,\n \"type\": \"String\",\n \"isRequired\": false,\n \"attributes\": []\n },\n \"content\": {\n \"name\": \"content\",\n \"isArray\": false,\n \"type\": \"String\",\n \"isRequired\": false,\n \"attributes\": []\n },\n \"status\": {\n \"name\": \"status\",\n \"isArray\": false,\n \"type\": {\n \"enum\": \"Status\"\n },\n \"isRequired\": false,\n \"attributes\": []\n },\n \"createdAt\": {\n \"name\": \"createdAt\",\n \"isArray\": false,\n \"type\": \"AWSDateTime\",\n \"isRequired\": false,\n \"attributes\": [],\n \"isReadOnly\": true\n },\n \"updatedAt\": {\n \"name\": \"updatedAt\",\n \"isArray\": false,\n \"type\": \"AWSDateTime\",\n \"isRequired\": false,\n \"attributes\": [],\n \"isReadOnly\": true\n }\n },\n \"syncable\": true,\n \"pluralName\": \"Blogs\",\n \"attributes\": [\n {\n \"type\": \"model\",\n \"properties\": {}\n },\n {\n \"type\": \"auth\",\n \"properties\": {\n \"rules\": [\n {\n \"allow\": \"public\",\n \"operations\": [\n \"create\",\n \"update\",\n \"delete\",\n \"read\"\n ]\n }\n ]\n }\n }\n ]\n }\n },\n \"enums\": {\n \"Status\": {\n \"name\": \"Status\",\n \"values\": [\n \"ENABLED\",\n \"DISABLED\"\n ]\n }\n },\n \"nonModels\": {},\n \"version\": \"demo\"\n};`,
|
|
37
38
|
);
|
|
38
39
|
|
|
39
40
|
describe('should sync amplify backend models', () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as printerDependency from 'amplify-prompts';
|
|
2
2
|
import * as JSONUtilitiesDependency from 'amplify-cli-core';
|
|
3
3
|
import { notifyMissingPackages } from '../commands/utils/notifyMissingPackages';
|
|
4
|
+
import { $TSContext } from 'amplify-cli-core';
|
|
4
5
|
jest.mock('amplify-prompts');
|
|
5
6
|
jest.mock('amplify-cli-core');
|
|
6
7
|
printerDependency.printer.info = jest.fn();
|
|
@@ -23,7 +24,7 @@ describe('should notify when packages are missing', () => {
|
|
|
23
24
|
},
|
|
24
25
|
},
|
|
25
26
|
};
|
|
26
|
-
notifyMissingPackages(context as
|
|
27
|
+
notifyMissingPackages(context as unknown as $TSContext);
|
|
27
28
|
expect(printerDependency.printer.debug).toBeCalledTimes(1);
|
|
28
29
|
});
|
|
29
30
|
|
|
@@ -39,7 +40,7 @@ describe('should notify when packages are missing', () => {
|
|
|
39
40
|
},
|
|
40
41
|
},
|
|
41
42
|
};
|
|
42
|
-
notifyMissingPackages(context as
|
|
43
|
+
notifyMissingPackages(context as unknown as $TSContext);
|
|
43
44
|
expect(printerDependency.printer.debug).toBeCalledTimes(1);
|
|
44
45
|
});
|
|
45
46
|
|
|
@@ -51,7 +52,7 @@ describe('should notify when packages are missing', () => {
|
|
|
51
52
|
},
|
|
52
53
|
},
|
|
53
54
|
};
|
|
54
|
-
notifyMissingPackages(context as
|
|
55
|
+
notifyMissingPackages(context as unknown as $TSContext);
|
|
55
56
|
expect(printerDependency.printer.warn).toBeCalledTimes(2);
|
|
56
57
|
});
|
|
57
58
|
|
|
@@ -67,7 +68,7 @@ describe('should notify when packages are missing', () => {
|
|
|
67
68
|
},
|
|
68
69
|
},
|
|
69
70
|
};
|
|
70
|
-
notifyMissingPackages(context as
|
|
71
|
+
notifyMissingPackages(context as unknown as $TSContext);
|
|
71
72
|
expect(printerDependency.printer.warn).toBeCalledTimes(1);
|
|
72
73
|
});
|
|
73
74
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
}
|
|
2
|
+
"version": "1.0.0"
|
|
3
|
+
}
|
|
@@ -24,7 +24,7 @@ describe('handlePrePush', () => {
|
|
|
24
24
|
beforeEach(() => {
|
|
25
25
|
context = {
|
|
26
26
|
amplify: {
|
|
27
|
-
invokePluginMethod: ()
|
|
27
|
+
invokePluginMethod: jest.fn().mockResolvedValue({ models: { Comment: {} } }),
|
|
28
28
|
},
|
|
29
29
|
input: {
|
|
30
30
|
options: {
|
|
@@ -87,17 +87,17 @@ describe('handlePrePush', () => {
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('runs handlePrePush', async () => {
|
|
90
|
-
utilsMock.isFormDetachedFromModel = jest.fn().
|
|
91
|
-
utilsMock.isFormSchemaCustomized = jest.fn().
|
|
90
|
+
utilsMock.isFormDetachedFromModel = jest.fn().mockReturnValue(true);
|
|
91
|
+
utilsMock.isFormSchemaCustomized = jest.fn().mockReturnValue(true);
|
|
92
92
|
const spy = jest.spyOn(printer, 'warn');
|
|
93
93
|
await prePushHandler(context);
|
|
94
|
-
expect(spy).toHaveBeenCalledWith(
|
|
94
|
+
expect(spy).toHaveBeenCalledWith(
|
|
95
|
+
'The following forms will no longer be available because the connected data model no longer exists: BlogCreateForm, BlogUpdateForm',
|
|
96
|
+
);
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
it('runs handlePrePush without schema', async () => {
|
|
98
|
-
context.amplify.invokePluginMethod = jest.fn()
|
|
99
|
-
.mockImplementation(() => ({ models: { Comment: {} } }))
|
|
100
|
-
.mockImplementation(() => (null));
|
|
100
|
+
context.amplify.invokePluginMethod = jest.fn().mockResolvedValue(null);
|
|
101
101
|
const spy = jest.spyOn(printer, 'debug');
|
|
102
102
|
await prePushHandler(context);
|
|
103
103
|
expect(spy).toHaveBeenCalledWith('Local schema not found');
|
|
@@ -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(
|
|
@@ -113,7 +113,7 @@ export const run = async (context: $TSContext, eventType: 'PostPush' | 'PostPull
|
|
|
113
113
|
|
|
114
114
|
notifyMissingPackages(context);
|
|
115
115
|
|
|
116
|
-
deleteDetachedForms(detachedForms, studioClient);
|
|
116
|
+
await deleteDetachedForms(detachedForms, studioClient);
|
|
117
117
|
} catch (e) {
|
|
118
118
|
printer.debug(e);
|
|
119
119
|
spinner.fail('Failed to sync UI components');
|