diff --git a/package.json b/package.json index d28e31b7d1..61ff3bbecc 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "@aws-amplify/graphql-api-construct/zod", "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-auth-transformer", "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-default-value-transformer", + "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-directives", "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-function-transformer", "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-http-transformer", "@aws-amplify/graphql-api-construct/@aws-amplify/graphql-index-transformer", @@ -143,6 +144,7 @@ "@aws-amplify/data-construct/zod", "@aws-amplify/data-construct/@aws-amplify/graphql-auth-transformer", "@aws-amplify/data-construct/@aws-amplify/graphql-default-value-transformer", + "@aws-amplify/data-construct/@aws-amplify/graphql-directives", "@aws-amplify/data-construct/@aws-amplify/graphql-function-transformer", "@aws-amplify/data-construct/@aws-amplify/graphql-http-transformer", "@aws-amplify/data-construct/@aws-amplify/graphql-index-transformer", diff --git a/packages/amplify-data-construct/.jsii b/packages/amplify-data-construct/.jsii index 49c2a29f88..7b66bcbf55 100644 --- a/packages/amplify-data-construct/.jsii +++ b/packages/amplify-data-construct/.jsii @@ -10,6 +10,7 @@ "@aws-amplify/backend-output-storage": "^0.2.2", "@aws-amplify/graphql-auth-transformer": "3.4.1", "@aws-amplify/graphql-default-value-transformer": "2.3.1", + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-function-transformer": "2.1.18", "@aws-amplify/graphql-http-transformer": "2.1.18", "@aws-amplify/graphql-index-transformer": "2.3.7", @@ -3534,5 +3535,5 @@ }, "types": {}, "version": "1.6.0", - "fingerprint": "bltwvDHncl6fGB0rcExcJfIVQhpCm6cS02qM4TBqm0U=" + "fingerprint": "wAUmFljef6wr5+hst88y7j8MkILf+dkTlVPYMpcG9GU=" } \ No newline at end of file diff --git a/packages/amplify-data-construct/nonJsiiDependencies.json b/packages/amplify-data-construct/nonJsiiDependencies.json index cffdeeb99b..4d1ddd2ed4 100644 --- a/packages/amplify-data-construct/nonJsiiDependencies.json +++ b/packages/amplify-data-construct/nonJsiiDependencies.json @@ -1,6 +1,7 @@ [ "@aws-amplify/backend-output-storage", "@aws-amplify/backend-output-schemas", + "@aws-amplify/graphql-directives", "@aws-amplify/graphql-transformer", "@aws-amplify/graphql-transformer-core", "@aws-amplify/graphql-transformer-interfaces", diff --git a/packages/amplify-data-construct/package.json b/packages/amplify-data-construct/package.json index 1eafb32bfa..e1339219aa 100644 --- a/packages/amplify-data-construct/package.json +++ b/packages/amplify-data-construct/package.json @@ -41,6 +41,7 @@ "zod", "@aws-amplify/graphql-auth-transformer", "@aws-amplify/graphql-default-value-transformer", + "@aws-amplify/graphql-directives", "@aws-amplify/graphql-function-transformer", "@aws-amplify/graphql-http-transformer", "@aws-amplify/graphql-index-transformer", @@ -77,6 +78,7 @@ "@aws-amplify/graphql-api-construct": "1.6.0", "@aws-amplify/graphql-auth-transformer": "3.4.1", "@aws-amplify/graphql-default-value-transformer": "2.3.1", + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-function-transformer": "2.1.18", "@aws-amplify/graphql-http-transformer": "2.1.18", "@aws-amplify/graphql-index-transformer": "2.3.7", diff --git a/packages/amplify-graphql-api-construct/.jsii b/packages/amplify-graphql-api-construct/.jsii index b6c3f0e912..8db3b7f590 100644 --- a/packages/amplify-graphql-api-construct/.jsii +++ b/packages/amplify-graphql-api-construct/.jsii @@ -10,6 +10,7 @@ "@aws-amplify/backend-output-storage": "^0.2.2", "@aws-amplify/graphql-auth-transformer": "3.4.1", "@aws-amplify/graphql-default-value-transformer": "2.3.1", + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-function-transformer": "2.1.18", "@aws-amplify/graphql-http-transformer": "2.1.18", "@aws-amplify/graphql-index-transformer": "2.3.7", @@ -8132,5 +8133,5 @@ } }, "version": "1.6.0", - "fingerprint": "C0VXkxPFCBh6W1H9yfqkeGmab7zndoRgpNOmXR6IjoM=" + "fingerprint": "FjoH8icW+tbFrS9JKLZc/+5mZIGwfLRkRZUx4VizFKI=" } \ No newline at end of file diff --git a/packages/amplify-graphql-api-construct/nonJsiiDependencies.json b/packages/amplify-graphql-api-construct/nonJsiiDependencies.json index cffdeeb99b..4d1ddd2ed4 100644 --- a/packages/amplify-graphql-api-construct/nonJsiiDependencies.json +++ b/packages/amplify-graphql-api-construct/nonJsiiDependencies.json @@ -1,6 +1,7 @@ [ "@aws-amplify/backend-output-storage", "@aws-amplify/backend-output-schemas", + "@aws-amplify/graphql-directives", "@aws-amplify/graphql-transformer", "@aws-amplify/graphql-transformer-core", "@aws-amplify/graphql-transformer-interfaces", diff --git a/packages/amplify-graphql-api-construct/package.json b/packages/amplify-graphql-api-construct/package.json index fabcab0ed2..b5b4fe4fa0 100644 --- a/packages/amplify-graphql-api-construct/package.json +++ b/packages/amplify-graphql-api-construct/package.json @@ -38,6 +38,7 @@ "@aws-amplify/backend-output-storage", "@aws-amplify/graphql-auth-transformer", "@aws-amplify/graphql-default-value-transformer", + "@aws-amplify/graphql-directives", "@aws-amplify/graphql-function-transformer", "@aws-amplify/graphql-http-transformer", "@aws-amplify/graphql-index-transformer", @@ -77,6 +78,7 @@ "@aws-amplify/backend-output-storage": "^0.2.2", "@aws-amplify/graphql-auth-transformer": "3.4.1", "@aws-amplify/graphql-default-value-transformer": "2.3.1", + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-function-transformer": "2.1.18", "@aws-amplify/graphql-http-transformer": "2.1.18", "@aws-amplify/graphql-index-transformer": "2.3.7", diff --git a/packages/amplify-graphql-auth-transformer/API.md b/packages/amplify-graphql-auth-transformer/API.md index 7dcdeeb097..a6aab735cf 100644 --- a/packages/amplify-graphql-auth-transformer/API.md +++ b/packages/amplify-graphql-auth-transformer/API.md @@ -64,7 +64,7 @@ export interface AuthDirective { } // @public (undocumented) -export const authDirectiveDefinition = "\n directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION\n input AuthRule {\n allow: AuthStrategy!\n provider: AuthProvider\n identityClaim: String\n groupClaim: String\n ownerField: String\n groupsField: String\n groups: [String]\n operations: [ModelOperation]\n }\n enum AuthStrategy {\n owner\n groups\n private\n public\n custom\n }\n enum AuthProvider {\n apiKey\n iam\n oidc\n userPools\n function\n }\n enum ModelOperation {\n create\n update\n delete\n read\n list\n get\n sync\n listen\n search\n }\n"; +export const authDirectiveDefinition: string; // @public (undocumented) export type AuthProvider = 'apiKey' | 'iam' | 'oidc' | 'userPools' | 'function'; diff --git a/packages/amplify-graphql-auth-transformer/package.json b/packages/amplify-graphql-auth-transformer/package.json index d099512807..a7bceb651f 100644 --- a/packages/amplify-graphql-auth-transformer/package.json +++ b/packages/amplify-graphql-auth-transformer/package.json @@ -29,6 +29,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-model-transformer": "2.6.0", "@aws-amplify/graphql-relational-transformer": "2.4.1", "@aws-amplify/graphql-transformer-core": "2.5.0", diff --git a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts index 9da63ec785..36a19d39f6 100644 --- a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts +++ b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts @@ -63,6 +63,7 @@ import { getSortKeyConnectionAttributeName, getObjectPrimaryKey, } from '@aws-amplify/graphql-relational-transformer'; +import { AuthDirective } from '@aws-amplify/graphql-directives'; import { AccessControlMatrix } from './accesscontrol'; import { AUTH_PROVIDER_DIRECTIVE_MAP, @@ -75,7 +76,6 @@ import { MODEL_OPERATIONS, SEARCHABLE_AGGREGATE_TYPES, AuthRule, - authDirectiveDefinition, ConfiguredAuthProviders, getConfiguredAuthProviders, collectFieldNames, @@ -181,7 +181,7 @@ export class AuthTransformer extends TransformerAuthBase implements TransformerA * constructor for creating AuthTransformer */ constructor() { - super('amplify-auth-transformer', authDirectiveDefinition); + super('amplify-auth-transformer', AuthDirective.definition); this.modelDirectiveConfig = new Map(); this.seenNonModelTypes = new Map(); this.authModelConfig = new Map(); diff --git a/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts index 0a6758bd22..5e3d6baa28 100644 --- a/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts +++ b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts @@ -1,4 +1,5 @@ import { GetArgumentsOptions } from '@aws-amplify/graphql-transformer-core'; +import { AuthDirective } from '@aws-amplify/graphql-directives'; /** * AuthStrategy @@ -104,41 +105,4 @@ export interface ConfiguredAuthProviders { shouldAddDefaultServiceDirective: boolean; } -export const authDirectiveDefinition = ` - directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION - input AuthRule { - allow: AuthStrategy! - provider: AuthProvider - identityClaim: String - groupClaim: String - ownerField: String - groupsField: String - groups: [String] - operations: [ModelOperation] - } - enum AuthStrategy { - owner - groups - private - public - custom - } - enum AuthProvider { - apiKey - iam - oidc - userPools - function - } - enum ModelOperation { - create - update - delete - read - list - get - sync - listen - search - } -`; +export const authDirectiveDefinition = AuthDirective.definition; diff --git a/packages/amplify-graphql-auth-transformer/tsconfig.json b/packages/amplify-graphql-auth-transformer/tsconfig.json index b3731dfabc..aa1c4be7c0 100644 --- a/packages/amplify-graphql-auth-transformer/tsconfig.json +++ b/packages/amplify-graphql-auth-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-model-transformer" }, diff --git a/packages/amplify-graphql-default-value-transformer/package.json b/packages/amplify-graphql-default-value-transformer/package.json index 162ddd8714..c4e35396d9 100644 --- a/packages/amplify-graphql-default-value-transformer/package.json +++ b/packages/amplify-graphql-default-value-transformer/package.json @@ -29,6 +29,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts index bf0362c8ee..15c76e22a5 100644 --- a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts +++ b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts @@ -13,6 +13,7 @@ import { TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { DefaultDirective } from '@aws-amplify/graphql-directives'; import { DirectiveNode, EnumTypeDefinitionNode, @@ -28,11 +29,6 @@ import { getBaseType, isEnum, isListType, isScalarOrEnum, ModelResourceIDs, toCa import { DefaultValueDirectiveConfiguration } from './types'; import { TypeValidators } from './validators'; -const directiveName = 'default'; -const directiveDefinition = ` - directive @${directiveName}(value: String!) on FIELD_DEFINITION -`; - const nonStringTypes = ['Int', 'Float', 'Boolean', 'AWSTimestamp', 'AWSJSON']; const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, type: TypeNode): void => { @@ -93,7 +89,7 @@ export class DefaultValueTransformer extends TransformerPluginBase { private directiveMap = new Map(); constructor() { - super('amplify-default-value-transformer', directiveDefinition); + super('amplify-default-value-transformer', DefaultDirective.definition); } field = ( diff --git a/packages/amplify-graphql-default-value-transformer/tsconfig.json b/packages/amplify-graphql-default-value-transformer/tsconfig.json index e787a97eaa..9b22cf80b2 100644 --- a/packages/amplify-graphql-default-value-transformer/tsconfig.json +++ b/packages/amplify-graphql-default-value-transformer/tsconfig.json @@ -4,5 +4,9 @@ "rootDir": "src", "outDir": "lib" }, - "references": [{ "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }] + "references": [ + { "path": "../amplify-graphql-directives" }, + { "path": "../amplify-graphql-transformer-interfaces" }, + { "path": "../graphql-mapping-template" } + ] } diff --git a/packages/amplify-graphql-directives/.npmignore b/packages/amplify-graphql-directives/.npmignore new file mode 100644 index 0000000000..3ee5d55b0b --- /dev/null +++ b/packages/amplify-graphql-directives/.npmignore @@ -0,0 +1,5 @@ +**/__mocks__/** +**/__tests__/** +src +tsconfig.json +tsconfig.tsbuildinfo diff --git a/packages/amplify-graphql-directives/API.md b/packages/amplify-graphql-directives/API.md new file mode 100644 index 0000000000..e8b3078c4e --- /dev/null +++ b/packages/amplify-graphql-directives/API.md @@ -0,0 +1,158 @@ +## API Report File for "@aws-amplify/graphql-directives" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public (undocumented) +export const AppSyncDirectives: readonly Directive[]; + +// @public (undocumented) +export const AuthDirective: Directive; + +// @public (undocumented) +export const AuthDirectiveV1: Directive; + +// @public (undocumented) +export const AwsApiKeyDirective: Directive; + +// @public (undocumented) +export const AwsAuthDirective: Directive; + +// @public (undocumented) +export const AwsCognitoUserPoolsDirective: Directive; + +// @public (undocumented) +export const AwsIamDirective: Directive; + +// @public (undocumented) +export const AwsLambdaDirective: Directive; + +// @public (undocumented) +export const AwsOidcDirective: Directive; + +// @public (undocumented) +export const AwsSubscribeDirective: Directive; + +// @public (undocumented) +export const BelongsToDirective: Directive; + +// @public (undocumented) +export const ConnectionDirectiveV1: Directive; + +// @public (undocumented) +export const DefaultDirective: Directive; + +// @public (undocumented) +export const DefaultDirectives: readonly Directive[]; + +// @public (undocumented) +export const DeprecatedDirective: Directive; + +// @public (undocumented) +export interface Directive { + // (undocumented) + readonly defaults: Defaults; + // (undocumented) + readonly definition: string; + // (undocumented) + readonly name: string; +} + +// @public (undocumented) +export interface DirectiveDefaults { +} + +// @public (undocumented) +export const FunctionDirective: Directive; + +// @public (undocumented) +export const FunctionDirectiveV1: Directive; + +// @public (undocumented) +export const HasManyDirective: Directive; + +// @public (undocumented) +export type HasManyDirectiveDefaults = { + limit: number; +}; + +// @public (undocumented) +export const HasOneDirective: Directive; + +// @public (undocumented) +export const HttpDirective: Directive; + +// @public (undocumented) +export type HttpDirectiveDefaults = { + method: string; + headers: string[]; +}; + +// Warning: (ae-forgotten-export) The symbol "HttpDirectiveV1Defaults" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export const HttpDirectiveV1: Directive; + +// @public (undocumented) +export const IndexDirective: Directive; + +// @public (undocumented) +export const KeyDirectiveV1: Directive; + +// @public (undocumented) +export const ManyToManyDirective: Directive; + +// @public (undocumented) +export type ManyToManyDirectiveDefaults = { + limit: number; +}; + +// @public (undocumented) +export const MapsToDirective: Directive; + +// @public (undocumented) +export const ModelDirective: Directive; + +// @public (undocumented) +export const ModelDirectiveV1: Directive; + +// @public (undocumented) +export const PredictionsDirective: Directive; + +// @public (undocumented) +export const PredictionsDirectiveV1: Directive; + +// @public (undocumented) +export const PrimaryKeyDirective: Directive; + +// @public (undocumented) +export const RefersToDirective: Directive; + +// @public (undocumented) +export const SearchableDirective: Directive; + +// @public (undocumented) +export const SearchableDirectiveV1: Directive; + +// @public (undocumented) +export const SqlDirective: Directive; + +// @public (undocumented) +export const V1Directives: readonly Directive[]; + +// @public (undocumented) +export const V2Directives: readonly Directive[]; + +// @public (undocumented) +export const VersionedDirectiveV1: Directive; + +// @public (undocumented) +export type VersionedDirectiveV1Defaults = { + versionField: string; + versionInput: string; +}; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/amplify-graphql-directives/Readme.md b/packages/amplify-graphql-directives/Readme.md new file mode 100644 index 0000000000..05ced1e24b --- /dev/null +++ b/packages/amplify-graphql-directives/Readme.md @@ -0,0 +1,19 @@ +# Amplify GraphQL Directives + +Source of truth for the GraphQL directive definition used by the Amplify GraphQL API. + +> :warning: **Intended for internal Amplify use only.** + +## Description + +This package defines the GraphQL directives in GraphQL syntax. +Each directive is imported into the corresponding GraphQL transformer. +This package is responsible for the name, definition, and argument defaults for a directive. +The GraphQL transformers utilize the GraphQL directives to define the behavior of the transform. + +This package also contains the AppSync GraphQL directives. +These directives are defined internally by AppSync. +The definitions here are copied from the internal definition. + +This package is intended to be the only source of truth for the GraphQL directive definitions used by the Amplify GraphQL API. +This package should be imported in place of reproducing the definitions in other packages. diff --git a/packages/amplify-graphql-directives/package.json b/packages/amplify-graphql-directives/package.json new file mode 100644 index 0000000000..3e40076d87 --- /dev/null +++ b/packages/amplify-graphql-directives/package.json @@ -0,0 +1,65 @@ +{ + "name": "@aws-amplify/graphql-directives", + "version": "1.0.0", + "description": "Directive definitions for Amplify GraphQL transformers.", + "repository": { + "type": "git", + "url": "https://github.com/aws-amplify/amplify-category-api.git", + "directory": "packages/amplify-graphql-directives" + }, + "author": "Amazon Web Services", + "license": "Apache-2.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "keywords": [ + "graphql", + "aws", + "amplify" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "clean": "rimraf ./lib", + "test": "jest", + "extract-api": "ts-node ../../scripts/extract-api.ts" + }, + "jest": { + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testURL": "http://localhost", + "testRegex": "(src/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "collectCoverage": true, + "coverageProvider": "v8", + "coverageThreshold": { + "global": { + "branches": 100, + "functions": 100, + "lines": 100 + } + }, + "coverageReporters": [ + "clover", + "text" + ], + "testEnvironment": "../../FixJestEnvironment.js", + "collectCoverageFrom": [ + "src/**/*.ts" + ], + "coveragePathIgnorePatterns": [ + "/__tests__/", + "src/directives/directive.ts" + ] + } +} diff --git a/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap b/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000..631d1e8e4b --- /dev/null +++ b/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap @@ -0,0 +1,632 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Directive Definitions AuthDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION + input AuthRule { + allow: AuthStrategy! + provider: AuthProvider + identityClaim: String + groupClaim: String + ownerField: String + groupsField: String + groups: [String] + operations: [ModelOperation] + } + enum AuthStrategy { + owner + groups + private + public + custom + } + enum AuthProvider { + apiKey + iam + oidc + userPools + function + } + enum ModelOperation { + create + update + delete + read + list + get + sync + listen + search + } +", + "name": "auth", +} +`; + +exports[`Directive Definitions AuthDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION + input AuthRule { + # Specifies the auth rule's strategy. Allowed values are 'owner', 'groups', 'public', 'private'. + allow: AuthStrategy! + + # Legacy name for identityClaim + identityField: String @deprecated(reason: \\"The 'identityField' argument is replaced by the 'identityClaim'.\\") + + # Specifies the name of the provider to use for the rule. This overrides the default provider + # when 'public' and 'private' AuthStrategy is used. Specifying a provider for 'owner' or 'groups' + # are not allowed. + provider: AuthProvider + + # Specifies the name of the claim to look for on the request's JWT token + # from Cognito User Pools (and in the future OIDC) that contains the identity + # of the user. If 'allow' is 'groups', this value should point to a list of groups + # in the claims. If 'allow' is 'owner', this value should point to the logged in user identity string. + # Defaults to \\"cognito:username\\" for Cognito User Pools auth. + identityClaim: String + + # Allows for custom config of 'groups' which is validated against the JWT + # Specifies a static list of groups that should have access to the object + groupClaim: String + + # Allowed when the 'allow' argument is 'owner'. + # Specifies the field of type String or [String] that contains owner(s) that can access the object. + ownerField: String # defaults to \\"owner\\" + # Allowed when the 'allow' argument is 'groups'. + # Specifies the field of type String or [String] that contains group(s) that can access the object. + groupsField: String + + # Allowed when the 'allow' argument is 'groups'. + # Specifies a static list of groups that should have access to the object. + groups: [String] + + # Specifies operations to which this auth rule should be applied. + operations: [ModelOperation] + + # Deprecated. It is recommended to use the 'operations' arguments. + queries: [ModelQuery] @deprecated(reason: \\"The 'queries' argument will be replaced by the 'operations' argument in a future release.\\") + + # Deprecated. It is recommended to use the 'operations' arguments. + mutations: [ModelMutation] + @deprecated(reason: \\"The 'mutations' argument will be replaced by the 'operations' argument in a future release.\\") + } + enum AuthStrategy { + owner + groups + private + public + } + enum AuthProvider { + apiKey + iam + oidc + userPools + } + enum ModelOperation { + create + update + delete + read + } + enum ModelQuery @deprecated(reason: \\"ModelQuery will be replaced by the 'ModelOperation' in a future release.\\") { + get + list + } + enum ModelMutation @deprecated(reason: \\"ModelMutation will be replaced by the 'ModelOperation' in a future release.\\") { + create + update + delete + } +", + "name": "auth", +} +`; + +exports[`Directive Definitions AwsApiKeyDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_api_key on FIELD_DEFINITION | OBJECT +", + "name": "aws_api_key", +} +`; + +exports[`Directive Definitions AwsAuthDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_auth(cognito_groups: [String!]!) on FIELD_DEFINITION +", + "name": "aws_auth", +} +`; + +exports[`Directive Definitions AwsCognitoUserPoolsDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_cognito_user_pools(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT +", + "name": "aws_cognito_user_pools", +} +`; + +exports[`Directive Definitions AwsIamDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_iam on FIELD_DEFINITION | OBJECT +", + "name": "aws_iam", +} +`; + +exports[`Directive Definitions AwsLambdaDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_lambda on FIELD_DEFINITION | OBJECT +", + "name": "aws_lambda", +} +`; + +exports[`Directive Definitions AwsOidcDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_oidc on FIELD_DEFINITION | OBJECT +", + "name": "aws_oidc", +} +`; + +exports[`Directive Definitions AwsSubscribeDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION +", + "name": "aws_subscribe", +} +`; + +exports[`Directive Definitions BelongsToDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @belongsTo(fields: [String!], references: [String!]) on FIELD_DEFINITION +", + "name": "belongsTo", +} +`; + +exports[`Directive Definitions ConnectionDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @connection( + name: String + keyField: String + sortField: String + keyName: String + limit: Int + fields: [String!] + ) on FIELD_DEFINITION +", + "name": "connection", +} +`; + +exports[`Directive Definitions DefaultDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @default(value: String!) on FIELD_DEFINITION +", + "name": "default", +} +`; + +exports[`Directive Definitions DeprecatedDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @deprecated(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE +", + "name": "deprecated", +} +`; + +exports[`Directive Definitions FunctionDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @function(name: String!, region: String, accountId: String) repeatable on FIELD_DEFINITION +", + "name": "function", +} +`; + +exports[`Directive Definitions FunctionDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @function(name: String!, region: String) repeatable on FIELD_DEFINITION +", + "name": "function", +} +`; + +exports[`Directive Definitions HasManyDirective 1`] = ` +Object { + "defaults": Object { + "limit": 100, + }, + "definition": " + directive @hasMany(indexName: String, fields: [String!], references: [String!], limit: Int = 100) on FIELD_DEFINITION +", + "name": "hasMany", +} +`; + +exports[`Directive Definitions HasOneDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @hasOne(fields: [String!], references: [String!]) on FIELD_DEFINITION +", + "name": "hasOne", +} +`; + +exports[`Directive Definitions HttpDirective 1`] = ` +Object { + "defaults": Object { + "headers": Array [], + "method": "GET", + }, + "definition": " + directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION + enum HttpMethod { + GET + POST + PUT + DELETE + PATCH + } + input HttpHeader { + key: String + value: String + } +", + "name": "http", +} +`; + +exports[`Directive Definitions HttpDirectiveV1 1`] = ` +Object { + "defaults": Object { + "headers": Array [], + "method": "GET", + }, + "definition": " + directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION + enum HttpMethod { + GET + POST + PUT + DELETE + PATCH + } + input HttpHeader { + key: String + value: String + } +", + "name": "http", +} +`; + +exports[`Directive Definitions IndexDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @index(name: String, sortKeyFields: [String], queryField: String) repeatable on FIELD_DEFINITION +", + "name": "index", +} +`; + +exports[`Directive Definitions KeyDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @key(name: String, fields: [String!]!, queryField: String) repeatable on OBJECT +", + "name": "key", +} +`; + +exports[`Directive Definitions ManyToManyDirective 1`] = ` +Object { + "defaults": Object { + "limit": 100, + }, + "definition": " + directive @manyToMany(relationName: String!, limit: Int = 100) on FIELD_DEFINITION +", + "name": "manyToMany", +} +`; + +exports[`Directive Definitions MapsToDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @mapsTo(name: String!) on OBJECT +", + "name": "mapsTo", +} +`; + +exports[`Directive Definitions ModelDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @model( + queries: ModelQueryMap + mutations: ModelMutationMap + subscriptions: ModelSubscriptionMap + timestamps: TimestampConfiguration + ) on OBJECT + input ModelMutationMap { + create: String + update: String + delete: String + } + input ModelQueryMap { + get: String + list: String + } + input ModelSubscriptionMap { + onCreate: [String] + onUpdate: [String] + onDelete: [String] + level: ModelSubscriptionLevel + } + enum ModelSubscriptionLevel { + off + public + on + } + input TimestampConfiguration { + createdAt: String + updatedAt: String + } +", + "name": "model", +} +`; + +exports[`Directive Definitions ModelDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @model( + queries: ModelQueryMap + mutations: ModelMutationMap + subscriptions: ModelSubscriptionMap + timestamps: TimestampConfiguration + ) on OBJECT + input ModelMutationMap { + create: String + update: String + delete: String + } + input ModelQueryMap { + get: String + list: String + } + input ModelSubscriptionMap { + onCreate: [String] + onUpdate: [String] + onDelete: [String] + level: ModelSubscriptionLevel + } + enum ModelSubscriptionLevel { + off + public + on + } + input TimestampConfiguration { + createdAt: String + updatedAt: String + } +", + "name": "model", +} +`; + +exports[`Directive Definitions PredictionsDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION + enum PredictionsActions { + identifyText + identifyLabels + convertTextToSpeech + translateText + } +", + "name": "predictions", +} +`; + +exports[`Directive Definitions PredictionsDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION + enum PredictionsActions { + identifyText + identifyLabels + convertTextToSpeech + translateText + } +", + "name": "predictions", +} +`; + +exports[`Directive Definitions PrimaryKeyDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @primaryKey(sortKeyFields: [String]) on FIELD_DEFINITION +", + "name": "primaryKey", +} +`; + +exports[`Directive Definitions RefersToDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @refersTo(name: String!) on OBJECT | FIELD_DEFINITION +", + "name": "refersTo", +} +`; + +exports[`Directive Definitions SearchableDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @searchable(queries: SearchableQueryMap) on OBJECT + input SearchableQueryMap { + search: String + } +", + "name": "searchable", +} +`; + +exports[`Directive Definitions SearchableDirectiveV1 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @searchable(queries: SearchableQueryMap) on OBJECT + input SearchableQueryMap { + search: String + } +", + "name": "searchable", +} +`; + +exports[`Directive Definitions SqlDirective 1`] = ` +Object { + "defaults": Object {}, + "definition": " + directive @sql(statement: String, reference: String) on FIELD_DEFINITION +", + "name": "sql", +} +`; + +exports[`Directive Definitions VersionedDirectiveV1 1`] = ` +Object { + "defaults": Object { + "versionField": "version", + "versionInput": "expectedVersion", + }, + "definition": " + directive @versioned(versionField: String = \\"version\\", versionInput: String = \\"expectedVersion\\") on OBJECT +", + "name": "versioned", +} +`; + +exports[`Directive Definitions include correct directives in AppSync directives 1`] = ` +Array [ + "aws_api_key", + "aws_auth", + "aws_cognito_user_pools", + "aws_iam", + "aws_lambda", + "aws_oidc", + "aws_subscribe", +] +`; + +exports[`Directive Definitions include correct directives in V1 directives 1`] = ` +Array [ + "auth", + "connection", + "function", + "http", + "key", + "model", + "predictions", + "searchable", + "versioned", +] +`; + +exports[`Directive Definitions include correct directives in V2 directives 1`] = ` +Array [ + "auth", + "belongsTo", + "default", + "deprecated", + "function", + "hasMany", + "hasOne", + "http", + "index", + "manyToMany", + "mapsTo", + "model", + "predictions", + "primaryKey", + "refersTo", + "searchable", + "sql", +] +`; + +exports[`Directive Definitions include correct directives in default directives 1`] = ` +Array [ + "aws_api_key", + "aws_auth", + "aws_cognito_user_pools", + "aws_iam", + "aws_lambda", + "aws_oidc", + "aws_subscribe", + "auth", + "belongsTo", + "default", + "deprecated", + "function", + "hasMany", + "hasOne", + "http", + "index", + "manyToMany", + "mapsTo", + "model", + "predictions", + "primaryKey", + "refersTo", + "searchable", + "sql", +] +`; diff --git a/packages/amplify-graphql-directives/src/__tests__/index.test.ts b/packages/amplify-graphql-directives/src/__tests__/index.test.ts new file mode 100644 index 0000000000..0c666e19d2 --- /dev/null +++ b/packages/amplify-graphql-directives/src/__tests__/index.test.ts @@ -0,0 +1,62 @@ +import { parse } from 'graphql'; +import * as Directives from '..'; +import type { Directive } from '..'; +import { AppSyncDirectives, DefaultDirectives, V1Directives, V2Directives } from '..'; + +describe('Directive Definitions', () => { + // remove lists of Directives, i.e. AppSyncDirectives, DefaultDirectives, V1Directives, and V2Directives + test.each(Object.entries(Directives).filter(([_, directive]) => !Array.isArray(directive)) as unknown as [string, Directive][])( + '%s', + (_, directive: Directive) => { + // assert valid graphql syntax + expect(() => parse(directive.definition)).not.toThrow(); + + // assert no changes to directive + expect(directive).toMatchSnapshot(); + }, + ); + + test('include correct directives in AppSync directives', () => { + expect(AppSyncDirectives.map((directive) => directive.name)).toMatchSnapshot(); + }); + + test('no negative interactions for AppSync directives', () => { + const directives = AppSyncDirectives.map((directive) => directive.definition).join('\n'); + + // asserts directives can be parsed together + expect(() => parse(directives)).not.toThrow(); + }); + + test('include correct directives in V2 directives', () => { + expect(V2Directives.map((directive) => directive.name)).toMatchSnapshot(); + }); + + test('no negative interactions for V2 directives', () => { + const directives = V2Directives.map((directive) => directive.definition).join('\n'); + + // asserts directives can be parsed together + expect(() => parse(directives)).not.toThrow(); + }); + + test('include correct directives in default directives', () => { + expect(DefaultDirectives.map((directive) => directive.name)).toMatchSnapshot(); + }); + + test('no negative interactions for default directives', () => { + const directives = DefaultDirectives.map((directive) => directive.definition).join('\n'); + + // asserts directives can be parsed together + expect(() => parse(directives)).not.toThrow(); + }); + + test('include correct directives in V1 directives', () => { + expect(V1Directives.map((directive) => directive.name)).toMatchSnapshot(); + }); + + test('no negative interactions for V1 directives', () => { + const directives = V1Directives.map((directive) => directive.definition).join('\n'); + + // asserts directives can be parsed together + expect(() => parse(directives)).not.toThrow(); + }); +}); diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-api-key.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-api-key.ts new file mode 100644 index 0000000000..3674a0cf9c --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-api-key.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_api_key'; +const definition = /* GraphQL */ ` + directive @${name} on FIELD_DEFINITION | OBJECT +`; +const defaults = {}; + +export const AwsApiKeyDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-auth.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-auth.ts new file mode 100644 index 0000000000..c54cc4c964 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-auth.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_auth'; +const definition = /* GraphQL */ ` + directive @${name}(cognito_groups: [String!]!) on FIELD_DEFINITION +`; +const defaults = {}; + +export const AwsAuthDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-cognito-user-pools.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-cognito-user-pools.ts new file mode 100644 index 0000000000..16e8431113 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-cognito-user-pools.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_cognito_user_pools'; +const definition = /* GraphQL */ ` + directive @${name}(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT +`; +const defaults = {}; + +export const AwsCognitoUserPoolsDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-iam.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-iam.ts new file mode 100644 index 0000000000..8f77b68da5 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-iam.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_iam'; +const definition = /* GraphQL */ ` + directive @${name} on FIELD_DEFINITION | OBJECT +`; +const defaults = {}; + +export const AwsIamDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-lambda.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-lambda.ts new file mode 100644 index 0000000000..623eb9f623 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-lambda.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_lambda'; +const definition = /* GraphQL */ ` + directive @${name} on FIELD_DEFINITION | OBJECT +`; +const defaults = {}; + +export const AwsLambdaDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-oidc.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-oidc.ts new file mode 100644 index 0000000000..244eb6024b --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-oidc.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_oidc'; +const definition = /* GraphQL */ ` + directive @${name} on FIELD_DEFINITION | OBJECT +`; +const defaults = {}; + +export const AwsOidcDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/aws-subscribe.ts b/packages/amplify-graphql-directives/src/directives/appsync/aws-subscribe.ts new file mode 100644 index 0000000000..bde6f57e4b --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/aws-subscribe.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'aws_subscribe'; +const definition = /* GraphQL */ ` + directive @${name}(mutations: [String!]!) on FIELD_DEFINITION +`; +const defaults = {}; + +export const AwsSubscribeDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/appsync/index.ts b/packages/amplify-graphql-directives/src/directives/appsync/index.ts new file mode 100644 index 0000000000..142ff5151b --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/appsync/index.ts @@ -0,0 +1,7 @@ +export { AwsSubscribeDirective } from './aws-subscribe'; +export { AwsAuthDirective } from './aws-auth'; +export { AwsApiKeyDirective } from './aws-api-key'; +export { AwsIamDirective } from './aws-iam'; +export { AwsOidcDirective } from './aws-oidc'; +export { AwsCognitoUserPoolsDirective } from './aws-cognito-user-pools'; +export { AwsLambdaDirective } from './aws-lambda'; diff --git a/packages/amplify-graphql-directives/src/directives/auth.ts b/packages/amplify-graphql-directives/src/directives/auth.ts new file mode 100644 index 0000000000..4b1cefa2ef --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/auth.ts @@ -0,0 +1,48 @@ +import { Directive } from './directive'; + +const name = 'auth'; +const definition = /* GraphQL */ ` + directive @${name}(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION + input AuthRule { + allow: AuthStrategy! + provider: AuthProvider + identityClaim: String + groupClaim: String + ownerField: String + groupsField: String + groups: [String] + operations: [ModelOperation] + } + enum AuthStrategy { + owner + groups + private + public + custom + } + enum AuthProvider { + apiKey + iam + oidc + userPools + function + } + enum ModelOperation { + create + update + delete + read + list + get + sync + listen + search + } +`; +const defaults = {}; + +export const AuthDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/belongs-to.ts b/packages/amplify-graphql-directives/src/directives/belongs-to.ts new file mode 100644 index 0000000000..25748bb867 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/belongs-to.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'belongsTo'; +const definition = /* GraphQL */ ` + directive @${name}(fields: [String!], references: [String!]) on FIELD_DEFINITION +`; +const defaults = {}; + +export const BelongsToDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/default.ts b/packages/amplify-graphql-directives/src/directives/default.ts new file mode 100644 index 0000000000..4aa8c33020 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/default.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'default'; +const definition = /* GraphQL */ ` + directive @${name}(value: String!) on FIELD_DEFINITION +`; +const defaults = {}; + +export const DefaultDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/deprecated.ts b/packages/amplify-graphql-directives/src/directives/deprecated.ts new file mode 100644 index 0000000000..47d6109844 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/deprecated.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'deprecated'; +const definition = /* GraphQL */ ` + directive @${name}(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE +`; +const defaults = {}; + +export const DeprecatedDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/directive.ts b/packages/amplify-graphql-directives/src/directives/directive.ts new file mode 100644 index 0000000000..c593cfa119 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/directive.ts @@ -0,0 +1,7 @@ +export interface DirectiveDefaults {} + +export interface Directive { + readonly name: string; + readonly definition: string; + readonly defaults: Defaults; +} diff --git a/packages/amplify-graphql-directives/src/directives/function.ts b/packages/amplify-graphql-directives/src/directives/function.ts new file mode 100644 index 0000000000..fb11f8f9d3 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/function.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'function'; +const definition = /* GraphQL */ ` + directive @${name}(name: String!, region: String, accountId: String) repeatable on FIELD_DEFINITION +`; +const defaults = {}; + +export const FunctionDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/has-many.ts b/packages/amplify-graphql-directives/src/directives/has-many.ts new file mode 100644 index 0000000000..2d8e97d0e8 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/has-many.ts @@ -0,0 +1,16 @@ +import { Directive } from './directive'; + +export type HasManyDirectiveDefaults = { limit: number }; +const name = 'hasMany'; +const defaults: HasManyDirectiveDefaults = { + limit: 100, +}; +const definition = /* GraphQL */ ` + directive @${name}(indexName: String, fields: [String!], references: [String!], limit: Int = ${defaults.limit}) on FIELD_DEFINITION +`; + +export const HasManyDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/has-one.ts b/packages/amplify-graphql-directives/src/directives/has-one.ts new file mode 100644 index 0000000000..46ebbc8d88 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/has-one.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'hasOne'; +const definition = /* GraphQL */ ` + directive @${name}(fields: [String!], references: [String!]) on FIELD_DEFINITION +`; +const defaults = {}; + +export const HasOneDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/http.ts b/packages/amplify-graphql-directives/src/directives/http.ts new file mode 100644 index 0000000000..ecd281def6 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/http.ts @@ -0,0 +1,30 @@ +import { Directive } from './directive'; + +export type HttpDirectiveDefaults = { method: string; headers: string[] }; +const name = 'http'; +const defaults: HttpDirectiveDefaults = { + method: 'GET', + headers: [], +}; +const definition = /* GraphQL */ ` + directive @${name}(method: HttpMethod = ${defaults.method}, url: String!, headers: [HttpHeader] = ${JSON.stringify( + defaults.headers, +)}) on FIELD_DEFINITION + enum HttpMethod { + GET + POST + PUT + DELETE + PATCH + } + input HttpHeader { + key: String + value: String + } +`; + +export const HttpDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/index-directive.ts b/packages/amplify-graphql-directives/src/directives/index-directive.ts new file mode 100644 index 0000000000..bdc6695da8 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/index-directive.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'index'; +const definition = /* GraphQL */ ` + directive @${name}(name: String, sortKeyFields: [String], queryField: String) repeatable on FIELD_DEFINITION +`; +const defaults = {}; + +export const IndexDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/index.ts b/packages/amplify-graphql-directives/src/directives/index.ts new file mode 100644 index 0000000000..d12bdf4290 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/index.ts @@ -0,0 +1,20 @@ +export type { Directive, DirectiveDefaults } from './directive'; +export * from './appsync'; +export * from './v1'; +export { AuthDirective } from './auth'; +export { BelongsToDirective } from './belongs-to'; +export { DefaultDirective } from './default'; +export { DeprecatedDirective } from './deprecated'; +export { FunctionDirective } from './function'; +export { HasManyDirective, HasManyDirectiveDefaults } from './has-many'; +export { HasOneDirective } from './has-one'; +export { HttpDirective, HttpDirectiveDefaults } from './http'; +export { IndexDirective } from './index-directive'; +export { ManyToManyDirective, ManyToManyDirectiveDefaults } from './many-to-many'; +export { MapsToDirective } from './maps-to'; +export { ModelDirective } from './model'; +export { PredictionsDirective } from './predictions'; +export { PrimaryKeyDirective } from './primary-key'; +export { RefersToDirective } from './refers-to'; +export { SearchableDirective } from './searchable'; +export { SqlDirective } from './sql'; diff --git a/packages/amplify-graphql-directives/src/directives/many-to-many.ts b/packages/amplify-graphql-directives/src/directives/many-to-many.ts new file mode 100644 index 0000000000..9e4e638213 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/many-to-many.ts @@ -0,0 +1,16 @@ +import { Directive } from './directive'; + +export type ManyToManyDirectiveDefaults = { limit: number }; +const name = 'manyToMany'; +const defaults: ManyToManyDirectiveDefaults = { + limit: 100, +}; +const definition = /* GraphQL */ ` + directive @${name}(relationName: String!, limit: Int = ${defaults.limit}) on FIELD_DEFINITION +`; + +export const ManyToManyDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/maps-to.ts b/packages/amplify-graphql-directives/src/directives/maps-to.ts new file mode 100644 index 0000000000..f9dc07df6d --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/maps-to.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'mapsTo'; +const definition = /* GraphQL */ ` + directive @${name}(name: String!) on OBJECT +`; +const defaults = {}; + +export const MapsToDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/model.ts b/packages/amplify-graphql-directives/src/directives/model.ts new file mode 100644 index 0000000000..803d30cf0d --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/model.ts @@ -0,0 +1,42 @@ +import { Directive } from './directive'; + +const name = 'model'; +const definition = /* GraphQL */ ` + directive @model( + queries: ModelQueryMap + mutations: ModelMutationMap + subscriptions: ModelSubscriptionMap + timestamps: TimestampConfiguration + ) on OBJECT + input ModelMutationMap { + create: String + update: String + delete: String + } + input ModelQueryMap { + get: String + list: String + } + input ModelSubscriptionMap { + onCreate: [String] + onUpdate: [String] + onDelete: [String] + level: ModelSubscriptionLevel + } + enum ModelSubscriptionLevel { + off + public + on + } + input TimestampConfiguration { + createdAt: String + updatedAt: String + } +`; +const defaults = {}; + +export const ModelDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/predictions.ts b/packages/amplify-graphql-directives/src/directives/predictions.ts new file mode 100644 index 0000000000..69f79ee1e1 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/predictions.ts @@ -0,0 +1,19 @@ +import { Directive } from './directive'; + +const name = 'predictions'; +const definition = /* GraphQL */ ` + directive @${name}(actions: [PredictionsActions!]!) on FIELD_DEFINITION + enum PredictionsActions { + identifyText + identifyLabels + convertTextToSpeech + translateText + } +`; +const defaults = {}; + +export const PredictionsDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/primary-key.ts b/packages/amplify-graphql-directives/src/directives/primary-key.ts new file mode 100644 index 0000000000..a506cc19a1 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/primary-key.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'primaryKey'; +const definition = /* GraphQL */ ` + directive @${name}(sortKeyFields: [String]) on FIELD_DEFINITION +`; +const defaults = {}; + +export const PrimaryKeyDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/refers-to.ts b/packages/amplify-graphql-directives/src/directives/refers-to.ts new file mode 100644 index 0000000000..7f8d173c22 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/refers-to.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'refersTo'; +const definition = /* GraphQL */ ` + directive @${name}(name: String!) on OBJECT | FIELD_DEFINITION +`; +const defaults = {}; + +export const RefersToDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/searchable.ts b/packages/amplify-graphql-directives/src/directives/searchable.ts new file mode 100644 index 0000000000..45571c49f8 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/searchable.ts @@ -0,0 +1,16 @@ +import { Directive } from './directive'; + +const name = 'searchable'; +const definition = /* GraphQL */ ` + directive @${name}(queries: SearchableQueryMap) on OBJECT + input SearchableQueryMap { + search: String + } +`; +const defaults = {}; + +export const SearchableDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/sql.ts b/packages/amplify-graphql-directives/src/directives/sql.ts new file mode 100644 index 0000000000..91ee15e868 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/sql.ts @@ -0,0 +1,13 @@ +import { Directive } from './directive'; + +const name = 'sql'; +const definition = /* GraphQL */ ` + directive @${name}(statement: String, reference: String) on FIELD_DEFINITION +`; +const defaults = {}; + +export const SqlDirective: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/auth.ts b/packages/amplify-graphql-directives/src/directives/v1/auth.ts new file mode 100644 index 0000000000..cf125d0bfc --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/auth.ts @@ -0,0 +1,84 @@ +import { Directive } from '../directive'; + +const name = 'auth'; +const definition = /* GraphQL */ ` + directive @${name}(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION + input AuthRule { + # Specifies the auth rule's strategy. Allowed values are 'owner', 'groups', 'public', 'private'. + allow: AuthStrategy! + + # Legacy name for identityClaim + identityField: String @deprecated(reason: "The 'identityField' argument is replaced by the 'identityClaim'.") + + # Specifies the name of the provider to use for the rule. This overrides the default provider + # when 'public' and 'private' AuthStrategy is used. Specifying a provider for 'owner' or 'groups' + # are not allowed. + provider: AuthProvider + + # Specifies the name of the claim to look for on the request's JWT token + # from Cognito User Pools (and in the future OIDC) that contains the identity + # of the user. If 'allow' is 'groups', this value should point to a list of groups + # in the claims. If 'allow' is 'owner', this value should point to the logged in user identity string. + # Defaults to "cognito:username" for Cognito User Pools auth. + identityClaim: String + + # Allows for custom config of 'groups' which is validated against the JWT + # Specifies a static list of groups that should have access to the object + groupClaim: String + + # Allowed when the 'allow' argument is 'owner'. + # Specifies the field of type String or [String] that contains owner(s) that can access the object. + ownerField: String # defaults to "owner" + # Allowed when the 'allow' argument is 'groups'. + # Specifies the field of type String or [String] that contains group(s) that can access the object. + groupsField: String + + # Allowed when the 'allow' argument is 'groups'. + # Specifies a static list of groups that should have access to the object. + groups: [String] + + # Specifies operations to which this auth rule should be applied. + operations: [ModelOperation] + + # Deprecated. It is recommended to use the 'operations' arguments. + queries: [ModelQuery] @deprecated(reason: "The 'queries' argument will be replaced by the 'operations' argument in a future release.") + + # Deprecated. It is recommended to use the 'operations' arguments. + mutations: [ModelMutation] + @deprecated(reason: "The 'mutations' argument will be replaced by the 'operations' argument in a future release.") + } + enum AuthStrategy { + owner + groups + private + public + } + enum AuthProvider { + apiKey + iam + oidc + userPools + } + enum ModelOperation { + create + update + delete + read + } + enum ModelQuery @deprecated(reason: "ModelQuery will be replaced by the 'ModelOperation' in a future release.") { + get + list + } + enum ModelMutation @deprecated(reason: "ModelMutation will be replaced by the 'ModelOperation' in a future release.") { + create + update + delete + } +`; +const defaults = {}; + +export const AuthDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/connection.ts b/packages/amplify-graphql-directives/src/directives/v1/connection.ts new file mode 100644 index 0000000000..9a11c0a4f5 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/connection.ts @@ -0,0 +1,20 @@ +import { Directive } from '../directive'; + +const name = 'connection'; +const definition = /* GraphQL */ ` + directive @${name}( + name: String + keyField: String + sortField: String + keyName: String + limit: Int + fields: [String!] + ) on FIELD_DEFINITION +`; +const defaults = {}; + +export const ConnectionDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/function.ts b/packages/amplify-graphql-directives/src/directives/v1/function.ts new file mode 100644 index 0000000000..af359eda84 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/function.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'function'; +const definition = /* GraphQL */ ` + directive @function(name: String!, region: String) repeatable on FIELD_DEFINITION +`; +const defaults = {}; + +export const FunctionDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/http.ts b/packages/amplify-graphql-directives/src/directives/v1/http.ts new file mode 100644 index 0000000000..2830d990d9 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/http.ts @@ -0,0 +1,30 @@ +import { Directive } from '../directive'; + +export type HttpDirectiveV1Defaults = { method: string; headers: string[] }; +const name = 'http'; +const defaults: HttpDirectiveV1Defaults = { + method: 'GET', + headers: [], +}; +const definition = /* GraphQL */ ` + directive @${name}(method: HttpMethod = ${defaults.method}, url: String!, headers: [HttpHeader] = ${JSON.stringify( + defaults.headers, +)}) on FIELD_DEFINITION + enum HttpMethod { + GET + POST + PUT + DELETE + PATCH + } + input HttpHeader { + key: String + value: String + } +`; + +export const HttpDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/index.ts b/packages/amplify-graphql-directives/src/directives/v1/index.ts new file mode 100644 index 0000000000..d989cf2c7a --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/index.ts @@ -0,0 +1,9 @@ +export { AuthDirectiveV1 } from './auth'; +export { ConnectionDirectiveV1 } from './connection'; +export { FunctionDirectiveV1 } from './function'; +export { HttpDirectiveV1 } from './http'; +export { KeyDirectiveV1 } from './key'; +export { ModelDirectiveV1 } from './model'; +export { PredictionsDirectiveV1 } from './predictions'; +export { SearchableDirectiveV1 } from './searchable'; +export { VersionedDirectiveV1, VersionedDirectiveV1Defaults } from './versioned'; diff --git a/packages/amplify-graphql-directives/src/directives/v1/key.ts b/packages/amplify-graphql-directives/src/directives/v1/key.ts new file mode 100644 index 0000000000..760aa89f38 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/key.ts @@ -0,0 +1,13 @@ +import { Directive } from '../directive'; + +const name = 'key'; +const definition = /* GraphQL */ ` + directive @${name}(name: String, fields: [String!]!, queryField: String) repeatable on OBJECT +`; +const defaults = {}; + +export const KeyDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/model.ts b/packages/amplify-graphql-directives/src/directives/v1/model.ts new file mode 100644 index 0000000000..424d204560 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/model.ts @@ -0,0 +1,42 @@ +import { Directive } from '../directive'; + +const name = 'model'; +const definition = /* GraphQL */ ` + directive @${name}( + queries: ModelQueryMap + mutations: ModelMutationMap + subscriptions: ModelSubscriptionMap + timestamps: TimestampConfiguration + ) on OBJECT + input ModelMutationMap { + create: String + update: String + delete: String + } + input ModelQueryMap { + get: String + list: String + } + input ModelSubscriptionMap { + onCreate: [String] + onUpdate: [String] + onDelete: [String] + level: ModelSubscriptionLevel + } + enum ModelSubscriptionLevel { + off + public + on + } + input TimestampConfiguration { + createdAt: String + updatedAt: String + } +`; +const defaults = {}; + +export const ModelDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/predictions.ts b/packages/amplify-graphql-directives/src/directives/v1/predictions.ts new file mode 100644 index 0000000000..07f9f61496 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/predictions.ts @@ -0,0 +1,19 @@ +import { Directive } from '../directive'; + +const name = 'predictions'; +const definition = /* GraphQL */ ` + directive @${name}(actions: [PredictionsActions!]!) on FIELD_DEFINITION + enum PredictionsActions { + identifyText + identifyLabels + convertTextToSpeech + translateText + } +`; +const defaults = {}; + +export const PredictionsDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/searchable.ts b/packages/amplify-graphql-directives/src/directives/v1/searchable.ts new file mode 100644 index 0000000000..d0ed496959 --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/searchable.ts @@ -0,0 +1,16 @@ +import { Directive } from '../directive'; + +const name = 'searchable'; +const definition = /* GraphQL */ ` + directive @${name}(queries: SearchableQueryMap) on OBJECT + input SearchableQueryMap { + search: String + } +`; +const defaults = {}; + +export const SearchableDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/directives/v1/versioned.ts b/packages/amplify-graphql-directives/src/directives/v1/versioned.ts new file mode 100644 index 0000000000..5952ff29ac --- /dev/null +++ b/packages/amplify-graphql-directives/src/directives/v1/versioned.ts @@ -0,0 +1,17 @@ +import { Directive } from '../directive'; + +export type VersionedDirectiveV1Defaults = { versionField: string; versionInput: string }; +const name = 'versioned'; +const defaults: VersionedDirectiveV1Defaults = { + versionField: 'version', + versionInput: 'expectedVersion', +}; +const definition = /* GraphQL */ ` + directive @${name}(versionField: String = "${defaults.versionField}", versionInput: String = "${defaults.versionInput}") on OBJECT +`; + +export const VersionedDirectiveV1: Directive = { + name, + definition, + defaults, +}; diff --git a/packages/amplify-graphql-directives/src/index.ts b/packages/amplify-graphql-directives/src/index.ts new file mode 100644 index 0000000000..f004d4fff4 --- /dev/null +++ b/packages/amplify-graphql-directives/src/index.ts @@ -0,0 +1,85 @@ +export * from './directives'; +import type { Directive } from './directives'; +import { + AuthDirective, + AuthDirectiveV1, + AwsApiKeyDirective, + AwsAuthDirective, + AwsCognitoUserPoolsDirective, + AwsIamDirective, + AwsLambdaDirective, + AwsOidcDirective, + AwsSubscribeDirective, + BelongsToDirective, + ConnectionDirectiveV1, + DefaultDirective, + DeprecatedDirective, + FunctionDirective, + FunctionDirectiveV1, + HasManyDirective, + HasOneDirective, + HttpDirective, + HttpDirectiveV1, + IndexDirective, + KeyDirectiveV1, + ManyToManyDirective, + MapsToDirective, + ModelDirective, + ModelDirectiveV1, + PredictionsDirective, + PredictionsDirectiveV1, + PrimaryKeyDirective, + RefersToDirective, + SearchableDirective, + SearchableDirectiveV1, + SqlDirective, + VersionedDirectiveV1, +} from './directives'; + +export const AppSyncDirectives: readonly Directive[] = [ + AwsApiKeyDirective, + AwsAuthDirective, + AwsCognitoUserPoolsDirective, + AwsIamDirective, + AwsLambdaDirective, + AwsOidcDirective, + AwsSubscribeDirective, +]; + +// This list should match constructTransformerChain in packages/amplify-graphql-transformer/src/graphql-transformer.ts +export const V2Directives: readonly Directive[] = [ + AuthDirective, + BelongsToDirective, + DefaultDirective, + DeprecatedDirective, + FunctionDirective, + HasManyDirective, + HasOneDirective, + HttpDirective, + IndexDirective, + ManyToManyDirective, + MapsToDirective, + ModelDirective, + PredictionsDirective, + PrimaryKeyDirective, + RefersToDirective, + SearchableDirective, + SqlDirective, +]; + +/** + * Default directives used by the GraphQL transform. + */ +export const DefaultDirectives: readonly Directive[] = AppSyncDirectives.concat(V2Directives); + +export const V1Directives: readonly Directive[] = [ + AuthDirectiveV1, + ConnectionDirectiveV1, + FunctionDirectiveV1, + HttpDirectiveV1, + KeyDirectiveV1, + ModelDirectiveV1, + PredictionsDirectiveV1, + SearchableDirectiveV1, + VersionedDirectiveV1, +]; diff --git a/packages/amplify-graphql-directives/tsconfig.json b/packages/amplify-graphql-directives/tsconfig.json new file mode 100644 index 0000000000..2b2102b20e --- /dev/null +++ b/packages/amplify-graphql-directives/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib" + } +} diff --git a/packages/amplify-graphql-function-transformer/package.json b/packages/amplify-graphql-function-transformer/package.json index 438cc5a226..5e79cf77cd 100644 --- a/packages/amplify-graphql-function-transformer/package.json +++ b/packages/amplify-graphql-function-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts b/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts index 08385aac17..4d689bf73d 100644 --- a/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts +++ b/packages/amplify-graphql-function-transformer/src/graphql-function-transformer.ts @@ -1,5 +1,6 @@ import { DirectiveWrapper, generateGetArgumentsInput, MappingTemplate, TransformerPluginBase } from '@aws-amplify/graphql-transformer-core'; import { TransformerContextProvider, TransformerSchemaVisitStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; +import { FunctionDirective } from '@aws-amplify/graphql-directives'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import { AuthorizationType } from 'aws-cdk-lib/aws-appsync'; import * as cdk from 'aws-cdk-lib'; @@ -16,15 +17,12 @@ type FunctionDirectiveConfiguration = { }; const FUNCTION_DIRECTIVE_STACK = 'FunctionDirectiveStack'; -const directiveDefinition = /* GraphQL */ ` - directive @function(name: String!, region: String, accountId: String) repeatable on FIELD_DEFINITION -`; export class FunctionTransformer extends TransformerPluginBase { private resolverGroups: Map = new Map(); constructor(private readonly functionNameMap?: Record) { - super('amplify-function-transformer', directiveDefinition); + super('amplify-function-transformer', FunctionDirective.definition); } field = ( diff --git a/packages/amplify-graphql-function-transformer/tsconfig.json b/packages/amplify-graphql-function-transformer/tsconfig.json index 1f53494b21..bf970b21a9 100644 --- a/packages/amplify-graphql-function-transformer/tsconfig.json +++ b/packages/amplify-graphql-function-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-http-transformer/package.json b/packages/amplify-graphql-http-transformer/package.json index 80cb24f558..8ffb9ed051 100644 --- a/packages/amplify-graphql-http-transformer/package.json +++ b/packages/amplify-graphql-http-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-http-transformer/src/graphql-http-transformer.ts b/packages/amplify-graphql-http-transformer/src/graphql-http-transformer.ts index c57b1488d1..06a62377ae 100644 --- a/packages/amplify-graphql-http-transformer/src/graphql-http-transformer.ts +++ b/packages/amplify-graphql-http-transformer/src/graphql-http-transformer.ts @@ -6,6 +6,7 @@ import { TransformerPluginBase, } from '@aws-amplify/graphql-transformer-core'; import { TransformerContextProvider, TransformerSchemaVisitStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; +import { HttpDirective } from '@aws-amplify/graphql-directives'; import { AuthorizationType } from 'aws-cdk-lib/aws-appsync'; import * as cdk from 'aws-cdk-lib'; import { @@ -69,26 +70,12 @@ const URL_REGEX = /(http(s)?:\/\/)|(\/.*)/g; const VALID_PROTOCOLS_REGEX = /^http(s)?:\/\//; const HTTP_DIRECTIVE_STACK = 'HttpStack'; const RESOLVER_VERSION = '2018-05-29'; -const directiveDefinition = /* GraphQL */ ` - directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION - enum HttpMethod { - GET - POST - PUT - DELETE - PATCH - } - input HttpHeader { - key: String - value: String - } -`; export class HttpTransformer extends TransformerPluginBase { private directiveList: HttpDirectiveConfiguration[] = []; constructor() { - super('amplify-http-transformer', directiveDefinition); + super('amplify-http-transformer', HttpDirective.definition); } field = ( diff --git a/packages/amplify-graphql-http-transformer/tsconfig.json b/packages/amplify-graphql-http-transformer/tsconfig.json index 1f53494b21..bf970b21a9 100644 --- a/packages/amplify-graphql-http-transformer/tsconfig.json +++ b/packages/amplify-graphql-http-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-index-transformer/package.json b/packages/amplify-graphql-index-transformer/package.json index 26c537c72e..1ef38e5666 100644 --- a/packages/amplify-graphql-index-transformer/package.json +++ b/packages/amplify-graphql-index-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-model-transformer": "2.6.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", diff --git a/packages/amplify-graphql-index-transformer/src/graphql-index-transformer.ts b/packages/amplify-graphql-index-transformer/src/graphql-index-transformer.ts index 07aff9209e..0320d737d2 100644 --- a/packages/amplify-graphql-index-transformer/src/graphql-index-transformer.ts +++ b/packages/amplify-graphql-index-transformer/src/graphql-index-transformer.ts @@ -10,6 +10,7 @@ import { TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { IndexDirective } from '@aws-amplify/graphql-directives'; import { DirectiveNode, EnumTypeDefinitionNode, @@ -24,11 +25,6 @@ import { addKeyConditionInputs, ensureQueryField, updateMutationConditionInput } import { IndexDirectiveConfiguration } from './types'; import { generateKeyAndQueryNameForConfig, validateNotSelfReferencing } from './utils'; -const directiveName = 'index'; -const directiveDefinition = ` - directive @${directiveName}(name: String, sortKeyFields: [String], queryField: String) repeatable on FIELD_DEFINITION -`; - /** * */ @@ -38,7 +34,7 @@ export class IndexTransformer extends TransformerPluginBase { private resolverMap: Map = new Map(); constructor() { - super('amplify-index-transformer', directiveDefinition); + super('amplify-index-transformer', IndexDirective.definition); } field = ( @@ -164,7 +160,7 @@ const validate = (config: IndexDirectiveConfiguration, ctx: TransformerContextPr const modelDirective = object.directives!.find((directive) => directive.name.value === 'model'); if (!modelDirective) { - throw new InvalidDirectiveError(`The @${directiveName} directive may only be added to object definitions annotated with @model.`); + throw new InvalidDirectiveError(`The @${IndexDirective.name} directive may only be added to object definitions annotated with @model.`); } config.modelDirective = modelDirective; @@ -195,11 +191,11 @@ const validate = (config: IndexDirectiveConfiguration, ctx: TransformerContextPr } if ( - peerDirective.name.value === directiveName && + peerDirective.name.value === IndexDirective.name && peerDirective.arguments!.some((arg: any) => arg.name.value === 'name' && arg.value.value === name) ) { throw new InvalidDirectiveError( - `You may only supply one @${directiveName} with the name '${name}' on type '${object.name.value}'.`, + `You may only supply one @${IndexDirective.name} with the name '${name}' on type '${object.name.value}'.`, ); } } diff --git a/packages/amplify-graphql-index-transformer/src/graphql-primary-key-transformer.ts b/packages/amplify-graphql-index-transformer/src/graphql-primary-key-transformer.ts index fc32412e99..5ee42dd534 100644 --- a/packages/amplify-graphql-index-transformer/src/graphql-primary-key-transformer.ts +++ b/packages/amplify-graphql-index-transformer/src/graphql-primary-key-transformer.ts @@ -12,6 +12,7 @@ import { TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { PrimaryKeyDirective } from '@aws-amplify/graphql-directives'; import { DirectiveNode, EnumTypeDefinitionNode, @@ -35,18 +36,13 @@ import { import { PrimaryKeyDirectiveConfiguration } from './types'; import { validateNotSelfReferencing, validateNotOwnerAuth, lookupResolverName } from './utils'; -const directiveName = 'primaryKey'; -const directiveDefinition = ` - directive @${directiveName}(sortKeyFields: [String]) on FIELD_DEFINITION -`; - export class PrimaryKeyTransformer extends TransformerPluginBase { private directiveList: PrimaryKeyDirectiveConfiguration[] = []; private resolverMap: Map = new Map(); constructor() { - super('amplify-primary-key-transformer', directiveDefinition); + super('amplify-primary-key-transformer', PrimaryKeyDirective.definition); } field = ( @@ -120,7 +116,9 @@ const validate = (config: PrimaryKeyDirectiveConfiguration, ctx: TransformerCont }); if (!modelDirective) { - throw new InvalidDirectiveError(`The @${directiveName} directive may only be added to object definitions annotated with @model.`); + throw new InvalidDirectiveError( + `The @${PrimaryKeyDirective.name} directive may only be added to object definitions annotated with @model.`, + ); } config.modelDirective = modelDirective; @@ -135,7 +133,7 @@ const validate = (config: PrimaryKeyDirectiveConfiguration, ctx: TransformerCont } for (const directive of objectField.directives!) { - if (directive.name.value === directiveName) { + if (directive.name.value === PrimaryKeyDirective.name) { throw new InvalidDirectiveError(`You may only supply one primary key on type '${object.name.value}'.`); } } diff --git a/packages/amplify-graphql-index-transformer/tsconfig.json b/packages/amplify-graphql-index-transformer/tsconfig.json index 1f53494b21..bf970b21a9 100644 --- a/packages/amplify-graphql-index-transformer/tsconfig.json +++ b/packages/amplify-graphql-index-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-model-transformer/package.json b/packages/amplify-graphql-model-transformer/package.json index 638c732fbe..df6059dbd5 100644 --- a/packages/amplify-graphql-model-transformer/package.json +++ b/packages/amplify-graphql-model-transformer/package.json @@ -32,6 +32,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts b/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts index ea2e71c67e..d23e0ed4e6 100644 --- a/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts +++ b/packages/amplify-graphql-model-transformer/src/graphql-model-transformer.ts @@ -35,6 +35,7 @@ import { TransformerValidationStepContextProvider, DataSourceStrategiesProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { ModelDirective } from '@aws-amplify/graphql-directives'; import { ITable } from 'aws-cdk-lib/aws-dynamodb'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as cdk from 'aws-cdk-lib'; @@ -85,39 +86,6 @@ import { AmplifyDynamoModelResourceGenerator } from './resources/amplify-dynamod */ export type Nullable = T | null; -export const directiveDefinition = /* GraphQl */ ` - directive @model( - queries: ModelQueryMap - mutations: ModelMutationMap - subscriptions: ModelSubscriptionMap - timestamps: TimestampConfiguration - ) on OBJECT - input ModelMutationMap { - create: String - update: String - delete: String - } - input ModelQueryMap { - get: String - list: String - } - input ModelSubscriptionMap { - onCreate: [String] - onUpdate: [String] - onDelete: [String] - level: ModelSubscriptionLevel - } - enum ModelSubscriptionLevel { - off - public - on - } - input TimestampConfiguration { - createdAt: String - updatedAt: String - } -`; - // Keys for the resource generator map to reference the generator for various ModelDataSourceStrategies const ITERATIVE_TABLE_GENERATOR = 'AmplifyDDB'; const SQL_LAMBDA_GENERATOR = 'SQL'; @@ -142,7 +110,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme private modelDirectiveConfig: Map = new Map(); constructor(options: ModelTransformerOptions = {}) { - super('amplify-model-transformer', directiveDefinition); + super('amplify-model-transformer', ModelDirective.definition); this.options = this.getOptions(options); this.resourceGeneratorMap.set(DDB_DB_TYPE, new DynamoModelResourceGenerator()); this.resourceGeneratorMap.set(SQL_LAMBDA_GENERATOR, new RdsModelResourceGenerator()); diff --git a/packages/amplify-graphql-model-transformer/tsconfig.json b/packages/amplify-graphql-model-transformer/tsconfig.json index 33a0e75d3d..0524a070c9 100644 --- a/packages/amplify-graphql-model-transformer/tsconfig.json +++ b/packages/amplify-graphql-model-transformer/tsconfig.json @@ -6,6 +6,7 @@ }, "include": ["src/**/*"], "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, { "path": "../amplify-graphql-transformer-core" }, diff --git a/packages/amplify-graphql-name-mapping-transformer/package.json b/packages/amplify-graphql-name-mapping-transformer/package.json index 2bbe7d415d..b831064083 100644 --- a/packages/amplify-graphql-name-mapping-transformer/package.json +++ b/packages/amplify-graphql-name-mapping-transformer/package.json @@ -30,6 +30,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql-mapping-template": "4.20.15", diff --git a/packages/amplify-graphql-name-mapping-transformer/src/__tests__/graphql-refers-to-transformer.test.ts b/packages/amplify-graphql-name-mapping-transformer/src/__tests__/graphql-refers-to-transformer.test.ts index 3ef128cb9b..860ddd6539 100644 --- a/packages/amplify-graphql-name-mapping-transformer/src/__tests__/graphql-refers-to-transformer.test.ts +++ b/packages/amplify-graphql-name-mapping-transformer/src/__tests__/graphql-refers-to-transformer.test.ts @@ -126,7 +126,7 @@ describe('@refersTo directive on models', () => { stubDirective.arguments = []; expect(() => refersToTransformer.object(stubDefinition as ObjectTypeDefinitionNode, stubDirective as DirectiveNode, stubTransformerContext), - ).toThrowErrorMatchingInlineSnapshot('"@refersTo is only supported on RDS models. DDBModel is not an RDS model."'); + ).toThrowErrorMatchingInlineSnapshot(`"@refersTo is only supported on SQL models. DDBModel is not a SQL model."`); }); it('requires a name to be specified', () => { @@ -286,7 +286,7 @@ describe('@refersTo directive on fields', () => { context.dataSourceStrategies[modelName] = DDB_DEFAULT_DATASOURCE_STRATEGY; expect(() => refersToTransformer.field(parent as ObjectTypeDefinitionNode, field as FieldDefinitionNode, directive as DirectiveNode, context), - ).toThrowErrorMatchingInlineSnapshot('"@refersTo is only supported on RDS models. DDBModel is not an RDS model."'); + ).toThrowErrorMatchingInlineSnapshot(`"@refersTo is only supported on SQL models. DDBModel is not a SQL model."`); }); it('cannot be applied on relational fields in a model', () => { diff --git a/packages/amplify-graphql-name-mapping-transformer/src/graphql-maps-to-transformer.ts b/packages/amplify-graphql-name-mapping-transformer/src/graphql-maps-to-transformer.ts index 4223ce9b8c..5ac03083ac 100644 --- a/packages/amplify-graphql-name-mapping-transformer/src/graphql-maps-to-transformer.ts +++ b/packages/amplify-graphql-name-mapping-transformer/src/graphql-maps-to-transformer.ts @@ -5,30 +5,25 @@ import { TransformerPreProcessContextProvider, TransformerSchemaVisitStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { MapsToDirective } from '@aws-amplify/graphql-directives'; import { ObjectTypeDefinitionNode, DirectiveNode, ObjectTypeExtensionNode } from 'graphql'; import { createMappingLambda } from './field-mapping-lambda'; import { attachFilterAndConditionInputMappingSlot, attachInputMappingSlot, attachResponseMappingSlot } from './field-mapping-resolvers'; import { shouldBeAppliedToModel, getMappedName, updateTypeMapping, setTypeMappingInSchema } from './graphql-name-mapping'; -const directiveName = 'mapsTo'; - -const directiveDefinition = ` - directive @${directiveName}(name: String!) on OBJECT -`; - export class MapsToTransformer extends TransformerPluginBase { constructor() { - super('amplify-maps-to-transformer', directiveDefinition, TransformerPluginType.GENERIC); + super('amplify-maps-to-transformer', MapsToDirective.definition, TransformerPluginType.GENERIC); } /** * During the AST tree walking, the mapsTo transformer registers any renamed models with the ctx.resourceHelper. */ object = (definition: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerSchemaVisitStepContextProvider): void => { - shouldBeAppliedToModel(definition, directiveName); + shouldBeAppliedToModel(definition, MapsToDirective.name); shouldBeAppliedToDDBModels(definition, ctx as TransformerContextProvider); const modelName = definition.name.value; - const mappedName = getMappedName(definition, directive, directiveName, ctx.inputDocument); + const mappedName = getMappedName(definition, directive, MapsToDirective.name, ctx.inputDocument); updateTypeMapping(modelName, mappedName, ctx.resourceHelper.setModelNameMapping); }; @@ -37,7 +32,7 @@ export class MapsToTransformer extends TransformerPluginBase { * @param context The pre-processing context for the transformer, used to store type mappings */ preMutateSchema = (context: TransformerPreProcessContextProvider): void => { - setTypeMappingInSchema(context, directiveName); + setTypeMappingInSchema(context, MapsToDirective.name); }; /** @@ -111,6 +106,6 @@ export const shouldBeAppliedToDDBModels = ( ): void => { const modelName = definition.name.value; if (!isDynamoDbModel(ctx, modelName)) { - throw new Error(`${directiveName} is only supported on DynamoDB models. ${modelName} is not a DDB model.`); + throw new Error(`${MapsToDirective.name} is only supported on DynamoDB models. ${modelName} is not a DDB model.`); } }; diff --git a/packages/amplify-graphql-name-mapping-transformer/src/graphql-refers-to-transformer.ts b/packages/amplify-graphql-name-mapping-transformer/src/graphql-refers-to-transformer.ts index 7001ff08b7..9fa1ba77f4 100644 --- a/packages/amplify-graphql-name-mapping-transformer/src/graphql-refers-to-transformer.ts +++ b/packages/amplify-graphql-name-mapping-transformer/src/graphql-refers-to-transformer.ts @@ -5,6 +5,7 @@ import { TransformerPreProcessContextProvider, TransformerSchemaVisitStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { RefersToDirective } from '@aws-amplify/graphql-directives'; import { ObjectTypeDefinitionNode, DirectiveNode, @@ -23,15 +24,9 @@ import { } from './graphql-name-mapping'; import { attachFieldMappingSlot } from './field-mapping-resolvers'; -const directiveName = 'refersTo'; - -const directiveDefinition = ` - directive @${directiveName}(name: String!) on OBJECT | FIELD_DEFINITION -`; - export class RefersToTransformer extends TransformerPluginBase { constructor() { - super('amplify-refers-to-transformer', directiveDefinition, TransformerPluginType.GENERIC); + super('amplify-refers-to-transformer', RefersToDirective.definition, TransformerPluginType.GENERIC); } /** @@ -39,10 +34,10 @@ export class RefersToTransformer extends TransformerPluginBase { */ object = (definition: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerSchemaVisitStepContextProvider): void => { const context = ctx as TransformerContextProvider; - shouldBeAppliedToModel(definition, directiveName); + shouldBeAppliedToModel(definition, RefersToDirective.name); shouldBeAppliedToRDSModels(definition, context); const modelName = definition.name.value; - const mappedName = getMappedName(definition, directive, directiveName, ctx.inputDocument); + const mappedName = getMappedName(definition, directive, RefersToDirective.name, ctx.inputDocument); updateTypeMapping(modelName, mappedName, ctx.resourceHelper.setModelNameMapping); }; @@ -62,10 +57,10 @@ export class RefersToTransformer extends TransformerPluginBase { } const context = ctx as TransformerContextProvider; const modelName = parent?.name?.value; - shouldBeAppliedToModel(parent, directiveName); + shouldBeAppliedToModel(parent, RefersToDirective.name); shouldBeAppliedToRDSModels(parent, context); shouldNotBeOnRelationalField(definition, modelName); - const mappedName = getMappedFieldName(parent, definition, directive, directiveName); + const mappedName = getMappedFieldName(parent, definition, directive, RefersToDirective.name); updateFieldMapping(modelName, definition?.name?.value, mappedName, ctx); }; @@ -103,7 +98,7 @@ export class RefersToTransformer extends TransformerPluginBase { * @param context The pre-processing context for the transformer, used to store type mappings */ preMutateSchema = (context: TransformerPreProcessContextProvider): void => { - setTypeMappingInSchema(context, directiveName); + setTypeMappingInSchema(context, RefersToDirective.name); }; } @@ -113,13 +108,15 @@ export const shouldBeAppliedToRDSModels = ( ): void => { const modelName = definition.name.value; if (!isSqlModel(ctx, modelName)) { - throw new Error(`@${directiveName} is only supported on RDS models. ${modelName} is not an RDS model.`); + throw new Error(`@${RefersToDirective.name} is only supported on SQL models. ${modelName} is not a SQL model.`); } }; export const shouldNotBeOnRelationalField = (definition: FieldDefinitionNode, modelName: string): void => { const relationalDirectives = ['hasOne', 'hasMany', 'belongsTo', 'manyToMany']; if (definition?.directives?.some((directive) => relationalDirectives.includes(directive?.name?.value))) { - throw new Error(`@${directiveName} is not supported on "${definition?.name?.value}" relational field in "${modelName}" model.`); + throw new Error( + `@${RefersToDirective.name} is not supported on "${definition?.name?.value}" relational field in "${modelName}" model.`, + ); } }; diff --git a/packages/amplify-graphql-name-mapping-transformer/tsconfig.json b/packages/amplify-graphql-name-mapping-transformer/tsconfig.json index 624c4aa272..867a1006c4 100644 --- a/packages/amplify-graphql-name-mapping-transformer/tsconfig.json +++ b/packages/amplify-graphql-name-mapping-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-relational-transformer" }, diff --git a/packages/amplify-graphql-predictions-transformer/package.json b/packages/amplify-graphql-predictions-transformer/package.json index 7ee39fe697..3dd1851d70 100644 --- a/packages/amplify-graphql-predictions-transformer/package.json +++ b/packages/amplify-graphql-predictions-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts b/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts index 40029b1656..93db873206 100644 --- a/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts +++ b/packages/amplify-graphql-predictions-transformer/src/graphql-predictions-transformer.ts @@ -12,6 +12,7 @@ import { TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { PredictionsDirective } from '@aws-amplify/graphql-directives'; import { DataSourceOptions, HttpDataSource, LambdaDataSource, CfnResolver, AuthorizationType } from 'aws-cdk-lib/aws-appsync'; import * as cdk from 'aws-cdk-lib'; import * as iam from 'aws-cdk-lib/aws-iam'; @@ -47,7 +48,6 @@ import { actionToDataSourceMap, actionToRoleAction, allowedActions } from './uti import { amzJsonContentType, convertTextToSpeech, - directiveDefinition, identifyEntities, identifyLabels, identifyLabelsAmzTarget, @@ -74,7 +74,7 @@ export class PredictionsTransformer extends TransformerPluginBase { private bucketName: string; constructor(predictionsConfig?: PredictionsConfig) { - super('amplify-predictions-transformer', directiveDefinition); + super('amplify-predictions-transformer', PredictionsDirective.definition); this.bucketName = predictionsConfig?.bucketName ?? ''; } diff --git a/packages/amplify-graphql-predictions-transformer/src/utils/constants.ts b/packages/amplify-graphql-predictions-transformer/src/utils/constants.ts index db6a75a79e..710b878e3f 100644 --- a/packages/amplify-graphql-predictions-transformer/src/utils/constants.ts +++ b/packages/amplify-graphql-predictions-transformer/src/utils/constants.ts @@ -1,13 +1,4 @@ export const PREDICTIONS_DIRECTIVE_STACK = 'PredictionsDirectiveStack'; -export const directiveDefinition = /* GraphQL */ ` - directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION - enum PredictionsActions { - identifyText - identifyLabels - convertTextToSpeech - translateText - } -`; export const identifyEntities = 'identifyEntities'; export const identifyText = 'identifyText'; export const identifyLabels = 'identifyLabels'; diff --git a/packages/amplify-graphql-predictions-transformer/tsconfig.json b/packages/amplify-graphql-predictions-transformer/tsconfig.json index 1f53494b21..bf970b21a9 100644 --- a/packages/amplify-graphql-predictions-transformer/tsconfig.json +++ b/packages/amplify-graphql-predictions-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-relational-transformer/package.json b/packages/amplify-graphql-relational-transformer/package.json index 800a2f0780..7e70f1f213 100644 --- a/packages/amplify-graphql-relational-transformer/package.json +++ b/packages/amplify-graphql-relational-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-index-transformer": "2.3.7", "@aws-amplify/graphql-model-transformer": "2.6.0", "@aws-amplify/graphql-transformer-core": "2.5.0", diff --git a/packages/amplify-graphql-relational-transformer/src/graphql-belongs-to-transformer.ts b/packages/amplify-graphql-relational-transformer/src/graphql-belongs-to-transformer.ts index 7cd3af32e1..dc45dc2a34 100644 --- a/packages/amplify-graphql-relational-transformer/src/graphql-belongs-to-transformer.ts +++ b/packages/amplify-graphql-relational-transformer/src/graphql-belongs-to-transformer.ts @@ -16,6 +16,7 @@ import { TransformerPreProcessContextProvider, ModelDataSourceStrategyDbType, } from '@aws-amplify/graphql-transformer-interfaces'; +import { BelongsToDirective } from '@aws-amplify/graphql-directives'; import { DirectiveNode, DocumentNode, @@ -39,11 +40,6 @@ import { import { getGenerator } from './resolver/generator-factory'; import { getBelongsToDirectiveTransformer } from './belongs-to/belongs-to-directive-transformer-factory'; -const directiveName = 'belongsTo'; -const directiveDefinition = ` - directive @${directiveName}(fields: [String!], references: [String!]) on FIELD_DEFINITION -`; - /** * Transformer for @belongsTo directive */ @@ -51,7 +47,7 @@ export class BelongsToTransformer extends TransformerPluginBase { private directiveList: BelongsToDirectiveConfiguration[] = []; constructor() { - super('amplify-belongs-to-transformer', directiveDefinition); + super('amplify-belongs-to-transformer', BelongsToDirective.definition); } field = ( @@ -63,7 +59,7 @@ export class BelongsToTransformer extends TransformerPluginBase { const directiveWrapped = new DirectiveWrapper(directive); const args = directiveWrapped.getArguments( { - directiveName, + directiveName: BelongsToDirective.name, object: parent as ObjectTypeDefinitionNode, field: definition, directive, @@ -90,7 +86,7 @@ export class BelongsToTransformer extends TransformerPluginBase { objectDefs?.forEach((def) => { const filteredFields = def?.fields?.filter((field) => - field?.directives?.some((dir) => dir.name.value === directiveName && objectTypeMap.get(getBaseType(field.type))), + field?.directives?.some((dir) => dir.name.value === BelongsToDirective.name && objectTypeMap.get(getBaseType(field.type))), ); filteredFields?.forEach((field) => { const relatedType = objectTypeMap.get(getBaseType(field.type)); @@ -183,7 +179,7 @@ const validate = (config: BelongsToDirectiveConfiguration, ctx: TransformerConte validateModelDirective(config); if (isListType(field.type)) { - throw new InvalidDirectiveError(`@${directiveName} cannot be used with lists.`); + throw new InvalidDirectiveError(`@${BelongsToDirective.name} cannot be used with lists.`); } config.connectionFields = []; @@ -206,7 +202,7 @@ const validate = (config: BelongsToDirectiveConfiguration, ctx: TransformerConte if (!isBiRelation && dbType === DDB_DB_TYPE) { throw new InvalidDirectiveError( - `${config.relatedType.name.value} must have a relationship with ${object.name.value} in order to use @${directiveName}.`, + `${config.relatedType.name.value} must have a relationship with ${object.name.value} in order to use @${BelongsToDirective.name}.`, ); } }; diff --git a/packages/amplify-graphql-relational-transformer/src/graphql-has-many-transformer.ts b/packages/amplify-graphql-relational-transformer/src/graphql-has-many-transformer.ts index f114281390..513764697a 100644 --- a/packages/amplify-graphql-relational-transformer/src/graphql-has-many-transformer.ts +++ b/packages/amplify-graphql-relational-transformer/src/graphql-has-many-transformer.ts @@ -14,6 +14,7 @@ import { TransformerTransformSchemaStepContextProvider, TransformerPreProcessContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { HasManyDirective } from '@aws-amplify/graphql-directives'; import { getBaseType, isListType, isNonNullType, makeField, makeNamedType, makeNonNullType } from 'graphql-transformer-common'; import { DirectiveNode, @@ -44,17 +45,11 @@ import { import { getGenerator } from './resolver/generator-factory'; import { getHasManyDirectiveTransformer } from './has-many/has-many-directive-transformer-factory'; -const directiveName = 'hasMany'; -const defaultLimit = 100; -const directiveDefinition = ` - directive @${directiveName}(indexName: String, fields: [String!], references: [String!], limit: Int = ${defaultLimit}) on FIELD_DEFINITION -`; - export class HasManyTransformer extends TransformerPluginBase { private directiveList: HasManyDirectiveConfiguration[] = []; constructor() { - super('amplify-has-many-transformer', directiveDefinition); + super('amplify-has-many-transformer', HasManyDirective.definition); } field = ( @@ -66,11 +61,11 @@ export class HasManyTransformer extends TransformerPluginBase { const directiveWrapped = new DirectiveWrapper(directive); const args = directiveWrapped.getArguments( { - directiveName, + directiveName: HasManyDirective.name, object: parent as ObjectTypeDefinitionNode, field: definition, directive, - limit: defaultLimit, + limit: HasManyDirective.defaults.limit, } as HasManyDirectiveConfiguration, generateGetArgumentsInput(context.transformParameters), ); @@ -91,7 +86,7 @@ export class HasManyTransformer extends TransformerPluginBase { const objectDefs = filteredDefs as Array>; // First iteration builds a map of the hasMany connecting fields that need to exist, second iteration ensures they exist objectDefs?.forEach((def) => { - const filteredFields = def?.fields?.filter((field) => field?.directives?.some((dir) => dir.name.value === directiveName)); + const filteredFields = def?.fields?.filter((field) => field?.directives?.some((dir) => dir.name.value === HasManyDirective.name)); filteredFields?.forEach((field) => { const baseFieldType = getBaseType(field.type); const connectionAttributeName = getConnectionAttributeName( @@ -172,7 +167,7 @@ const validate = (config: HasManyDirectiveConfiguration, ctx: TransformerContext validateModelDirective(config); if (!isListType(field.type)) { - throw new InvalidDirectiveError(`@${directiveName} must be used with a list. Use @hasOne for non-list types.`); + throw new InvalidDirectiveError(`@${HasManyDirective.name} must be used with a list. Use @hasOne for non-list types.`); } config.connectionFields = []; diff --git a/packages/amplify-graphql-relational-transformer/src/graphql-has-one-transformer.ts b/packages/amplify-graphql-relational-transformer/src/graphql-has-one-transformer.ts index 0331fb29a0..d389c73405 100644 --- a/packages/amplify-graphql-relational-transformer/src/graphql-has-one-transformer.ts +++ b/packages/amplify-graphql-relational-transformer/src/graphql-has-one-transformer.ts @@ -14,6 +14,7 @@ import { TransformerTransformSchemaStepContextProvider, TransformerPreProcessContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { HasOneDirective } from '@aws-amplify/graphql-directives'; import { ArgumentNode, DirectiveNode, @@ -52,11 +53,6 @@ import { import { getGenerator } from './resolver/generator-factory'; import { getHasOneDirectiveTransformer } from './has-one/has-one-directive-transformer-factory'; -const directiveName = 'hasOne'; -const directiveDefinition = ` - directive @${directiveName}(fields: [String!], references: [String!]) on FIELD_DEFINITION -`; - /** * Transformer for @hasOne directive */ @@ -64,7 +60,7 @@ export class HasOneTransformer extends TransformerPluginBase { private directiveList: HasOneDirectiveConfiguration[] = []; constructor() { - super('amplify-has-one-transformer', directiveDefinition); + super('amplify-has-one-transformer', HasOneDirective.definition); } field = ( @@ -76,7 +72,7 @@ export class HasOneTransformer extends TransformerPluginBase { const directiveWrapped = new DirectiveWrapper(directive); const args = directiveWrapped.getArguments( { - directiveName, + directiveName: HasOneDirective.name, object: parent as ObjectTypeDefinitionNode, field: definition, directive, @@ -101,7 +97,7 @@ export class HasOneTransformer extends TransformerPluginBase { ); objectDefs?.forEach((def) => { - const filteredFields = def?.fields?.filter((field) => field?.directives?.some((dir) => dir.name.value === directiveName)); + const filteredFields = def?.fields?.filter((field) => field?.directives?.some((dir) => dir.name.value === HasOneDirective.name)); filteredFields?.forEach((field) => { field?.directives?.forEach((dir) => { const connectionAttributeName = getConnectionAttributeName( @@ -196,7 +192,7 @@ const validate = (config: HasOneDirectiveConfiguration, ctx: TransformerContextP validateModelDirective(config); if (isListType(field.type)) { - throw new InvalidDirectiveError(`@${directiveName} cannot be used with lists. Use @hasMany instead.`); + throw new InvalidDirectiveError(`@${HasOneDirective.name} cannot be used with lists. Use @hasMany instead.`); } config.connectionFields = []; diff --git a/packages/amplify-graphql-relational-transformer/src/graphql-many-to-many-transformer.ts b/packages/amplify-graphql-relational-transformer/src/graphql-many-to-many-transformer.ts index 2a66acfaea..85efe03f7d 100644 --- a/packages/amplify-graphql-relational-transformer/src/graphql-many-to-many-transformer.ts +++ b/packages/amplify-graphql-relational-transformer/src/graphql-many-to-many-transformer.ts @@ -22,6 +22,7 @@ import { DataSourceStrategiesProvider, ModelDataSourceStrategy, } from '@aws-amplify/graphql-transformer-interfaces'; +import { ManyToManyDirective } from '@aws-amplify/graphql-directives'; import { DirectiveNode, DocumentNode, @@ -67,12 +68,6 @@ import { import { HasOneTransformer } from './graphql-has-one-transformer'; import { DDBRelationalResolverGenerator } from './resolver/ddb-generator'; -const directiveName = 'manyToMany'; -const defaultLimit = 100; -const directiveDefinition = ` - directive @${directiveName}(relationName: String!, limit: Int = ${defaultLimit}) on FIELD_DEFINITION -`; - /** * ManyToManyTransformer * The many to many transformer is shorthand for an additional model in the a GraphQL schema, @@ -99,7 +94,7 @@ export class ManyToManyTransformer extends TransformerPluginBase { hasOneTransformer: HasOneTransformer, authProvider: TransformerAuthProvider, ) { - super('amplify-many-to-many-transformer', directiveDefinition); + super('amplify-many-to-many-transformer', ManyToManyDirective.definition); this.modelTransformer = modelTransformer; this.indexTransformer = indexTransformer; this.hasOneTransformer = hasOneTransformer; @@ -115,11 +110,11 @@ export class ManyToManyTransformer extends TransformerPluginBase { const directiveWrapped = new DirectiveWrapper(directive); const args = directiveWrapped.getArguments( { - directiveName, + directiveName: ManyToManyDirective.name, object: parent as ObjectTypeDefinitionNode, field: definition, directive, - limit: defaultLimit, + limit: ManyToManyDirective.defaults.limit, } as ManyToManyDirectiveConfiguration, generateGetArgumentsInput(context.transformParameters), ); @@ -128,7 +123,7 @@ export class ManyToManyTransformer extends TransformerPluginBase { args.connectionFields = []; if (!isListType(definition.type)) { - throw new InvalidDirectiveError(`@${directiveName} must be used with a list.`); + throw new InvalidDirectiveError(`@${ManyToManyDirective.name} must be used with a list.`); } addDirectiveToRelationMap(this.relationMap, args); @@ -152,7 +147,7 @@ export class ManyToManyTransformer extends TransformerPluginBase { objectDefs?.forEach((def) => { def?.fields?.forEach((field) => { field?.directives - ?.filter((dir) => dir.name.value === directiveName) + ?.filter((dir) => dir.name.value === ManyToManyDirective.name) ?.forEach((dir) => { const relationArg = dir?.arguments?.find((arg) => arg.name.value === 'relationName'); if (relationArg?.value?.kind === 'StringValue') { @@ -294,14 +289,14 @@ export class ManyToManyTransformer extends TransformerPluginBase { const { directive1, directive2, name } = relation; if (!directive2) { - throw new InvalidDirectiveError(`@${directiveName} relation '${name}' must be used in exactly two locations.`); + throw new InvalidDirectiveError(`@${ManyToManyDirective.name} relation '${name}' must be used in exactly two locations.`); } const d1ExpectedType = getBaseType(directive1.field.type); const d2ExpectedType = getBaseType(directive2.field.type); if (isSqlModel(ctx, d1ExpectedType) || isSqlModel(ctx, d2ExpectedType)) { - throw new InvalidDirectiveError(`@${directiveName} directive cannot be used on a SQL model.`); + throw new InvalidDirectiveError(`@${ManyToManyDirective.name} directive cannot be used on a SQL model.`); } const d1Strategy = getModelDataSourceStrategy(ctx, d1ExpectedType); @@ -311,25 +306,25 @@ export class ManyToManyTransformer extends TransformerPluginBase { (isAmplifyDynamoDbModelDataSourceStrategy(d1Strategy) && !isAmplifyDynamoDbModelDataSourceStrategy(d2Strategy)) ) { throw new InvalidDirectiveError( - `@${directiveName} directive cannot be used to relate models with a different DynamoDB-based strategies.`, + `@${ManyToManyDirective.name} directive cannot be used to relate models with a different DynamoDB-based strategies.`, ); } if (d1ExpectedType !== directive2.object.name.value) { throw new InvalidDirectiveError( - `@${directiveName} relation '${name}' expects '${d1ExpectedType}' but got '${directive2.object.name.value}'.`, + `@${ManyToManyDirective.name} relation '${name}' expects '${d1ExpectedType}' but got '${directive2.object.name.value}'.`, ); } if (d2ExpectedType !== directive1.object.name.value) { throw new InvalidDirectiveError( - `@${directiveName} relation '${name}' expects '${d2ExpectedType}' but got '${directive1.object.name.value}'.`, + `@${ManyToManyDirective.name} relation '${name}' expects '${d2ExpectedType}' but got '${directive1.object.name.value}'.`, ); } if (ctx.output.hasType(name)) { throw new InvalidDirectiveError( - `@${directiveName} relation name '${name}' (derived from '${directive1.relationName}') already exists as a type in the schema.`, + `@${ManyToManyDirective.name} relation name '${name}' (derived from '${directive1.relationName}') already exists as a type in the schema.`, ); } }); @@ -557,7 +552,7 @@ function addDirectiveToRelationMap(map: Map, directi } if (relation.directive2) { - throw new InvalidDirectiveError(`@${directiveName} relation '${relationName}' must be used in exactly two locations.`); + throw new InvalidDirectiveError(`@${ManyToManyDirective.name} relation '${relationName}' must be used in exactly two locations.`); } relation.directive2 = directive; diff --git a/packages/amplify-graphql-relational-transformer/tsconfig.json b/packages/amplify-graphql-relational-transformer/tsconfig.json index 7bdded381d..4c203fb0b5 100644 --- a/packages/amplify-graphql-relational-transformer/tsconfig.json +++ b/packages/amplify-graphql-relational-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-searchable-transformer/package.json b/packages/amplify-graphql-searchable-transformer/package.json index ae745e6b39..9834543f5d 100644 --- a/packages/amplify-graphql-searchable-transformer/package.json +++ b/packages/amplify-graphql-searchable-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-model-transformer": "2.6.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", diff --git a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts index b114863d52..3c8f749e92 100644 --- a/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts +++ b/packages/amplify-graphql-searchable-transformer/src/graphql-searchable-transformer.ts @@ -13,6 +13,7 @@ import { TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider, } from '@aws-amplify/graphql-transformer-interfaces'; +import { SearchableDirective } from '@aws-amplify/graphql-directives'; import { DynamoDbDataSource } from 'aws-cdk-lib/aws-appsync'; import { Table } from 'aws-cdk-lib/aws-dynamodb'; import { ArnFormat, CfnCondition, Fn } from 'aws-cdk-lib'; @@ -265,15 +266,7 @@ export class SearchableModelTransformer extends TransformerPluginBase { searchableObjectNames: string[]; constructor() { - super( - 'amplify-searchable-transformer', - /* GraphQL */ ` - directive @searchable(queries: SearchableQueryMap) on OBJECT - input SearchableQueryMap { - search: String - } - `, - ); + super('amplify-searchable-transformer', SearchableDirective.definition); this.searchableObjectTypeDefinitions = []; this.searchableObjectNames = []; } diff --git a/packages/amplify-graphql-searchable-transformer/tsconfig.json b/packages/amplify-graphql-searchable-transformer/tsconfig.json index 276fe8970b..ee14ca8eb1 100644 --- a/packages/amplify-graphql-searchable-transformer/tsconfig.json +++ b/packages/amplify-graphql-searchable-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" } diff --git a/packages/amplify-graphql-sql-transformer/package.json b/packages/amplify-graphql-sql-transformer/package.json index 4db73a5d05..663f637f7d 100644 --- a/packages/amplify-graphql-sql-transformer/package.json +++ b/packages/amplify-graphql-sql-transformer/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-model-transformer": "2.6.0", "@aws-amplify/graphql-transformer-core": "2.5.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", diff --git a/packages/amplify-graphql-sql-transformer/src/graphql-sql-transformer.ts b/packages/amplify-graphql-sql-transformer/src/graphql-sql-transformer.ts index 324f3283e0..d8f88f7e5b 100644 --- a/packages/amplify-graphql-sql-transformer/src/graphql-sql-transformer.ts +++ b/packages/amplify-graphql-sql-transformer/src/graphql-sql-transformer.ts @@ -7,6 +7,7 @@ import { MappingTemplate, TransformerPluginBase, } from '@aws-amplify/graphql-transformer-core'; +import { SqlDirective } from '@aws-amplify/graphql-directives'; import { TransformerContextProvider, TransformerSchemaVisitStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; import * as cdk from 'aws-cdk-lib'; import { @@ -35,15 +36,12 @@ type SqlDirectiveConfiguration = { }; const SQL_DIRECTIVE_STACK = 'CustomSQLStack'; -const directiveDefinition = /* GraphQL */ ` - directive @sql(statement: String, reference: String) on FIELD_DEFINITION -`; export class SqlTransformer extends TransformerPluginBase { private sqlDirectiveFields: Map = new Map(); constructor() { - super('amplify-sql-transformer', directiveDefinition); + super('amplify-sql-transformer', SqlDirective.definition); } field = ( diff --git a/packages/amplify-graphql-sql-transformer/tsconfig.json b/packages/amplify-graphql-sql-transformer/tsconfig.json index 1f53494b21..bf970b21a9 100644 --- a/packages/amplify-graphql-sql-transformer/tsconfig.json +++ b/packages/amplify-graphql-sql-transformer/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../amplify-graphql-transformer-core" }, { "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/amplify-graphql-transformer-core/package.json b/packages/amplify-graphql-transformer-core/package.json index 9391b16f10..8d8e63edaa 100644 --- a/packages/amplify-graphql-transformer-core/package.json +++ b/packages/amplify-graphql-transformer-core/package.json @@ -28,6 +28,7 @@ "extract-api": "ts-node ../../scripts/extract-api.ts" }, "dependencies": { + "@aws-amplify/graphql-directives": "1.0.0", "@aws-amplify/graphql-transformer-interfaces": "3.4.0", "fs-extra": "^8.1.0", "graphql": "^15.5.0", diff --git a/packages/amplify-graphql-transformer-core/src/transformation/validation.ts b/packages/amplify-graphql-transformer-core/src/transformation/validation.ts index 83188ddfbe..24f1208830 100644 --- a/packages/amplify-graphql-transformer-core/src/transformation/validation.ts +++ b/packages/amplify-graphql-transformer-core/src/transformation/validation.ts @@ -57,6 +57,16 @@ import { UniqueDirectivesPerLocationRule } from 'graphql/validation/rules/Unique // AuthMode Types import { AppSyncAuthConfiguration, AppSyncAuthMode } from '@aws-amplify/graphql-transformer-interfaces'; import { validateSDL } from 'graphql/validation/validate'; +import { + AwsSubscribeDirective, + AwsAuthDirective, + AwsApiKeyDirective, + AwsIamDirective, + AwsOidcDirective, + AwsCognitoUserPoolsDirective, + AwsLambdaDirective, + DeprecatedDirective, +} from '@aws-amplify/graphql-directives'; /** * This set includes all validation rules defined by the GraphQL spec. @@ -106,18 +116,18 @@ scalar BigInt scalar Double `); -export const EXTRA_DIRECTIVES_DOCUMENT = parse(` -directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION -directive @aws_auth(cognito_groups: [String!]!) on FIELD_DEFINITION -directive @aws_api_key on FIELD_DEFINITION | OBJECT -directive @aws_iam on FIELD_DEFINITION | OBJECT -directive @aws_oidc on FIELD_DEFINITION | OBJECT -directive @aws_cognito_user_pools(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT -directive @aws_lambda on FIELD_DEFINITION | OBJECT - -# Allows transformer libraries to deprecate directive arguments. -directive @deprecated(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE -`); +export const EXTRA_DIRECTIVES_DOCUMENT = parse( + [ + AwsSubscribeDirective.definition, + AwsAuthDirective.definition, + AwsApiKeyDirective.definition, + AwsIamDirective.definition, + AwsOidcDirective.definition, + AwsCognitoUserPoolsDirective.definition, + AwsLambdaDirective.definition, + DeprecatedDirective.definition, + ].join('\n'), +); // As query type is mandatory in the schema we've to append a dummy one if it is not present const NOOP_QUERY = parse(` diff --git a/packages/amplify-graphql-transformer-core/tsconfig.json b/packages/amplify-graphql-transformer-core/tsconfig.json index 084f08346a..440bd6dbdf 100644 --- a/packages/amplify-graphql-transformer-core/tsconfig.json +++ b/packages/amplify-graphql-transformer-core/tsconfig.json @@ -4,5 +4,9 @@ "rootDir": "src", "outDir": "lib" }, - "references": [{ "path": "../amplify-graphql-transformer-interfaces" }, { "path": "../graphql-transformer-common" }] + "references": [ + { "path": "../amplify-graphql-directives" }, + { "path": "../amplify-graphql-transformer-interfaces" }, + { "path": "../graphql-transformer-common" } + ] } diff --git a/packages/amplify-graphql-transformer/src/graphql-transformer.ts b/packages/amplify-graphql-transformer/src/graphql-transformer.ts index aae1bbf5b7..60e50d3db2 100644 --- a/packages/amplify-graphql-transformer/src/graphql-transformer.ts +++ b/packages/amplify-graphql-transformer/src/graphql-transformer.ts @@ -61,6 +61,7 @@ export const constructTransformerChain = (options?: TransformerFactoryArgs): Tra const indexTransformer = new IndexTransformer(); const hasOneTransformer = new HasOneTransformer(); + // The default list of transformers should match DefaultDirectives in packages/amplify-graphql-directives/src/index.ts return [ modelTransformer, new FunctionTransformer(options?.functionNameMap), diff --git a/packages/graphql-auth-transformer/API.md b/packages/graphql-auth-transformer/API.md index 38ca3f54b9..d62a7d3885 100644 --- a/packages/graphql-auth-transformer/API.md +++ b/packages/graphql-auth-transformer/API.md @@ -119,7 +119,7 @@ export type UserPoolConfig = { // Warnings were encountered during analysis: // -// src/ModelAuthTransformer.ts:149:3 - (ae-forgotten-export) The symbol "AuthProvider" needs to be exported by the entry point index.d.ts +// src/ModelAuthTransformer.ts:144:3 - (ae-forgotten-export) The symbol "AuthProvider" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts b/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts index b9013b9d8d..2dd9b9087e 100644 --- a/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts +++ b/packages/graphql-auth-transformer/src/ModelAuthTransformer.ts @@ -1,11 +1,5 @@ -import { - Transformer, - TransformerContext, - InvalidDirectiveError, - gql, - getDirectiveArguments, - getFieldArguments, -} from 'graphql-transformer-core'; +import { Transformer, TransformerContext, InvalidDirectiveError, getDirectiveArguments, getFieldArguments } from 'graphql-transformer-core'; +import { AuthDirectiveV1 } from '@aws-amplify/graphql-directives'; import GraphQLAPI from 'cloudform-types/types/appSync/graphQlApi'; import Resolver from 'cloudform-types/types/appSync/resolver'; import { StringParameter } from 'cloudform-types'; @@ -20,6 +14,7 @@ import { NamedTypeNode, InputObjectTypeDefinitionNode, TypeDefinitionNode, + parse, } from 'graphql'; import { ResourceConstants, @@ -170,84 +165,7 @@ export class ModelAuthTransformer extends Transformer { unauthPolicyResources: Set; constructor(config?: ModelAuthTransformerConfig) { - super( - 'ModelAuthTransformer', - gql` - directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION - input AuthRule { - # Specifies the auth rule's strategy. Allowed values are 'owner', 'groups', 'public', 'private'. - allow: AuthStrategy! - - # Legacy name for identityClaim - identityField: String @deprecated(reason: "The 'identityField' argument is replaced by the 'identityClaim'.") - - # Specifies the name of the provider to use for the rule. This overrides the default provider - # when 'public' and 'private' AuthStrategy is used. Specifying a provider for 'owner' or 'groups' - # are not allowed. - provider: AuthProvider - - # Specifies the name of the claim to look for on the request's JWT token - # from Cognito User Pools (and in the future OIDC) that contains the identity - # of the user. If 'allow' is 'groups', this value should point to a list of groups - # in the claims. If 'allow' is 'owner', this value should point to the logged in user identity string. - # Defaults to "cognito:username" for Cognito User Pools auth. - identityClaim: String - - # Allows for custom config of 'groups' which is validated against the JWT - # Specifies a static list of groups that should have access to the object - groupClaim: String - - # Allowed when the 'allow' argument is 'owner'. - # Specifies the field of type String or [String] that contains owner(s) that can access the object. - ownerField: String # defaults to "owner" - # Allowed when the 'allow' argument is 'groups'. - # Specifies the field of type String or [String] that contains group(s) that can access the object. - groupsField: String - - # Allowed when the 'allow' argument is 'groups'. - # Specifies a static list of groups that should have access to the object. - groups: [String] - - # Specifies operations to which this auth rule should be applied. - operations: [ModelOperation] - - # Deprecated. It is recommended to use the 'operations' arguments. - queries: [ModelQuery] - @deprecated(reason: "The 'queries' argument will be replaced by the 'operations' argument in a future release.") - - # Deprecated. It is recommended to use the 'operations' arguments. - mutations: [ModelMutation] - @deprecated(reason: "The 'mutations' argument will be replaced by the 'operations' argument in a future release.") - } - enum AuthStrategy { - owner - groups - private - public - } - enum AuthProvider { - apiKey - iam - oidc - userPools - } - enum ModelOperation { - create - update - delete - read - } - enum ModelQuery @deprecated(reason: "ModelQuery will be replaced by the 'ModelOperation' in a future release.") { - get - list - } - enum ModelMutation @deprecated(reason: "ModelMutation will be replaced by the 'ModelOperation' in a future release.") { - create - update - delete - } - `, - ); + super('ModelAuthTransformer', parse(AuthDirectiveV1.definition)); if (config && config.authConfig) { this.config = config; diff --git a/packages/graphql-auth-transformer/tsconfig.json b/packages/graphql-auth-transformer/tsconfig.json index 623e46ce09..478cbfc9c6 100644 --- a/packages/graphql-auth-transformer/tsconfig.json +++ b/packages/graphql-auth-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-connection-transformer" }, { "path": "../graphql-dynamodb-transformer" }, { "path": "../graphql-elasticsearch-transformer" }, diff --git a/packages/graphql-connection-transformer/src/ModelConnectionTransformer.ts b/packages/graphql-connection-transformer/src/ModelConnectionTransformer.ts index fc1452f958..0ce9e26d09 100644 --- a/packages/graphql-connection-transformer/src/ModelConnectionTransformer.ts +++ b/packages/graphql-connection-transformer/src/ModelConnectionTransformer.ts @@ -1,4 +1,5 @@ -import { Transformer, TransformerContext, InvalidDirectiveError, gql, getDirectiveArguments } from 'graphql-transformer-core'; +import { Transformer, TransformerContext, InvalidDirectiveError, getDirectiveArguments } from 'graphql-transformer-core'; +import { ConnectionDirectiveV1 } from '@aws-amplify/graphql-directives'; import { DirectiveNode, ObjectTypeDefinitionNode, @@ -7,6 +8,7 @@ import { InterfaceTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, + parse, } from 'graphql'; import { makeModelConnectionType, @@ -165,19 +167,7 @@ export class ModelConnectionTransformer extends Transformer { resources: ResourceFactory; constructor() { - super( - 'ModelConnectionTransformer', - gql` - directive @connection( - name: String - keyField: String - sortField: String - keyName: String - limit: Int - fields: [String!] - ) on FIELD_DEFINITION - `, - ); + super('ModelConnectionTransformer', parse(ConnectionDirectiveV1.definition)); this.resources = new ResourceFactory(); } diff --git a/packages/graphql-connection-transformer/tsconfig.json b/packages/graphql-connection-transformer/tsconfig.json index c8118ff9fc..3793fefb97 100644 --- a/packages/graphql-connection-transformer/tsconfig.json +++ b/packages/graphql-connection-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-dynamodb-transformer" }, { "path": "../graphql-key-transformer" }, { "path": "../graphql-mapping-template" }, diff --git a/packages/graphql-dynamodb-transformer/src/DynamoDBModelTransformer.ts b/packages/graphql-dynamodb-transformer/src/DynamoDBModelTransformer.ts index 1901ed77c6..c5ddf4aa3e 100644 --- a/packages/graphql-dynamodb-transformer/src/DynamoDBModelTransformer.ts +++ b/packages/graphql-dynamodb-transformer/src/DynamoDBModelTransformer.ts @@ -1,5 +1,5 @@ import { DeletionPolicy, AppSync } from 'cloudform-types'; -import { DirectiveNode, ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode, FieldDefinitionNode } from 'graphql'; +import { DirectiveNode, ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode, FieldDefinitionNode, parse } from 'graphql'; import { blankObject, makeConnectionField, @@ -12,7 +12,8 @@ import { ResolverResourceIDs, getBaseType, } from 'graphql-transformer-common'; -import { getDirectiveArguments, gql, Transformer, TransformerContext, SyncConfig, InvalidDirectiveError } from 'graphql-transformer-core'; +import { getDirectiveArguments, Transformer, TransformerContext, SyncConfig, InvalidDirectiveError } from 'graphql-transformer-core'; +import { ModelDirectiveV1 } from '@aws-amplify/graphql-directives'; import { getNonModelObjectArray, makeCreateInputObject, @@ -62,38 +63,7 @@ export const CONDITIONS_MINIMUM_VERSION = 5; * } */ -export const directiveDefinition = gql` - directive @model( - queries: ModelQueryMap - mutations: ModelMutationMap - subscriptions: ModelSubscriptionMap - timestamps: TimestampConfiguration - ) on OBJECT - input ModelMutationMap { - create: String - update: String - delete: String - } - input ModelQueryMap { - get: String - list: String - } - input ModelSubscriptionMap { - onCreate: [String] - onUpdate: [String] - onDelete: [String] - level: ModelSubscriptionLevel - } - enum ModelSubscriptionLevel { - off - public - on - } - input TimestampConfiguration { - createdAt: String - updatedAt: String - } -`; +export const directiveDefinition = parse(ModelDirectiveV1.definition); export class DynamoDBModelTransformer extends Transformer { resources: ResourceFactory; diff --git a/packages/graphql-dynamodb-transformer/tsconfig.json b/packages/graphql-dynamodb-transformer/tsconfig.json index 8f1a5a05a1..f3fc268a32 100644 --- a/packages/graphql-dynamodb-transformer/tsconfig.json +++ b/packages/graphql-dynamodb-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, { "path": "../graphql-transformer-core" } diff --git a/packages/graphql-elasticsearch-transformer/src/SearchableModelTransformer.ts b/packages/graphql-elasticsearch-transformer/src/SearchableModelTransformer.ts index 183ee1635c..957f17bd47 100644 --- a/packages/graphql-elasticsearch-transformer/src/SearchableModelTransformer.ts +++ b/packages/graphql-elasticsearch-transformer/src/SearchableModelTransformer.ts @@ -1,6 +1,7 @@ import path = require('path'); -import { Transformer, TransformerContext, getDirectiveArguments, gql, InvalidDirectiveError } from 'graphql-transformer-core'; -import { DirectiveNode, ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode } from 'graphql'; +import { Transformer, TransformerContext, getDirectiveArguments, InvalidDirectiveError } from 'graphql-transformer-core'; +import { SearchableDirectiveV1 } from '@aws-amplify/graphql-directives'; +import { DirectiveNode, ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode, parse } from 'graphql'; import { makeNamedType, blankObjectExtension, @@ -45,15 +46,7 @@ export class SearchableModelTransformer extends Transformer { resources: ResourceFactory; constructor() { - super( - `SearchableModelTransformer`, - gql` - directive @searchable(queries: SearchableQueryMap) on OBJECT - input SearchableQueryMap { - search: String - } - `, - ); + super(`SearchableModelTransformer`, parse(SearchableDirectiveV1.definition)); this.resources = new ResourceFactory(); } diff --git a/packages/graphql-elasticsearch-transformer/tsconfig.json b/packages/graphql-elasticsearch-transformer/tsconfig.json index da3b983bfd..1814a1ef9f 100644 --- a/packages/graphql-elasticsearch-transformer/tsconfig.json +++ b/packages/graphql-elasticsearch-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-dynamodb-transformer" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, diff --git a/packages/graphql-function-transformer/src/FunctionTransformer.ts b/packages/graphql-function-transformer/src/FunctionTransformer.ts index 75e1e1c284..069866dd66 100644 --- a/packages/graphql-function-transformer/src/FunctionTransformer.ts +++ b/packages/graphql-function-transformer/src/FunctionTransformer.ts @@ -1,7 +1,8 @@ -import { Transformer, gql, TransformerContext, getDirectiveArguments, TransformerContractError } from 'graphql-transformer-core'; +import { Transformer, TransformerContext, getDirectiveArguments, TransformerContractError } from 'graphql-transformer-core'; +import { FunctionDirectiveV1 } from '@aws-amplify/graphql-directives'; import { obj, str, ref, printBlock, compoundExpression, qref, raw, iff } from 'graphql-mapping-template'; import { ResolverResourceIDs, FunctionResourceIDs, ResourceConstants } from 'graphql-transformer-common'; -import { ObjectTypeDefinitionNode, FieldDefinitionNode, DirectiveNode } from 'graphql'; +import { ObjectTypeDefinitionNode, FieldDefinitionNode, DirectiveNode, parse } from 'graphql'; import { AppSync, IAM, Fn } from 'cloudform-types'; import { lambdaArnResource } from './lambdaArns'; @@ -12,9 +13,7 @@ export class FunctionTransformer extends Transformer { // prettier-ignore super( 'FunctionTransformer', - gql` - directive @function(name: String!, region: String) repeatable on FIELD_DEFINITION - ` + parse(FunctionDirectiveV1.definition), ); } @@ -24,7 +23,7 @@ export class FunctionTransformer extends Transformer { field = (parent: ObjectTypeDefinitionNode, definition: FieldDefinitionNode, directive: DirectiveNode, ctx: TransformerContext) => { const { name, region } = getDirectiveArguments(directive); if (!name) { - throw new TransformerContractError(`Must supply a 'name' to @function.`); + throw new TransformerContractError(`Must supply a 'name' to @${FunctionDirectiveV1.name}.`); } // Add the iam role if it does not exist. diff --git a/packages/graphql-function-transformer/tsconfig.json b/packages/graphql-function-transformer/tsconfig.json index 8f1a5a05a1..f3fc268a32 100644 --- a/packages/graphql-function-transformer/tsconfig.json +++ b/packages/graphql-function-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, { "path": "../graphql-transformer-core" } diff --git a/packages/graphql-http-transformer/src/HttpTransformer.ts b/packages/graphql-http-transformer/src/HttpTransformer.ts index 302631d50d..d20854bb48 100644 --- a/packages/graphql-http-transformer/src/HttpTransformer.ts +++ b/packages/graphql-http-transformer/src/HttpTransformer.ts @@ -1,4 +1,5 @@ -import { Transformer, TransformerContext, TransformerContractError, gql } from 'graphql-transformer-core'; +import { Transformer, TransformerContext, TransformerContractError } from 'graphql-transformer-core'; +import { HttpDirectiveV1 } from '@aws-amplify/graphql-directives'; import { DirectiveNode, ObjectTypeDefinitionNode, @@ -7,6 +8,7 @@ import { InterfaceTypeDefinitionNode, InputValueDefinitionNode, print, + parse, } from 'graphql'; import { getDirectiveArgument, isScalar, ResolverResourceIDs, HttpResourceIDs } from 'graphql-transformer-common'; import { ResourceFactory } from './resources'; @@ -39,23 +41,7 @@ export class HttpTransformer extends Transformer { static urlRegex = /(http(s)?:\/\/)|(\/.*)/g; constructor() { - super( - 'HttpTransformer', - gql` - directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION - enum HttpMethod { - GET - POST - PUT - DELETE - PATCH - } - input HttpHeader { - key: String - value: String - } - `, - ); + super('HttpTransformer', parse(HttpDirectiveV1.definition)); this.resources = new ResourceFactory(); } diff --git a/packages/graphql-http-transformer/tsconfig.json b/packages/graphql-http-transformer/tsconfig.json index 8f1a5a05a1..f3fc268a32 100644 --- a/packages/graphql-http-transformer/tsconfig.json +++ b/packages/graphql-http-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, { "path": "../graphql-transformer-core" } diff --git a/packages/graphql-key-transformer/src/KeyTransformer.ts b/packages/graphql-key-transformer/src/KeyTransformer.ts index e65731c2e3..ac53778892 100644 --- a/packages/graphql-key-transformer/src/KeyTransformer.ts +++ b/packages/graphql-key-transformer/src/KeyTransformer.ts @@ -1,4 +1,5 @@ -import { Transformer, gql, TransformerContext, getDirectiveArguments, InvalidDirectiveError } from 'graphql-transformer-core'; +import { Transformer, TransformerContext, getDirectiveArguments, InvalidDirectiveError } from 'graphql-transformer-core'; +import { KeyDirectiveV1 } from '@aws-amplify/graphql-directives'; import { obj, str, @@ -63,6 +64,7 @@ import { Kind, InputValueDefinitionNode, EnumTypeDefinitionNode, + parse, } from 'graphql'; import { AppSync, Fn, Refs } from 'cloudform-types'; import { Projection, GlobalSecondaryIndex, LocalSecondaryIndex } from 'cloudform-types/types/dynamoDb/table'; @@ -79,9 +81,7 @@ export class KeyTransformer extends Transformer { // prettier-ignore super( 'KeyTransformer', - gql` - directive @key(name: String, fields: [String!]!, queryField: String) repeatable on OBJECT - ` + parse(KeyDirectiveV1.definition), ); } diff --git a/packages/graphql-key-transformer/tsconfig.json b/packages/graphql-key-transformer/tsconfig.json index da3b983bfd..1814a1ef9f 100644 --- a/packages/graphql-key-transformer/tsconfig.json +++ b/packages/graphql-key-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-dynamodb-transformer" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, diff --git a/packages/graphql-predictions-transformer/src/PredictionsTransformer.ts b/packages/graphql-predictions-transformer/src/PredictionsTransformer.ts index ad8f85482f..89c7e74bef 100644 --- a/packages/graphql-predictions-transformer/src/PredictionsTransformer.ts +++ b/packages/graphql-predictions-transformer/src/PredictionsTransformer.ts @@ -6,8 +6,10 @@ import { valueFromASTUntyped, ArgumentNode, InputValueDefinitionNode, + parse, } from 'graphql'; -import { Transformer, gql, TransformerContext, InvalidDirectiveError } from 'graphql-transformer-core'; +import { Transformer, TransformerContext, InvalidDirectiveError } from 'graphql-transformer-core'; +import { PredictionsDirectiveV1 } from '@aws-amplify/graphql-directives'; import { ResolverResourceIDs, PredictionsResourceIDs } from 'graphql-transformer-common'; import { Fn } from 'cloudform-types'; import { getActionInputType, makeActionInputObject, getActionInputName, addInputArgument, createInputValueAction } from './definitions'; @@ -26,19 +28,7 @@ export class PredictionsTransformer extends Transformer { predictionsConfig: PredictionsConfig; constructor(predictionsConfig?: PredictionsConfig) { - super( - 'PredictionsTransformer', - gql` - # where the parent this field is defined on is a query type - directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION - enum PredictionsActions { - identifyText - identifyLabels - convertTextToSpeech - translateText - } - `, - ); + super('PredictionsTransformer', parse(PredictionsDirectiveV1.definition)); this.resources = new ResourceFactory(); this.predictionsConfig = predictionsConfig; } diff --git a/packages/graphql-predictions-transformer/tsconfig.json b/packages/graphql-predictions-transformer/tsconfig.json index 8f1a5a05a1..f3fc268a32 100644 --- a/packages/graphql-predictions-transformer/tsconfig.json +++ b/packages/graphql-predictions-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, { "path": "../graphql-transformer-core" } diff --git a/packages/graphql-relational-schema-transformer/tsconfig.json b/packages/graphql-relational-schema-transformer/tsconfig.json index 723a6bdb53..02f3ff8297 100644 --- a/packages/graphql-relational-schema-transformer/tsconfig.json +++ b/packages/graphql-relational-schema-transformer/tsconfig.json @@ -5,5 +5,9 @@ "rootDir": "src", "outDir": "lib" }, - "references": [{ "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }] + "references": [ + { "path": "../amplify-graphql-directives" }, + { "path": "../graphql-mapping-template" }, + { "path": "../graphql-transformer-common" } + ] } diff --git a/packages/graphql-versioned-transformer/src/VersionedModelTransformer.ts b/packages/graphql-versioned-transformer/src/VersionedModelTransformer.ts index df60602a87..7cf4b4a87d 100644 --- a/packages/graphql-versioned-transformer/src/VersionedModelTransformer.ts +++ b/packages/graphql-versioned-transformer/src/VersionedModelTransformer.ts @@ -1,5 +1,6 @@ -import { Transformer, TransformerContext, InvalidDirectiveError, TransformerContractError, gql } from 'graphql-transformer-core'; -import { valueFromASTUntyped, ArgumentNode, ObjectTypeDefinitionNode, DirectiveNode, Kind } from 'graphql'; +import { Transformer, TransformerContext, InvalidDirectiveError, TransformerContractError } from 'graphql-transformer-core'; +import { VersionedDirectiveV1 } from '@aws-amplify/graphql-directives'; +import { valueFromASTUntyped, ArgumentNode, ObjectTypeDefinitionNode, DirectiveNode, Kind, parse } from 'graphql'; import { printBlock, compoundExpression, set, ref, qref, obj, str, raw } from 'graphql-mapping-template'; import { ResourceConstants, @@ -14,13 +15,7 @@ import { export class VersionedModelTransformer extends Transformer { constructor() { - super( - 'VersionedModelTransformer', - // TODO: Allow version attribute selection. Could be `@version on FIELD_DEFINITION` - gql` - directive @versioned(versionField: String = "version", versionInput: String = "expectedVersion") on OBJECT - `, - ); + super('VersionedModelTransformer', parse(VersionedDirectiveV1.definition)); } /** diff --git a/packages/graphql-versioned-transformer/tsconfig.json b/packages/graphql-versioned-transformer/tsconfig.json index 8f1a5a05a1..f3fc268a32 100644 --- a/packages/graphql-versioned-transformer/tsconfig.json +++ b/packages/graphql-versioned-transformer/tsconfig.json @@ -6,6 +6,7 @@ "outDir": "lib" }, "references": [ + { "path": "../amplify-graphql-directives" }, { "path": "../graphql-mapping-template" }, { "path": "../graphql-transformer-common" }, { "path": "../graphql-transformer-core" }