Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into generate-client-code-…
Browse files Browse the repository at this point in the history
…command
  • Loading branch information
alharris-at committed Sep 25, 2023
2 parents 79cb5e8 + b48dae8 commit 3f26cef
Show file tree
Hide file tree
Showing 18 changed files with 361 additions and 28 deletions.
7 changes: 7 additions & 0 deletions .changeset/fuzzy-socks-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@aws-amplify/model-generator': minor
---

Add wrapper to around types, documents, and model generation (`generateAPICode`).

Change `createGraphqlDocumentGenerator` and `createGraphqlTypesGenerator` to use backendIdentifier and credentialProvider.
5 changes: 5 additions & 0 deletions .changeset/happy-paws-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend-cli': patch
---

fix: change 'out' to 'outDir'
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions packages/cli/src/commands/sandbox/sandbox_command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ describe('sandbox command', () => {
});

it('starts sandbox with user provided output directory for client config', async () => {
await commandRunner.runCommand('sandbox --out test/location --format js');
await commandRunner.runCommand(
'sandbox --outDir test/location --format js'
);
assert.equal(sandboxStartMock.mock.callCount(), 1);
assert.deepStrictEqual(
sandboxStartMock.mock.calls[0].arguments[0].clientConfigFilePath,
Expand All @@ -75,7 +77,7 @@ describe('sandbox command', () => {
assert.match(output, /--dirToWatch/);
assert.match(output, /--exclude/);
assert.match(output, /--format/);
assert.match(output, /--out/);
assert.match(output, /--outDir/);
});

it('fails if invalid dirToWatch is provided', async () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/sandbox/sandbox_command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type SandboxCommandOptions = {
exclude: string[] | undefined;
name: string | undefined;
format: ClientConfigFormat | undefined;
out: string | undefined;
outDir: string | undefined;
profile: string | undefined;
};

Expand Down Expand Up @@ -57,7 +57,7 @@ export class SandboxCommand
exclude: args.exclude,
name: args.name,
format: args.format,
clientConfigFilePath: args.out,
clientConfigFilePath: args.outDir,
profile: args.profile,
});
process.once('SIGINT', () => void this.sigIntHandler());
Expand Down Expand Up @@ -95,7 +95,7 @@ export class SandboxCommand
array: false,
choices: Object.values(ClientConfigFormat),
})
.option('out', {
.option('outDir', {
describe:
'A path to directory where config is written. If not provided defaults to current process working directory.',
type: 'string',
Expand Down
58 changes: 56 additions & 2 deletions packages/model-generator/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,62 @@
```ts

import { AwsCredentialIdentityProvider } from '@aws-sdk/types';
import { BackendIdentifier } from '@aws-amplify/deployed-backend-client';
import { ModelsTarget } from '@aws-amplify/graphql-generator';
import { StatementsTarget } from '@aws-amplify/graphql-generator';
import { TypesTarget } from '@aws-amplify/graphql-generator';

// @public
export const createGraphqlDocumentGenerator: ({ apiId, }: GraphqlDocumentGeneratorFactoryParams) => GraphqlDocumentGenerator;
export const createGraphqlDocumentGenerator: ({ backendIdentifier, credentialProvider, }: GraphqlDocumentGeneratorFactoryParams) => GraphqlDocumentGenerator;

// @public (undocumented)
export type DocumentGenerationParameters = {
language: TargetLanguage;
maxDepth?: number;
typenameIntrospection?: boolean;
};

// @public
export const generateApiCode: (props: GenerateApiCodeProps) => Promise<GenerationResult>;

// @public (undocumented)
export type GenerateApiCodeProps = GenerateOptions & BackendIdentifier & {
credentialProvider: AwsCredentialIdentityProvider;
};

// @public (undocumented)
export type GenerateGraphqlCodegenOptions = {
format: 'graphql-codegen';
statementTarget: 'javascript' | 'graphql' | 'flow' | 'typescript' | 'angular';
maxDepth?: number;
typeNameIntrospection?: boolean;
typeTarget?: 'json' | 'swift' | 'typescript' | 'flow' | 'scala' | 'flow-modern' | 'angular';
multipleSwiftFiles?: boolean;
};

// @public (undocumented)
export type GenerateIntrospectionOptions = {
format: 'introspection';
};

// @public (undocumented)
export type GenerateModelsOptions = {
format: 'modelgen';
modelTarget: 'java' | 'swift' | 'javascript' | 'typescript' | 'dart';
generateIndexRules?: boolean;
emitAuthProvider?: boolean;
useExperimentalPipelinedTransformer?: boolean;
transformerVersion?: boolean;
respectPrimaryKeyAttributesOnConnectionField?: boolean;
generateModelsForLazyLoadAndCustomSelectionSet?: boolean;
addTimestampFields?: boolean;
handleListNullabilityTransparently?: boolean;
};

// @public (undocumented)
export type GenerateOptions = GenerateGraphqlCodegenOptions | GenerateModelsOptions | GenerateIntrospectionOptions;

// @public (undocumented)
export type GenerationResult = {
writeToDirectory: (directoryPath: string) => Promise<void>;
Expand All @@ -28,7 +72,8 @@ export type GraphqlDocumentGenerator = {

// @public (undocumented)
export type GraphqlDocumentGeneratorFactoryParams = {
apiId: string;
backendIdentifier: BackendIdentifier;
credentialProvider: AwsCredentialIdentityProvider;
};

// @public (undocumented)
Expand All @@ -44,6 +89,14 @@ export type GraphqlTypesGenerator = {
// @public (undocumented)
export type ModelsGenerationParameters = {
target: ModelsTarget;
generateIndexRules?: boolean;
emitAuthProvider?: boolean;
useExperimentalPipelinedTransformer?: boolean;
transformerVersion?: boolean;
respectPrimaryKeyAttributesOnConnectionField?: boolean;
generateModelsForLazyLoadAndCustomSelectionSet?: boolean;
addTimestampFields?: boolean;
handleListNullabilityTransparently?: boolean;
};

// @public (undocumented)
Expand All @@ -52,6 +105,7 @@ export type TargetLanguage = StatementsTarget;
// @public (undocumented)
export type TypesGenerationParameters = {
target: TypesTarget;
multipleSwiftFiles?: boolean;
};

// (No @packageDocumentation comment for this package)
Expand Down
1 change: 1 addition & 0 deletions packages/model-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@aws-amplify/graphql-generator": "^0.1.0",
"@aws-sdk/client-appsync": "^3.398.0",
"@aws-sdk/client-s3": "^3.414.0",
"@aws-sdk/credential-providers": "^3.414.0",
"@aws-sdk/types": "^3.413.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { AwsCredentialIdentityProvider } from '@aws-sdk/types';
import { BackendIdentifier } from '@aws-amplify/deployed-backend-client';
import { createGraphqlDocumentGenerator } from './create_graphql_document_generator.js';

describe('model generator factory', () => {
it('throws an error if a null apiId is passed in', async () => {
it('throws an error if a null backendIdentifier is passed in', async () => {
assert.throws(() =>
createGraphqlDocumentGenerator({ apiId: null as unknown as string })
createGraphqlDocumentGenerator({
backendIdentifier: null as unknown as BackendIdentifier,
credentialProvider: null as unknown as AwsCredentialIdentityProvider,
})
);
});

it('throws an error if a null backendIdentifier is passed in', async () => {
assert.throws(() =>
createGraphqlDocumentGenerator({
backendIdentifier: { stackName: 'foo' },
credentialProvider: null as unknown as AwsCredentialIdentityProvider,
})
);
});
});
38 changes: 32 additions & 6 deletions packages/model-generator/src/create_graphql_document_generator.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,51 @@
import { AppSyncClient } from '@aws-sdk/client-appsync';
import {
BackendIdentifier,
BackendOutputClient,
} from '@aws-amplify/deployed-backend-client';
import { graphqlOutputKey } from '@aws-amplify/backend-output-schemas';
import { AwsCredentialIdentityProvider } from '@aws-sdk/types';
import { AppsyncGraphqlGenerationResult } from './appsync_graphql_generation_result.js';
import { AppSyncIntrospectionSchemaFetcher } from './appsync_schema_fetcher.js';
import { AppSyncGraphqlDocumentGenerator } from './graphql_document_generator.js';
import { GraphqlDocumentGenerator } from './model_generator.js';

export type GraphqlDocumentGeneratorFactoryParams = {
apiId: string;
backendIdentifier: BackendIdentifier;
credentialProvider: AwsCredentialIdentityProvider;
};

/**
* Factory function to compose a model generator
*/
export const createGraphqlDocumentGenerator = ({
apiId,
backendIdentifier,
credentialProvider,
}: GraphqlDocumentGeneratorFactoryParams): GraphqlDocumentGenerator => {
if (!apiId) {
throw new Error('`apiId` must be defined');
if (!backendIdentifier) {
throw new Error('`backendIdentifier` must be defined');
}
if (!credentialProvider) {
throw new Error('`credentialProvider` must be defined');
}

const fetchSchema = async () => {
const backendOutputClient = new BackendOutputClient(
credentialProvider,
backendIdentifier
);
const output = await backendOutputClient.getOutput();
const apiId = output[graphqlOutputKey]?.payload.awsAppsyncApiId;
if (!apiId) {
throw new Error(`Unable to determine AppSync API ID.`);
}

return new AppSyncIntrospectionSchemaFetcher(new AppSyncClient()).fetch(
apiId
);
};
return new AppSyncGraphqlDocumentGenerator(
() =>
new AppSyncIntrospectionSchemaFetcher(new AppSyncClient()).fetch(apiId),
fetchSchema,
(fileMap) => new AppsyncGraphqlGenerationResult(fileMap)
);
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { AwsCredentialIdentityProvider } from '@aws-sdk/types';
import { BackendIdentifier } from '@aws-amplify/deployed-backend-client';
import { createGraphqlTypesGenerator } from './create_graphql_types_generator.js';

describe('types generator factory', () => {
it('throws an error if a null apiId is passed in', async () => {
it('throws an error if a null backendIdentifier is passed in', async () => {
assert.throws(() =>
createGraphqlTypesGenerator({ apiId: null as unknown as string })
createGraphqlTypesGenerator({
backendIdentifier: null as unknown as BackendIdentifier,
credentialProvider: null as unknown as AwsCredentialIdentityProvider,
})
);
});

it('throws an error if a null backendIdentifier is passed in', async () => {
assert.throws(() =>
createGraphqlTypesGenerator({
backendIdentifier: { stackName: 'foo' },
credentialProvider: null as unknown as AwsCredentialIdentityProvider,
})
);
});
});
38 changes: 32 additions & 6 deletions packages/model-generator/src/create_graphql_types_generator.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,51 @@
import { AppSyncClient } from '@aws-sdk/client-appsync';
import {
BackendIdentifier,
BackendOutputClient,
} from '@aws-amplify/deployed-backend-client';
import { graphqlOutputKey } from '@aws-amplify/backend-output-schemas';
import { AwsCredentialIdentityProvider } from '@aws-sdk/types';
import { AppsyncGraphqlGenerationResult } from './appsync_graphql_generation_result.js';
import { AppSyncIntrospectionSchemaFetcher } from './appsync_schema_fetcher.js';
import { AppSyncGraphqlTypesGenerator } from './graphql_types_generator.js';
import { GraphqlTypesGenerator } from './model_generator.js';

export type GraphqlTypesGeneratorFactoryParams = {
apiId: string;
backendIdentifier: BackendIdentifier;
credentialProvider: AwsCredentialIdentityProvider;
};

/**
* Factory function to compose a model generator
*/
export const createGraphqlTypesGenerator = ({
apiId,
backendIdentifier,
credentialProvider,
}: GraphqlTypesGeneratorFactoryParams): GraphqlTypesGenerator => {
if (!apiId) {
throw new Error('`apiId` must be defined');
if (!backendIdentifier) {
throw new Error('`backendIdentifier` must be defined');
}
if (!credentialProvider) {
throw new Error('`credentialProvider` must be defined');
}

const fetchSchema = async () => {
const backendOutputClient = new BackendOutputClient(
credentialProvider,
backendIdentifier
);
const output = await backendOutputClient.getOutput();
const apiId = output[graphqlOutputKey]?.payload.awsAppsyncApiId;
if (!apiId) {
throw new Error(`Unable to determine AppSync API ID.`);
}

return new AppSyncIntrospectionSchemaFetcher(new AppSyncClient()).fetch(
apiId
);
};
return new AppSyncGraphqlTypesGenerator(
() =>
new AppSyncIntrospectionSchemaFetcher(new AppSyncClient()).fetch(apiId),
fetchSchema,
(fileMap) => new AppsyncGraphqlGenerationResult(fileMap)
);
};
17 changes: 17 additions & 0 deletions packages/model-generator/src/generate_api_code.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import assert from 'assert';
import { describe, it } from 'node:test';
import { GenerateApiCodeProps, generateApiCode } from './generate_api_code.js';

describe('generateAPICode', () => {
describe('graphql-codegen', () => {});
describe('modelgen', () => {});
describe('introspection', () => {});

it('throws error on unknown format', async () => {
const props = {
format: 'unsupported',
stackName: 'stack_name',
} as unknown as GenerateApiCodeProps;
await assert.rejects(() => generateApiCode(props));
});
});
Loading

0 comments on commit 3f26cef

Please sign in to comment.