@aws-amplify/amplify-util-uibuilder 1.5.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/amplify-plugin.json +10 -3
  3. package/lib/clients/amplify-studio-client.d.ts +13 -2
  4. package/lib/clients/amplify-studio-client.d.ts.map +1 -1
  5. package/lib/clients/amplify-studio-client.js +85 -17
  6. package/lib/clients/amplify-studio-client.js.map +1 -1
  7. package/lib/commands/generateComponents.d.ts.map +1 -1
  8. package/lib/commands/generateComponents.js +33 -15
  9. package/lib/commands/generateComponents.js.map +1 -1
  10. package/lib/commands/help.d.ts +1 -1
  11. package/lib/commands/help.d.ts.map +1 -1
  12. package/lib/commands/help.js +2 -2
  13. package/lib/commands/help.js.map +1 -1
  14. package/lib/commands/utils/codegenResources.d.ts +14 -3
  15. package/lib/commands/utils/codegenResources.d.ts.map +1 -1
  16. package/lib/commands/utils/codegenResources.js +72 -5
  17. package/lib/commands/utils/codegenResources.js.map +1 -1
  18. package/lib/commands/utils/featureFlags.d.ts +2 -0
  19. package/lib/commands/utils/featureFlags.d.ts.map +1 -0
  20. package/lib/commands/utils/featureFlags.js +35 -0
  21. package/lib/commands/utils/featureFlags.js.map +1 -0
  22. package/lib/commands/utils/getUiBuilderComponentsPath.d.ts.map +1 -1
  23. package/lib/commands/utils/getUiBuilderComponentsPath.js.map +1 -1
  24. package/lib/commands/utils/shouldRenderComponents.d.ts +1 -1
  25. package/lib/commands/utils/shouldRenderComponents.d.ts.map +1 -1
  26. package/lib/commands/utils/shouldRenderComponents.js +14 -8
  27. package/lib/commands/utils/shouldRenderComponents.js.map +1 -1
  28. package/lib/commands/utils/syncAmplifyUiBuilderComponents.d.ts +12 -20
  29. package/lib/commands/utils/syncAmplifyUiBuilderComponents.d.ts.map +1 -1
  30. package/lib/commands/utils/syncAmplifyUiBuilderComponents.js +51 -3
  31. package/lib/commands/utils/syncAmplifyUiBuilderComponents.js.map +1 -1
  32. package/lib/commands/version.d.ts +1 -1
  33. package/lib/commands/version.d.ts.map +1 -1
  34. package/lib/commands/version.js +2 -2
  35. package/lib/commands/version.js.map +1 -1
  36. package/lib/event-handlers/handle-PostEnvAdd.d.ts +1 -1
  37. package/lib/event-handlers/handle-PostEnvAdd.d.ts.map +1 -1
  38. package/lib/event-handlers/handle-PostEnvAdd.js +4 -6
  39. package/lib/event-handlers/handle-PostEnvAdd.js.map +1 -1
  40. package/lib/event-handlers/handle-PostPull.d.ts +1 -1
  41. package/lib/event-handlers/handle-PostPull.d.ts.map +1 -1
  42. package/lib/event-handlers/handle-PostPull.js +4 -3
  43. package/lib/event-handlers/handle-PostPull.js.map +1 -1
  44. package/lib/event-handlers/handle-PostPush.d.ts +3 -0
  45. package/lib/event-handlers/handle-PostPush.d.ts.map +1 -0
  46. package/lib/event-handlers/handle-PostPush.js +15 -0
  47. package/lib/event-handlers/handle-PostPush.js.map +1 -0
  48. package/package.json +8 -7
  49. package/src/__tests__/cloneComponentsFromEnv.test.ts +17 -6
  50. package/src/__tests__/createUiBuilderComponent.test.ts +26 -3
  51. package/src/__tests__/generateComponents.test.ts +44 -15
  52. package/src/__tests__/getAmplifyDataSchema.test.ts +51 -19
  53. package/src/__tests__/shouldRenderComponents.test.ts +51 -4
  54. package/src/__tests__/syncAmplifyUiComponents.test.ts +126 -8
  55. package/src/__tests__/utils.ts +70 -0
  56. package/src/clients/amplify-studio-client.ts +157 -69
  57. package/src/commands/generateComponents.ts +43 -16
  58. package/src/commands/help.ts +5 -2
  59. package/src/commands/utils/codegenResources.ts +115 -6
  60. package/src/commands/utils/featureFlags.ts +62 -0
  61. package/src/commands/utils/getUiBuilderComponentsPath.ts +7 -2
  62. package/src/commands/utils/shouldRenderComponents.ts +20 -8
  63. package/src/commands/utils/syncAmplifyUiBuilderComponents.ts +96 -29
  64. package/src/commands/version.ts +5 -2
  65. package/src/event-handlers/handle-PostEnvAdd.ts +8 -6
  66. package/src/event-handlers/handle-PostPull.ts +7 -3
  67. package/src/event-handlers/handle-PostPush.ts +15 -0
  68. package/tsconfig.tsbuildinfo +1 -1
  69. package/src/__tests__/handleEvents.test.ts +0 -21
