Skip to content

Commit fac63c1

Browse files
authored
feat: Sync codegen behavior implementation adding generateModelsSync (#894)
* feat: Add vendor version of @graphql-codegen/core * feat: Sync codegen behavior implementation - modify and integrate * Minor edits to maintenance instructions * Regenerate API and license to fix build issues * Use sync behavior in comparison test * simplify equality comparison * Add internal docs for exported behavior * Updates from feedback * Update readme/instructions * Updates from comments * Update snapshots
1 parent bef8bb2 commit fac63c1

File tree

29 files changed

+6120
-2049
lines changed

29 files changed

+6120
-2049
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# API approval - public surface and dependencies.
55
**/API.md @aws-amplify/amplify-data-admins
66

7+
# Vendor code changes
8+
packages/**/vendor/** @aws-amplify/amplify-data-admins
9+
710
# Dependency Licensing approval
811
dependency_licenses.txt @aws-amplify/amplify-data-admins
912

dependency_licenses.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9556,7 +9556,7 @@ The following software may be included in this product: change-case-all. A copy
95569556

95579557
MIT License
95589558

9559-
Modified work: Copyright (c) 2020 Jonas Gnioui <btxtiger@outlook.com>
9559+
Modified work: Copyright (c) 2020 Jonas Gnioui <btxtiger@icloud.com>
95609560

95619561
Original work:
95629562

@@ -9586,7 +9586,7 @@ The following software may be included in this product: change-case-all. A copy
95869586

95879587
MIT License
95889588

9589-
Modified work: Copyright (c) 2020 Jonas Gnioui <btxtiger@icloud.com>
9589+
Modified work: Copyright (c) 2020 Jonas Gnioui <btxtiger@outlook.com>
95909590

95919591
Original work:
95929592

packages/amplify-codegen/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"@aws-amplify/graphql-docs-generator": "4.2.1",
2626
"@aws-amplify/graphql-generator": "0.4.7",
2727
"@aws-amplify/graphql-types-generator": "3.6.0",
28-
"@graphql-codegen/core": "2.6.6",
28+
"@graphql-codegen/core": "^2.6.6",
2929
"chalk": "^3.0.0",
3030
"fs-extra": "^8.1.0",
3131
"glob-parent": "^6.0.2",

packages/amplify-codegen/tests/commands/model-introspection.test.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { generateModelIntrospection, getModelIntrospection } = require('../../src/commands/model-intropection');
22
const graphqlGenerator = require('@aws-amplify/graphql-generator');
3+
const codegen_core = require('@graphql-codegen/core');
34
const mockFs = require('mock-fs');
45
const path = require('path');
56
const fs = require('fs');
@@ -14,7 +15,6 @@ jest.mock('@aws-amplify/graphql-generator', () => {
1415
jest.mock('@graphql-codegen/core', () => {
1516
const originalModule = jest.requireActual('@graphql-codegen/core');
1617
const codegen = jest.fn();
17-
codegen.mockReturnValue(MOCK_GENERATED_CODE);
1818
return {
1919
...originalModule,
2020
codegen,
@@ -27,6 +27,7 @@ const MOCK_PROJECT_NAME = 'myapp';
2727
const MOCK_BACKEND_DIRECTORY = 'backend';
2828
const MOCK_GENERATED_INTROSPECTION = { schemaVersion: 1 };
2929
const MOCK_GENERATED_CODE = JSON.stringify(MOCK_GENERATED_INTROSPECTION);
30+
3031
const MOCK_CONTEXT = {
3132
print: {
3233
info: jest.fn(),
@@ -55,7 +56,6 @@ const MOCK_CONTEXT = {
5556
};
5657

5758
describe('generateModelIntrospection', () => {
58-
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
5959
const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
6060
const outputDirectory = path.join(MOCK_PROJECT_ROOT, MOCK_OUTPUT_DIR);
6161
const mockedFiles = {};
@@ -64,6 +64,11 @@ describe('generateModelIntrospection', () => {
6464
};
6565
mockedFiles[outputDirectory] = {};
6666

67+
beforeAll(() => {
68+
codegen_core.codegen.mockReturnValue(MOCK_GENERATED_CODE);
69+
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
70+
});
71+
6772
beforeEach(() => {
6873
jest.clearAllMocks();
6974
});
@@ -76,7 +81,7 @@ describe('generateModelIntrospection', () => {
7681
...MOCK_CONTEXT,
7782
parameters: {
7883
options: {
79-
['output-dir']: MOCK_OUTPUT_DIR,
84+
'output-dir': MOCK_OUTPUT_DIR,
8085
},
8186
},
8287
};
@@ -99,7 +104,7 @@ describe('generateModelIntrospection', () => {
99104
});
100105

101106
describe('getModelIntrospection', () => {
102-
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
107+
103108
const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
104109
const outputDirectory = path.join(MOCK_PROJECT_ROOT, MOCK_OUTPUT_DIR);
105110
const mockedFiles = {};
@@ -108,6 +113,11 @@ describe('getModelIntrospection', () => {
108113
};
109114
mockedFiles[outputDirectory] = {};
110115

116+
beforeAll(() => {
117+
codegen_core.codegen.mockReturnValue(MOCK_GENERATED_CODE);
118+
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
119+
});
120+
111121
beforeEach(() => {
112122
jest.clearAllMocks();
113123
});

packages/appsync-modelgen-plugin/API.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
```ts
66

7+
import { CodegenPlugin } from '@graphql-codegen/plugin-helpers';
78
import { PluginFunction } from '@graphql-codegen/plugin-helpers';
89
import { RawConfig } from '@graphql-codegen/visitor-plugin-common';
910
import { RawDocumentsConfig } from '@graphql-codegen/visitor-plugin-common';
@@ -142,9 +143,15 @@ export type ModelIntrospectionSchema = {
142143
// @public (undocumented)
143144
export const plugin: PluginFunction<RawAppSyncModelConfig>;
144145

146+
// @public (undocumented)
147+
export const pluginSync: SyncTypes.PluginFunction<RawAppSyncModelConfig>;
148+
145149
// @public (undocumented)
146150
export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig>;
147151

152+
// @public (undocumented)
153+
export const presetSync: SyncTypes.OutputPreset<AppSyncModelCodeGenPresetConfig>;
154+
148155
// @public (undocumented)
149156
export type PrimaryKeyInfo = {
150157
isCustomPrimaryKey: boolean;
@@ -235,6 +242,39 @@ export type SchemaSubscription = SchemaQuery;
235242
// @public (undocumented)
236243
export type SchemaSubscriptions = Record<string, SchemaSubscription>;
237244

245+
// @public (undocumented)
246+
export namespace SyncTypes {
247+
// (undocumented)
248+
export type CodegenPlugin<T = any> = Omit<CodegenPlugin<T>, 'plugin'> & {
249+
plugin: PluginFunction<T>;
250+
};
251+
// (undocumented)
252+
export type ConfiguredPlugin = Types.ConfiguredPlugin;
253+
// (undocumented)
254+
export type DocumentFile = Types.DocumentFile;
255+
// Warning: (ae-forgotten-export) The symbol "SyncCache" needs to be exported by the entry point index.d.ts
256+
// Warning: (ae-forgotten-export) The symbol "SyncPluginMap" needs to be exported by the entry point index.d.ts
257+
//
258+
// (undocumented)
259+
export type GenerateOptions = SyncCache<SyncPluginMap<Types.GenerateOptions>>;
260+
// (undocumented)
261+
export type OutputPreset<TPresetConfig = any> = {
262+
buildGeneratesSection: (options: PresetFnArgs<TPresetConfig>) => GenerateOptions[];
263+
};
264+
// (undocumented)
265+
export type PluginConfig = Types.PluginConfig;
266+
// (undocumented)
267+
export type PluginFunction<T> = (...args: Parameters<PluginFunction<T>>) => Awaited<ReturnType<PluginFunction<T>>>;
268+
// (undocumented)
269+
export type PluginOutput = Types.PluginOutput;
270+
// (undocumented)
271+
export type PresetFnArgs<Config = any, PluginConfig = {
272+
[key: string]: any;
273+
}> = SyncCache<SyncPluginMap<Types.PresetFnArgs<Config, PluginConfig>>>;
274+
// (undocumented)
275+
export type SkipDocumentsValidationOptions = Types.SkipDocumentsValidationOptions;
276+
}
277+
238278
// @public (undocumented)
239279
export type Target = 'java' | 'swift' | 'javascript' | 'typescript' | 'dart' | 'introspection';
240280

packages/appsync-modelgen-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"extract-api": "ts-node ../../scripts/extract-api.ts"
2828
},
2929
"dependencies": {
30-
"@graphql-codegen/plugin-helpers": "^1.18.8",
30+
"@graphql-codegen/plugin-helpers": "^3.1.1",
3131
"@graphql-codegen/visitor-plugin-common": "^1.22.0",
3232
"@graphql-tools/utils": "^6.0.18",
3333
"chalk": "^3.0.0",

packages/appsync-modelgen-plugin/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface AppSyncModelPluginConfig extends RawDocumentsConfig {
77
export * from './plugin';
88
export * from './preset';
99
export * from './interfaces/introspection';
10+
export { SyncTypes } from './types/sync'
1011

1112
export const addToSchema = (config: AppSyncModelPluginConfig) => {
1213
const result: string[] = [];

packages/appsync-modelgen-plugin/src/plugin.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import { AppSyncModelTypeScriptVisitor } from './visitors/appsync-typescript-vis
99
import { AppSyncModelJavascriptVisitor } from './visitors/appsync-javascript-visitor';
1010
import { AppSyncModelDartVisitor } from './visitors/appsync-dart-visitor';
1111
import { AppSyncModelIntrospectionVisitor } from './visitors/appsync-model-introspection-visitor';
12-
export const plugin: PluginFunction<RawAppSyncModelConfig> = (
12+
import { SyncTypes } from './types/sync';
13+
14+
/**
15+
* @internal
16+
*/
17+
export const pluginSync: SyncTypes.PluginFunction<RawAppSyncModelConfig> = (
1318
schema: GraphQLSchema,
1419
rawDocuments: Types.DocumentFile[],
1520
config: RawAppSyncModelConfig,
@@ -59,3 +64,11 @@ export const plugin: PluginFunction<RawAppSyncModelConfig> = (
5964
}
6065
return '';
6166
};
67+
68+
export const plugin: PluginFunction<RawAppSyncModelConfig> = (
69+
schema: GraphQLSchema,
70+
rawDocuments: Types.DocumentFile[],
71+
config: RawAppSyncModelConfig,
72+
) => {
73+
return pluginSync(schema, rawDocuments, config);
74+
};

packages/appsync-modelgen-plugin/src/preset.ts

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { join } from 'path';
44
import { JAVA_SCALAR_MAP, SWIFT_SCALAR_MAP, TYPESCRIPT_SCALAR_MAP, DART_SCALAR_MAP, METADATA_SCALAR_MAP } from './scalars';
55
import { LOADER_CLASS_NAME, GENERATED_PACKAGE_NAME } from './configs/java-config';
66
import { graphqlName, toUpper } from 'graphql-transformer-common';
7+
import { SyncTypes } from './types/sync';
78

89
const APPSYNC_DATA_STORE_CODEGEN_TARGETS = ['java', 'swift', 'javascript', 'typescript', 'dart', 'introspection'];
910

@@ -31,12 +32,25 @@ export type AppSyncModelCodeGenPresetConfig = {
3132
isDataStoreEnabled?: boolean;
3233
};
3334

35+
/**
36+
* NOTE: The different codegen target presets restructure the options to meet the needs of the target plugin
37+
* None of this remapping interacts with the pluginMap or cache interface, so we can reuse all logic if we strip out
38+
* the pluginMap and cache, then re-introduce them in the returned preset.
39+
*/
40+
41+
/**
42+
* Internal types that represent the options without the pluginMap and cache, which we will use in each of our
43+
* target preset option construction implementations
44+
*/
45+
type GenerateOptions = Omit<SyncTypes.GenerateOptions, 'cache' | 'pluginMap'>;
46+
type PresetFnArgs = Omit<SyncTypes.PresetFnArgs<AppSyncModelCodeGenPresetConfig>, 'cache' | 'pluginMap'>;
47+
3448
const generateJavaPreset = (
35-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
49+
options: PresetFnArgs,
3650
models: TypeDefinitionNode[],
3751
manyToManyJoinModels: TypeDefinitionNode[],
38-
): Types.GenerateOptions[] => {
39-
const config: Types.GenerateOptions[] = [];
52+
): GenerateOptions[] => {
53+
const config: GenerateOptions[] = [];
4054
const modelFolder = options.config.overrideOutputDir
4155
? [options.config.overrideOutputDir]
4256
: [options.baseOutputDir, ...GENERATED_PACKAGE_NAME.split('.')];
@@ -105,10 +119,10 @@ const generateJavaPreset = (
105119
};
106120

107121
const generateSwiftPreset = (
108-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
122+
options: PresetFnArgs,
109123
models: TypeDefinitionNode[],
110-
): Types.GenerateOptions[] => {
111-
const config: Types.GenerateOptions[] = [];
124+
): GenerateOptions[] => {
125+
const config: GenerateOptions[] = [];
112126
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : options.baseOutputDir;
113127
models.forEach(model => {
114128
const modelName = model.name.value;
@@ -152,10 +166,10 @@ const generateSwiftPreset = (
152166
};
153167

154168
const generateTypeScriptPreset = (
155-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
169+
options: PresetFnArgs,
156170
models: TypeDefinitionNode[],
157-
): Types.GenerateOptions[] => {
158-
const config: Types.GenerateOptions[] = [];
171+
): GenerateOptions[] => {
172+
const config: GenerateOptions[] = [];
159173
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : join(options.baseOutputDir);
160174
config.push({
161175
...options,
@@ -181,10 +195,10 @@ const generateTypeScriptPreset = (
181195
};
182196

183197
const generateJavasScriptPreset = (
184-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
198+
options: PresetFnArgs,
185199
models: TypeDefinitionNode[],
186-
): Types.GenerateOptions[] => {
187-
const config: Types.GenerateOptions[] = [];
200+
): GenerateOptions[] => {
201+
const config: GenerateOptions[] = [];
188202
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : join(options.baseOutputDir);
189203
config.push({
190204
...options,
@@ -234,10 +248,10 @@ const generateJavasScriptPreset = (
234248
};
235249

236250
const generateDartPreset = (
237-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
251+
options: PresetFnArgs,
238252
models: TypeDefinitionNode[],
239-
): Types.GenerateOptions[] => {
240-
const config: Types.GenerateOptions[] = [];
253+
): GenerateOptions[] => {
254+
const config: GenerateOptions[] = [];
241255
const modelFolder = options.config.overrideOutputDir ?? options.baseOutputDir;
242256
models.forEach(model => {
243257
const modelName = model.name.value;
@@ -264,7 +278,7 @@ const generateDartPreset = (
264278
return config;
265279
};
266280

267-
const generateManyToManyModelStubs = (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): TypeDefinitionNode[] => {
281+
const generateManyToManyModelStubs = (options: PresetFnArgs): TypeDefinitionNode[] => {
268282
let models = new Array<TypeDefinitionNode>();
269283
let manyToManySet = new Set<string>();
270284
options.schema.definitions.forEach(def => {
@@ -295,10 +309,10 @@ const generateManyToManyModelStubs = (options: Types.PresetFnArgs<AppSyncModelCo
295309
};
296310

297311
const generateIntrospectionPreset = (
298-
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
312+
options: PresetFnArgs,
299313
models: TypeDefinitionNode[],
300-
): Types.GenerateOptions[] => {
301-
const config: Types.GenerateOptions[] = [];
314+
): GenerateOptions[] => {
315+
const config: GenerateOptions[] = [];
302316
// model-intropection.json
303317
config.push({
304318
...options,
@@ -312,8 +326,7 @@ const generateIntrospectionPreset = (
312326
return config;
313327
};
314328

315-
export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
316-
buildGeneratesSection: (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): Types.GenerateOptions[] => {
329+
const buildGenerations = (options: PresetFnArgs): GenerateOptions[] => {
317330
const codeGenTarget = options.config.target;
318331
const typesToSkip: string[] = ['Query', 'Mutation', 'Subscription'];
319332
const models: TypeDefinitionNode[] = options.schema.definitions.filter(
@@ -346,5 +359,42 @@ export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
346359
)}`,
347360
);
348361
}
349-
},
350-
};
362+
};
363+
364+
365+
366+
/**
367+
* @internal
368+
* The presetSync interface uses our SyncTypes __without__ promise/async typing
369+
*/
370+
export const presetSync: SyncTypes.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
371+
buildGeneratesSection: (options: SyncTypes.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): SyncTypes.GenerateOptions[] => {
372+
// Extract cache and pluginMap from the options
373+
const {cache, pluginMap, ...otherOptions} = options;
374+
375+
// Generate the list of options and re-introduce the pluginMap and cache
376+
return buildGenerations(otherOptions).map((config: GenerateOptions) => ({
377+
pluginMap,
378+
cache,
379+
...config,
380+
}))
381+
}
382+
}
383+
384+
/**
385+
* @internal
386+
* The preset interface uses the @graphql-codegen/core interfaces __with__ promise/async typing
387+
*/
388+
export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
389+
buildGeneratesSection: (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): Types.GenerateOptions[] => {
390+
// Extract cache and pluginMap from the options
391+
const {cache, pluginMap, ...otherOptions} = options;
392+
393+
// Generate the list of options and re-introduce the pluginMap and cache
394+
return buildGenerations(otherOptions).map((config: GenerateOptions) => ({
395+
pluginMap,
396+
cache,
397+
...config,
398+
}))
399+
}
400+
}

0 commit comments

Comments
 (0)