Skip to content

Commit

Permalink
feat: Sync codegen behavior implementation adding generateModelsSync (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
stocaaro authored Oct 23, 2024
1 parent bef8bb2 commit fac63c1
Show file tree
Hide file tree
Showing 29 changed files with 6,120 additions and 2,049 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# API approval - public surface and dependencies.
**/API.md @aws-amplify/amplify-data-admins

# Vendor code changes
packages/**/vendor/** @aws-amplify/amplify-data-admins

# Dependency Licensing approval
dependency_licenses.txt @aws-amplify/amplify-data-admins

Expand Down
4 changes: 2 additions & 2 deletions dependency_licenses.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9556,7 +9556,7 @@ The following software may be included in this product: change-case-all. A copy

MIT License

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

Original work:

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

MIT License

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

Original work:

Expand Down
2 changes: 1 addition & 1 deletion packages/amplify-codegen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@aws-amplify/graphql-docs-generator": "4.2.1",
"@aws-amplify/graphql-generator": "0.4.7",
"@aws-amplify/graphql-types-generator": "3.6.0",
"@graphql-codegen/core": "2.6.6",
"@graphql-codegen/core": "^2.6.6",
"chalk": "^3.0.0",
"fs-extra": "^8.1.0",
"glob-parent": "^6.0.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { generateModelIntrospection, getModelIntrospection } = require('../../src/commands/model-intropection');
const graphqlGenerator = require('@aws-amplify/graphql-generator');
const codegen_core = require('@graphql-codegen/core');
const mockFs = require('mock-fs');
const path = require('path');
const fs = require('fs');
Expand All @@ -14,7 +15,6 @@ jest.mock('@aws-amplify/graphql-generator', () => {
jest.mock('@graphql-codegen/core', () => {
const originalModule = jest.requireActual('@graphql-codegen/core');
const codegen = jest.fn();
codegen.mockReturnValue(MOCK_GENERATED_CODE);
return {
...originalModule,
codegen,
Expand All @@ -27,6 +27,7 @@ const MOCK_PROJECT_NAME = 'myapp';
const MOCK_BACKEND_DIRECTORY = 'backend';
const MOCK_GENERATED_INTROSPECTION = { schemaVersion: 1 };
const MOCK_GENERATED_CODE = JSON.stringify(MOCK_GENERATED_INTROSPECTION);

const MOCK_CONTEXT = {
print: {
info: jest.fn(),
Expand Down Expand Up @@ -55,7 +56,6 @@ const MOCK_CONTEXT = {
};

describe('generateModelIntrospection', () => {
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
const outputDirectory = path.join(MOCK_PROJECT_ROOT, MOCK_OUTPUT_DIR);
const mockedFiles = {};
Expand All @@ -64,6 +64,11 @@ describe('generateModelIntrospection', () => {
};
mockedFiles[outputDirectory] = {};

beforeAll(() => {
codegen_core.codegen.mockReturnValue(MOCK_GENERATED_CODE);
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
});

beforeEach(() => {
jest.clearAllMocks();
});
Expand All @@ -76,7 +81,7 @@ describe('generateModelIntrospection', () => {
...MOCK_CONTEXT,
parameters: {
options: {
['output-dir']: MOCK_OUTPUT_DIR,
'output-dir': MOCK_OUTPUT_DIR,
},
},
};
Expand All @@ -99,7 +104,7 @@ describe('generateModelIntrospection', () => {
});

describe('getModelIntrospection', () => {
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });

const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
const outputDirectory = path.join(MOCK_PROJECT_ROOT, MOCK_OUTPUT_DIR);
const mockedFiles = {};
Expand All @@ -108,6 +113,11 @@ describe('getModelIntrospection', () => {
};
mockedFiles[outputDirectory] = {};

beforeAll(() => {
codegen_core.codegen.mockReturnValue(MOCK_GENERATED_CODE);
graphqlGenerator.generateModels.mockReturnValue({ 'model-introspection.json': MOCK_GENERATED_CODE });
});

beforeEach(() => {
jest.clearAllMocks();
});
Expand Down
40 changes: 40 additions & 0 deletions packages/appsync-modelgen-plugin/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
```ts

import { CodegenPlugin } from '@graphql-codegen/plugin-helpers';
import { PluginFunction } from '@graphql-codegen/plugin-helpers';
import { RawConfig } from '@graphql-codegen/visitor-plugin-common';
import { RawDocumentsConfig } from '@graphql-codegen/visitor-plugin-common';
Expand Down Expand Up @@ -142,9 +143,15 @@ export type ModelIntrospectionSchema = {
// @public (undocumented)
export const plugin: PluginFunction<RawAppSyncModelConfig>;

// @public (undocumented)
export const pluginSync: SyncTypes.PluginFunction<RawAppSyncModelConfig>;

// @public (undocumented)
export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig>;

// @public (undocumented)
export const presetSync: SyncTypes.OutputPreset<AppSyncModelCodeGenPresetConfig>;

// @public (undocumented)
export type PrimaryKeyInfo = {
isCustomPrimaryKey: boolean;
Expand Down Expand Up @@ -235,6 +242,39 @@ export type SchemaSubscription = SchemaQuery;
// @public (undocumented)
export type SchemaSubscriptions = Record<string, SchemaSubscription>;

// @public (undocumented)
export namespace SyncTypes {
// (undocumented)
export type CodegenPlugin<T = any> = Omit<CodegenPlugin<T>, 'plugin'> & {
plugin: PluginFunction<T>;
};
// (undocumented)
export type ConfiguredPlugin = Types.ConfiguredPlugin;
// (undocumented)
export type DocumentFile = Types.DocumentFile;
// Warning: (ae-forgotten-export) The symbol "SyncCache" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "SyncPluginMap" needs to be exported by the entry point index.d.ts
//
// (undocumented)
export type GenerateOptions = SyncCache<SyncPluginMap<Types.GenerateOptions>>;
// (undocumented)
export type OutputPreset<TPresetConfig = any> = {
buildGeneratesSection: (options: PresetFnArgs<TPresetConfig>) => GenerateOptions[];
};
// (undocumented)
export type PluginConfig = Types.PluginConfig;
// (undocumented)
export type PluginFunction<T> = (...args: Parameters<PluginFunction<T>>) => Awaited<ReturnType<PluginFunction<T>>>;
// (undocumented)
export type PluginOutput = Types.PluginOutput;
// (undocumented)
export type PresetFnArgs<Config = any, PluginConfig = {
[key: string]: any;
}> = SyncCache<SyncPluginMap<Types.PresetFnArgs<Config, PluginConfig>>>;
// (undocumented)
export type SkipDocumentsValidationOptions = Types.SkipDocumentsValidationOptions;
}

// @public (undocumented)
export type Target = 'java' | 'swift' | 'javascript' | 'typescript' | 'dart' | 'introspection';

Expand Down
2 changes: 1 addition & 1 deletion packages/appsync-modelgen-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"extract-api": "ts-node ../../scripts/extract-api.ts"
},
"dependencies": {
"@graphql-codegen/plugin-helpers": "^1.18.8",
"@graphql-codegen/plugin-helpers": "^3.1.1",
"@graphql-codegen/visitor-plugin-common": "^1.22.0",
"@graphql-tools/utils": "^6.0.18",
"chalk": "^3.0.0",
Expand Down
1 change: 1 addition & 0 deletions packages/appsync-modelgen-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface AppSyncModelPluginConfig extends RawDocumentsConfig {
export * from './plugin';
export * from './preset';
export * from './interfaces/introspection';
export { SyncTypes } from './types/sync'

export const addToSchema = (config: AppSyncModelPluginConfig) => {
const result: string[] = [];
Expand Down
15 changes: 14 additions & 1 deletion packages/appsync-modelgen-plugin/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import { AppSyncModelTypeScriptVisitor } from './visitors/appsync-typescript-vis
import { AppSyncModelJavascriptVisitor } from './visitors/appsync-javascript-visitor';
import { AppSyncModelDartVisitor } from './visitors/appsync-dart-visitor';
import { AppSyncModelIntrospectionVisitor } from './visitors/appsync-model-introspection-visitor';
export const plugin: PluginFunction<RawAppSyncModelConfig> = (
import { SyncTypes } from './types/sync';

/**
* @internal
*/
export const pluginSync: SyncTypes.PluginFunction<RawAppSyncModelConfig> = (
schema: GraphQLSchema,
rawDocuments: Types.DocumentFile[],
config: RawAppSyncModelConfig,
Expand Down Expand Up @@ -59,3 +64,11 @@ export const plugin: PluginFunction<RawAppSyncModelConfig> = (
}
return '';
};

export const plugin: PluginFunction<RawAppSyncModelConfig> = (
schema: GraphQLSchema,
rawDocuments: Types.DocumentFile[],
config: RawAppSyncModelConfig,
) => {
return pluginSync(schema, rawDocuments, config);
};
96 changes: 73 additions & 23 deletions packages/appsync-modelgen-plugin/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { join } from 'path';
import { JAVA_SCALAR_MAP, SWIFT_SCALAR_MAP, TYPESCRIPT_SCALAR_MAP, DART_SCALAR_MAP, METADATA_SCALAR_MAP } from './scalars';
import { LOADER_CLASS_NAME, GENERATED_PACKAGE_NAME } from './configs/java-config';
import { graphqlName, toUpper } from 'graphql-transformer-common';
import { SyncTypes } from './types/sync';

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

Expand Down Expand Up @@ -31,12 +32,25 @@ export type AppSyncModelCodeGenPresetConfig = {
isDataStoreEnabled?: boolean;
};

/**
* NOTE: The different codegen target presets restructure the options to meet the needs of the target plugin
* None of this remapping interacts with the pluginMap or cache interface, so we can reuse all logic if we strip out
* the pluginMap and cache, then re-introduce them in the returned preset.
*/

/**
* Internal types that represent the options without the pluginMap and cache, which we will use in each of our
* target preset option construction implementations
*/
type GenerateOptions = Omit<SyncTypes.GenerateOptions, 'cache' | 'pluginMap'>;
type PresetFnArgs = Omit<SyncTypes.PresetFnArgs<AppSyncModelCodeGenPresetConfig>, 'cache' | 'pluginMap'>;

const generateJavaPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
manyToManyJoinModels: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
const modelFolder = options.config.overrideOutputDir
? [options.config.overrideOutputDir]
: [options.baseOutputDir, ...GENERATED_PACKAGE_NAME.split('.')];
Expand Down Expand Up @@ -105,10 +119,10 @@ const generateJavaPreset = (
};

const generateSwiftPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : options.baseOutputDir;
models.forEach(model => {
const modelName = model.name.value;
Expand Down Expand Up @@ -152,10 +166,10 @@ const generateSwiftPreset = (
};

const generateTypeScriptPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : join(options.baseOutputDir);
config.push({
...options,
Expand All @@ -181,10 +195,10 @@ const generateTypeScriptPreset = (
};

const generateJavasScriptPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
const modelFolder = options.config.overrideOutputDir ? options.config.overrideOutputDir : join(options.baseOutputDir);
config.push({
...options,
Expand Down Expand Up @@ -234,10 +248,10 @@ const generateJavasScriptPreset = (
};

const generateDartPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
const modelFolder = options.config.overrideOutputDir ?? options.baseOutputDir;
models.forEach(model => {
const modelName = model.name.value;
Expand All @@ -264,7 +278,7 @@ const generateDartPreset = (
return config;
};

const generateManyToManyModelStubs = (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): TypeDefinitionNode[] => {
const generateManyToManyModelStubs = (options: PresetFnArgs): TypeDefinitionNode[] => {
let models = new Array<TypeDefinitionNode>();
let manyToManySet = new Set<string>();
options.schema.definitions.forEach(def => {
Expand Down Expand Up @@ -295,10 +309,10 @@ const generateManyToManyModelStubs = (options: Types.PresetFnArgs<AppSyncModelCo
};

const generateIntrospectionPreset = (
options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>,
options: PresetFnArgs,
models: TypeDefinitionNode[],
): Types.GenerateOptions[] => {
const config: Types.GenerateOptions[] = [];
): GenerateOptions[] => {
const config: GenerateOptions[] = [];
// model-intropection.json
config.push({
...options,
Expand All @@ -312,8 +326,7 @@ const generateIntrospectionPreset = (
return config;
};

export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
buildGeneratesSection: (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): Types.GenerateOptions[] => {
const buildGenerations = (options: PresetFnArgs): GenerateOptions[] => {
const codeGenTarget = options.config.target;
const typesToSkip: string[] = ['Query', 'Mutation', 'Subscription'];
const models: TypeDefinitionNode[] = options.schema.definitions.filter(
Expand Down Expand Up @@ -346,5 +359,42 @@ export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
)}`,
);
}
},
};
};



/**
* @internal
* The presetSync interface uses our SyncTypes __without__ promise/async typing
*/
export const presetSync: SyncTypes.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
buildGeneratesSection: (options: SyncTypes.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): SyncTypes.GenerateOptions[] => {
// Extract cache and pluginMap from the options
const {cache, pluginMap, ...otherOptions} = options;

// Generate the list of options and re-introduce the pluginMap and cache
return buildGenerations(otherOptions).map((config: GenerateOptions) => ({
pluginMap,
cache,
...config,
}))
}
}

/**
* @internal
* The preset interface uses the @graphql-codegen/core interfaces __with__ promise/async typing
*/
export const preset: Types.OutputPreset<AppSyncModelCodeGenPresetConfig> = {
buildGeneratesSection: (options: Types.PresetFnArgs<AppSyncModelCodeGenPresetConfig>): Types.GenerateOptions[] => {
// Extract cache and pluginMap from the options
const {cache, pluginMap, ...otherOptions} = options;

// Generate the list of options and re-introduce the pluginMap and cache
return buildGenerations(otherOptions).map((config: GenerateOptions) => ({
pluginMap,
cache,
...config,
}))
}
}
Loading

0 comments on commit fac63c1

Please sign in to comment.