@@ -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
- export async function shouldRenderComponents(context: $TSContext) {
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.exeInfo.projectConfig['javascript'].framework !== 'react') {
29
- printer.debug('Not pulling components because this project is not configured with the "react" framework');
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
+ };
@@ -1,30 +1,43 @@
1
1
  import { printer } from 'amplify-prompts';
2
2
  import { $TSContext } from 'amplify-cli-core';
3
3
  import {
4
- StudioComponent, StudioTheme, GenericDataSchema,
4
+ StudioComponent, StudioTheme, GenericDataSchema, StudioForm, StudioSchema, checkIsSupportedAsForm,
5
5
  } from '@aws-amplify/codegen-ui';
6
- import { createUiBuilderComponent, createUiBuilderTheme } from './codegenResources';
6
+ import {
7
+ createUiBuilderComponent,
8
+ createUiBuilderForm,
9
+ createUiBuilderTheme,
10
+ generateBaseForms,
11
+ } from './codegenResources';
7
12
  import { getUiBuilderComponentsPath } from './getUiBuilderComponentsPath';
8
13
 
14
+ type CodegenResponse<T extends StudioSchema> =
15
+ | {
16
+ resultType: 'SUCCESS';
17
+ schema: T;
18
+ schemaName?: string;
19
+ }
20
+ | {
21
+ resultType: 'FAILURE';
22
+ schemaName: string;
23
+ error: Error;
24
+ schema?: T;
25
+ };
26
+
27
+ // TODO: when types are updated in codegen-ui reference mappers here so the arguments accepted are not any
28
+
9
29
  /**
10
30
  * Returns instances of StudioComponent from the component schemas
11
31
  */
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- export const generateUiBuilderComponents = (context: $TSContext, componentSchemas: any[], dataSchema?: GenericDataSchema): ({
14
- resultType: string;
15
- component: StudioComponent;
16
- schemaName?: undefined;
17
- error?: undefined;
18
- } | {
19
- resultType: string;
20
- schemaName: string;
21
- error: Error;
22
- component?: undefined;
23
- })[] => {
24
- const componentResults = componentSchemas.map(schema => {
32
+ export const generateUiBuilderComponents = (
33
+ context: $TSContext,
34
+ componentSchemas: any[], // eslint-disable-line @typescript-eslint/no-explicit-any
35
+ dataSchema?: GenericDataSchema,
36
+ ): CodegenResponse<StudioComponent>[] => {
37
+ const componentResults = componentSchemas.map<CodegenResponse<StudioComponent>>(schema => {
25
38
  try {
26
39
  const component = createUiBuilderComponent(context, schema, dataSchema);
27
- return { resultType: 'SUCCESS', component };
40
+ return { resultType: 'SUCCESS', schema: component };
28
41
  } catch (e) {
29
42
  printer.debug(`Failure caught processing ${schema.name}`);
30
43
  printer.debug(e);
@@ -44,21 +57,14 @@ export const generateUiBuilderComponents = (context: $TSContext, componentSchema
44
57
  * Returns instances of StudioTheme from theme schemas
45
58
  */
46
59
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]): ({
48
- resultType: string;
49
- theme: StudioTheme;
50
- schemaName?: undefined;
51
- error?: undefined;
52
- } | {
53
- resultType: string;
54
- schemaName: string;
55
- error: Error;
56
- theme?: undefined;
57
- })[] => {
58
- const themeResults = themeSchemas.map(schema => {
60
+ export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]): CodegenResponse<StudioTheme>[] => {
61
+ if (themeSchemas.length === 0) {
62
+ return [generateDefaultTheme(context)];
63
+ }
64
+ const themeResults = themeSchemas.map<CodegenResponse<StudioTheme>>(schema => {
59
65
  try {
60
66
  const theme = createUiBuilderTheme(context, schema);
61
- return { resultType: 'SUCCESS', theme };
67
+ return { resultType: 'SUCCESS', schema: theme };
62
68
  } catch (e) {
63
69
  printer.debug(`Failure caught processing ${schema.name}`);
64
70
  printer.debug(e);
@@ -71,3 +77,64 @@ export const generateUiBuilderThemes = (context: $TSContext, themeSchemas: any[]
71
77
  );
72
78
  return themeResults;
73
79
  };
80
+
81
+ /**
82
+ * Generates the defaultTheme in the user's project that's exported from @aws-amplify/codegen-ui-react
83
+ */
84
+ const generateDefaultTheme = (context: $TSContext): CodegenResponse<StudioTheme> => {
85
+ try {
86
+ const theme = createUiBuilderTheme(context, { name: 'studioTheme', values: [] }, { renderDefaultTheme: true });
87
+ printer.debug(
88
+ `Generated default theme in ${getUiBuilderComponentsPath(context)}`,
89
+ );
90
+ return { resultType: 'SUCCESS', schema: theme };
91
+ } catch (e) {
92
+ printer.debug(`Failure caught rendering default theme`);
93
+ printer.debug(e);
94
+ return { resultType: 'FAILURE', schemaName: 'studioTheme', error: e };
95
+ }
96
+ };
97
+
98
+ /**
99
+ * Returns instances of StudioForm from form schemas
100
+ */
101
+ export const generateUiBuilderForms = (
102
+ context: $TSContext,
103
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
+ formSchemas: any[],
105
+ dataSchema?: GenericDataSchema,
106
+ autoGenerateForms?: boolean,
107
+ ): CodegenResponse<StudioForm>[] => {
108
+ const modelMap: { [model: string]: Set<'create' | 'update'> } = {};
109
+ if (dataSchema?.dataSourceType === 'DataStore' && autoGenerateForms) {
110
+ Object.entries(dataSchema.models).forEach(([name, model]) => {
111
+ if (checkIsSupportedAsForm(model) && !model.isJoinTable) {
112
+ modelMap[name] = new Set(['create', 'update']);
113
+ }
114
+ });
115
+ }
116
+ const codegenForm = (schema: StudioForm): CodegenResponse<StudioForm> => {
117
+ try {
118
+ const form = createUiBuilderForm(context, schema, dataSchema);
119
+ return { resultType: 'SUCCESS', schema: form };
120
+ } catch (e) {
121
+ printer.debug(`Failure caught processing ${schema.name}`);
122
+ printer.debug(e);
123
+ return { resultType: 'FAILURE', schemaName: schema.name, error: e };
124
+ }
125
+ };
126
+ const formResults = formSchemas.map((schema: StudioForm) => {
127
+ if (schema?.dataType && schema.dataType?.dataSourceType === 'DataStore') {
128
+ modelMap[schema.dataType.dataTypeName]?.delete(schema.formActionType);
129
+ }
130
+ return codegenForm(schema);
131
+ });
132
+
133
+ // append remaining models
134
+ formResults.push(...generateBaseForms(modelMap).map(codegenForm));
135
+
136
+ printer.debug(
137
+ `Generated ${formResults.filter(result => result.resultType === 'SUCCESS').length} forms in ${getUiBuilderComponentsPath(context)}`,
138
+ );
139
+ return formResults;
140
+ };
@@ -1,6 +1,9 @@
1
1
  import { printer } from 'amplify-prompts';
2
2
  import path from 'path';
3
3
 
4
- export async function run() {
4
+ /**
5
+ * runs version command
6
+ */
7
+ export const run = async (): Promise<void> => {
5
8
  printer.info((await import(path.join(__dirname, '..', '..', 'package.json'))).version);
6
- }
9
+ };
@@ -1,14 +1,16 @@
1
1
  import { $TSContext } from 'amplify-cli-core';
2
2
  import { printer } from 'amplify-prompts';
3
+ import { run as cloneComponentsFromEnv } from '../commands/cloneComponentsFromEnv';
3
4
 
4
- export async function run(context: $TSContext) {
5
+ /**
6
+ *
7
+ * runs after adding an environment
8
+ */
9
+ export const run = async (context: $TSContext): Promise<void> => {
5
10
  try {
6
- await context.amplify.invokePluginMethod(context, 'ui-builder', undefined, 'executeAmplifyCommand', [
7
- context,
8
- 'cloneComponentsFromEnv',
9
- ]);
11
+ await cloneComponentsFromEnv(context);
10
12
  } catch (e) {
11
13
  // Swallow all errors from the uibuilder plugin
12
14
  printer.debug(e);
13
15
  }
14
- }
16
+ };
@@ -1,11 +1,15 @@
1
1
  import { $TSContext } from 'amplify-cli-core';
2
2
  import { printer } from 'amplify-prompts';
3
+ import { run as generateComponents } from '../commands/generateComponents';
3
4
 
4
- export async function run(context: $TSContext) {
5
+ /**
6
+ * The code to run after a pull.
7
+ */
8
+ export const run = async (context: $TSContext): Promise<void> => {
5
9
  try {
6
- await context.amplify.invokePluginMethod(context, 'ui-builder', undefined, 'executeAmplifyCommand', [context, 'generateComponents']);
10
+ await generateComponents(context);
7
11
  } catch (e) {
8
12
  // Swallow all errors from the uibuilder plugin
9
13
  printer.debug(e);
10
14
  }
11
- }
15
+ };
@@ -0,0 +1,15 @@
1
+ import { $TSContext } from 'amplify-cli-core';
2
+ import { printer } from 'amplify-prompts';
3
+ import { run as generateComponents } from '../commands/generateComponents';
4
+
5
+ /**
6
+ * The code to run after a push
7
+ */
8
+ export const run = async (context: $TSContext): Promise<void> => {
9
+ try {
10
+ await generateComponents(context);
11
+ } catch (e) {
12
+ // Swallow all errors from the uibuilder plugin
13
+ printer.debug(e);
14
+ }
15
+ };