diff --git a/package-lock.json b/package-lock.json index 4cc95f92..06656a6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,6 @@ "serverless": "^3.25.1", "ts-jest": "^27.1.5", "ts-node": "^10.9.1", - "ts-toolbelt": "^9.6.0", "typescript": "^4.9.3" }, "peerDependencies": { @@ -14889,12 +14888,6 @@ "node": ">=0.3.1" } }, - "node_modules/ts-toolbelt": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true - }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -26899,12 +26892,6 @@ } } }, - "ts-toolbelt": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true - }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", diff --git a/package.json b/package.json index c1eb6f6f..3b3f0e4b 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "serverless": "^3.25.1", "ts-jest": "^27.1.5", "ts-node": "^10.9.1", - "ts-toolbelt": "^9.6.0", "typescript": "^4.9.3" }, "dependencies": { diff --git a/src/types/common.ts b/src/types/common.ts new file mode 100644 index 00000000..b2815632 --- /dev/null +++ b/src/types/common.ts @@ -0,0 +1,244 @@ +import { CfnWafRuleStatement, IntrinsicFunction } from './cloudFormation'; + +export type IamStatement = { + Effect: 'Allow' | 'Deny'; + Action: string[]; + Resource: string | IntrinsicFunction | (string | IntrinsicFunction)[]; +}; + +export type WafConfig = { + enabled?: boolean; + arn?: string; + name?: string; + defaultAction?: WafAction; + description?: string; + visibilityConfig?: VisibilityConfig; + rules?: WafRule[]; +}; + +export type WafThrottleConfig = + | number + | { + name?: string; + action?: WafAction; + aggregateKeyType?: 'IP' | 'FORWARDED_IP'; + limit?: number; + priority?: number; + forwardedIPConfig?: { + headerName: string; + fallbackBehavior: 'MATCH' | 'NO_MATCH'; + }; + scopeDownStatement?: CfnWafRuleStatement; + visibilityConfig?: VisibilityConfig; + }; + +export type WafDisableIntrospectionConfig = { + name?: string; + priority?: number; + visibilityConfig?: VisibilityConfig; +}; + +export type WafAction = 'Allow' | 'Block'; +export type WafRuleAction = 'Allow' | 'Block' | 'Count' | 'Captcha'; + +export type WafRuleThrottle = { + throttle: WafThrottleConfig; +}; + +export type WafRuleCustom = { + name: string; + priority?: number; + action?: WafRuleAction; + statement: CfnWafRuleStatement; + visibilityConfig?: VisibilityConfig; +}; + +export type WafRuleDisableIntrospection = { + disableIntrospection: WafDisableIntrospectionConfig; +}; + +export type WafRule = + | WafRuleThrottle + | WafRuleDisableIntrospection + | WafRuleCustom + | 'disableIntrospection' + | 'throttle'; + +export type ApiKeyConfig = { + apiKeyId?: string; + name: string; + description?: string; + expiresAfter?: string | number; + expiresAt?: string; + wafRules?: WafRule[]; +}; + +export type CognitoAuth = { + type: 'AMAZON_COGNITO_USER_POOLS'; + config: { + userPoolId: string | IntrinsicFunction; + awsRegion?: string | IntrinsicFunction; + defaultAction?: 'ALLOW' | 'DENY'; + appIdClientRegex?: string | IntrinsicFunction; + }; +}; + +export type IamAuth = { + type: 'AWS_IAM'; +}; + +export type LambdaAuth = { + type: 'AWS_LAMBDA'; + config: LambdaConfig & { + identityValidationExpression?: string; + authorizerResultTtlInSeconds?: number; + }; +}; + +export type OidcAuth = { + type: 'OPENID_CONNECT'; + config: { + issuer: string; + clientId: string; + iatTTL?: number; + authTTL?: number; + }; +}; + +export type ApiKeyAuth = { + type: 'API_KEY'; +}; + +export type Auth = CognitoAuth | LambdaAuth | OidcAuth | ApiKeyAuth | IamAuth; + +export type DomainConfig = { + enabled?: boolean; + useCloudFormation?: boolean; + retain?: boolean; + name: string; + certificateArn?: string; + hostedZoneId?: string; + hostedZoneName?: string; + route53?: boolean; +}; + +export type SyncConfig = { + conflictDetection: 'VERSION' | 'NONE'; + conflictHandler: 'OPTIMISTIC_CONCURRENCY' | 'AUTOMERGE' | 'LAMBDA'; +} & LambdaConfig; + +export type Substitutions = Record; + +export type DsDynamoDBConfig = { + type: 'AMAZON_DYNAMODB'; + config: { + tableName: string | IntrinsicFunction; + useCallerCredentials?: boolean; + serviceRoleArn?: string | IntrinsicFunction; + region?: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + versioned?: boolean; + deltaSyncConfig?: { + deltaSyncTableName: string; + baseTableTTL?: number; + deltaSyncTableTTL?: number; + }; + }; +}; + +export type DsEventBridgeConfig = { + type: 'AMAZON_EVENTBRIDGE'; + config: { + serviceRoleArn?: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + eventBusArn: string | IntrinsicFunction; + }; +}; + +export type DsRelationalDbConfig = { + type: 'RELATIONAL_DATABASE'; + config: { + region?: string; + relationalDatabaseSourceType?: 'RDS_HTTP_ENDPOINT'; + serviceRoleArn?: string | IntrinsicFunction; + dbClusterIdentifier: string | IntrinsicFunction; + databaseName?: string | IntrinsicFunction; + schema?: string; + awsSecretStoreArn: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + }; +}; + +export type DsOpenSearchConfig = { + type: 'AMAZON_OPENSEARCH_SERVICE'; + config: { + domain?: string; + endpoint?: string | IntrinsicFunction; + region?: string | IntrinsicFunction; + serviceRoleArn?: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + }; +}; + +export type LambdaConfig = + | { + functionName: string; + functionAlias?: string; + } + | { + functionArn: string | IntrinsicFunction; + } + | { + function: Record; + }; + +export type DsLambdaConfig = { + type: 'AWS_LAMBDA'; + config: { + serviceRoleArn?: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + } & LambdaConfig; +}; + +export type DsHttpConfig = { + type: 'HTTP'; + config: { + endpoint: string | IntrinsicFunction; + serviceRoleArn?: string | IntrinsicFunction; + iamRoleStatements?: IamStatement[]; + authorizationConfig?: { + authorizationType: 'AWS_IAM'; + awsIamConfig: { + signingRegion: string | IntrinsicFunction; + signingServiceName?: string | IntrinsicFunction; + }; + }; + }; +}; + +export type DsNone = { + type: 'NONE'; +}; + +export type VisibilityConfig = { + name?: string; + cloudWatchMetricsEnabled?: boolean; + sampledRequestsEnabled?: boolean; +}; + +export type LoggingConfig = { + level: 'ERROR' | 'NONE' | 'ALL'; + enabled?: boolean; + excludeVerboseContent?: boolean; + retentionInDays?: number; + roleArn?: string | IntrinsicFunction; +}; + +export type CachingConfig = { + enabled?: boolean; + behavior: 'FULL_REQUEST_CACHING' | 'PER_RESOLVER_CACHING'; + type?: string; + ttl?: number; + atRestEncryption?: boolean; + transitEncryption?: boolean; +}; diff --git a/src/types/index.ts b/src/types/index.ts index f4543149..c8cfae9b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,50 +1,95 @@ -import { A, O } from 'ts-toolbelt'; +import { BuildOptions } from 'esbuild'; import { - DataSourceConfig as InternalDataSourceConfig, - ResolverConfig as InternalResolverConfig, - PipelineFunctionConfig as InternalPipelineFunctionConfig, ApiKeyConfig, - AppSyncConfig as InternalAppSyncConfig, -} from './plugin'; + Auth, + Substitutions, + CachingConfig, + DomainConfig, + LoggingConfig, + WafConfig, + DsDynamoDBConfig, + DsEventBridgeConfig, + DsHttpConfig, + DsLambdaConfig, + DsNone, + DsOpenSearchConfig, + DsRelationalDbConfig, + SyncConfig, +} from './common'; +export * from './common'; -/* Completely replaces keys of O1 with those of O */ -type Replace = O.Merge< - O, - O.Omit> ->; +export type AppSyncConfig = { + name: string; + schema?: string | string[]; + authentication: Auth; + additionalAuthentications?: Auth[]; + domain?: DomainConfig; + apiKeys?: (ApiKeyConfig | string)[]; + resolvers?: Record[] | Record; + pipelineFunctions?: + | Record[] + | Record; + dataSources: + | Record[] + | Record; + substitutions?: Substitutions; + xrayEnabled?: boolean; + logging?: LoggingConfig; + caching?: CachingConfig; + waf?: WafConfig; + tags?: Record; + visibility?: 'GLOBAL' | 'PRIVATE'; + esbuild?: BuildOptions | false; +}; -export * from './plugin'; +export type BaseResolverConfig = { + field?: string; + type?: string; + request?: string | false; + response?: string | false; + code?: string; + caching?: + | { + ttl?: number; + keys?: string[]; + } + | boolean; + sync?: SyncConfig; + substitutions?: Substitutions; +}; -export type DataSourceConfig = O.Omit; +export type ResolverConfig = UnitResolverConfig | PipelineResolverConfig; -export type PipelineFunctionConfig = Replace< - { dataSource: string | DataSourceConfig }, - O.Omit ->; +export type UnitResolverConfig = BaseResolverConfig & { + kind: 'UNIT'; + dataSource: string | DataSourceConfig; + maxBatchSize?: number; +}; -export type ResolverConfig = O.Update< - O.Update< - O.Optional, - 'dataSource', - string | DataSourceConfig - >, - 'functions', - (string | PipelineFunctionConfig)[] ->; +export type PipelineResolverConfig = BaseResolverConfig & { + kind?: 'PIPELINE'; + functions: (string | PipelineFunctionConfig)[]; +}; -export type AppSyncConfig = Replace< - { - schema?: string | string[]; - apiKeys?: (ApiKeyConfig | string)[]; - resolvers?: - | Record[] - | Record; - pipelineFunctions?: - | Record[] - | Record; - dataSources: - | Record[] - | Record; - }, - O.Optional ->; +export type DataSourceConfig = { + description?: string; +} & ( + | DsHttpConfig + | DsDynamoDBConfig + | DsRelationalDbConfig + | DsOpenSearchConfig + | DsLambdaConfig + | DsEventBridgeConfig + | DsNone +); + +export type PipelineFunctionConfig = { + dataSource: string | DataSourceConfig; + description?: string; + code?: string; + request?: string; + response?: string; + maxBatchSize?: number; + substitutions?: Substitutions; + sync?: SyncConfig; +}; diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 8e5538d2..f7e245de 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -1,5 +1,22 @@ -import { CfnWafRuleStatement, IntrinsicFunction } from './cloudFormation'; import { BuildOptions } from 'esbuild'; +import { + Auth, + DomainConfig, + ApiKeyConfig, + LoggingConfig, + CachingConfig, + WafConfig, + SyncConfig, + DsHttpConfig, + DsDynamoDBConfig, + DsRelationalDbConfig, + DsOpenSearchConfig, + DsLambdaConfig, + DsEventBridgeConfig, + DsNone, + Substitutions, +} from './common'; +export * from './common'; export type AppSyncConfig = { name: string; @@ -21,133 +38,6 @@ export type AppSyncConfig = { esbuild?: BuildOptions | false; }; -export type IamStatement = { - Effect: 'Allow' | 'Deny'; - Action: string[]; - Resource: string | IntrinsicFunction | (string | IntrinsicFunction)[]; -}; - -export type WafConfig = { - enabled?: boolean; - arn?: string; - name?: string; - defaultAction?: WafAction; - description?: string; - visibilityConfig?: VisibilityConfig; - rules?: WafRule[]; -}; - -export type WafThrottleConfig = - | number - | { - name?: string; - action?: WafAction; - aggregateKeyType?: 'IP' | 'FORWARDED_IP'; - limit?: number; - priority?: number; - forwardedIPConfig?: { - headerName: string; - fallbackBehavior: 'MATCH' | 'NO_MATCH'; - }; - scopeDownStatement?: CfnWafRuleStatement; - visibilityConfig?: VisibilityConfig; - }; - -export type WafDisableIntrospectionConfig = { - name?: string; - priority?: number; - visibilityConfig?: VisibilityConfig; -}; - -export type WafAction = 'Allow' | 'Block'; -export type WafRuleAction = 'Allow' | 'Block' | 'Count' | 'Captcha'; - -export type WafRuleThrottle = { - throttle: WafThrottleConfig; -}; - -export type WafRuleCustom = { - name: string; - priority?: number; - action?: WafRuleAction; - statement: CfnWafRuleStatement; - visibilityConfig?: VisibilityConfig; -}; - -export type WafRuleDisableIntrospection = { - disableIntrospection: WafDisableIntrospectionConfig; -}; - -export type WafRule = - | WafRuleThrottle - | WafRuleDisableIntrospection - | WafRuleCustom - | 'disableIntrospection' - | 'throttle'; - -export type ApiKeyConfig = { - apiKeyId?: string; - name: string; - description?: string; - expiresAfter?: string | number; - expiresAt?: string; - wafRules?: WafRule[]; -}; - -export type CognitoAuth = { - type: 'AMAZON_COGNITO_USER_POOLS'; - config: { - userPoolId: string | IntrinsicFunction; - awsRegion?: string | IntrinsicFunction; - defaultAction?: 'ALLOW' | 'DENY'; - appIdClientRegex?: string | IntrinsicFunction; - }; -}; - -export type IamAuth = { - type: 'AWS_IAM'; -}; - -export type LambdaAuth = { - type: 'AWS_LAMBDA'; - config: LambdaConfig & { - identityValidationExpression?: string; - authorizerResultTtlInSeconds?: number; - }; -}; - -export type OidcAuth = { - type: 'OPENID_CONNECT'; - config: { - issuer: string; - clientId: string; - iatTTL?: number; - authTTL?: number; - }; -}; - -export type ApiKeyAuth = { - type: 'API_KEY'; -}; - -export type Auth = CognitoAuth | LambdaAuth | OidcAuth | ApiKeyAuth | IamAuth; - -export type DomainConfig = { - enabled?: boolean; - useCloudFormation?: boolean; - retain?: boolean; - name: string; - certificateArn?: string; - hostedZoneId?: string; - hostedZoneName?: string; - route53?: boolean; -}; - -export type SyncConfig = { - conflictDetection: 'VERSION' | 'NONE'; - conflictHandler: 'OPTIMISTIC_CONCURRENCY' | 'AUTOMERGE' | 'LAMBDA'; -} & LambdaConfig; - export type BaseResolverConfig = { field: string; type: string; @@ -177,111 +67,6 @@ export type PipelineResolverConfig = BaseResolverConfig & { functions: string[]; }; -export type Substitutions = Record; - -export type PipelineFunctionConfig = { - name: string; - dataSource: string; - description?: string; - code?: string; - request?: string; - response?: string; - maxBatchSize?: number; - substitutions?: Substitutions; - sync?: SyncConfig; -}; - -export type DsDynamoDBConfig = { - type: 'AMAZON_DYNAMODB'; - config: { - tableName: string | IntrinsicFunction; - useCallerCredentials?: boolean; - serviceRoleArn?: string | IntrinsicFunction; - region?: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - versioned?: boolean; - deltaSyncConfig?: { - deltaSyncTableName: string; - baseTableTTL?: number; - deltaSyncTableTTL?: number; - }; - }; -}; - -export type DsEventBridgeConfig = { - type: 'AMAZON_EVENTBRIDGE'; - config: { - serviceRoleArn?: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - eventBusArn: string | IntrinsicFunction; - }; -}; - -export type DsRelationalDbConfig = { - type: 'RELATIONAL_DATABASE'; - config: { - region?: string; - relationalDatabaseSourceType?: 'RDS_HTTP_ENDPOINT'; - serviceRoleArn?: string | IntrinsicFunction; - dbClusterIdentifier: string | IntrinsicFunction; - databaseName?: string | IntrinsicFunction; - schema?: string; - awsSecretStoreArn: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - }; -}; - -export type DsOpenSearchConfig = { - type: 'AMAZON_OPENSEARCH_SERVICE'; - config: { - domain?: string; - endpoint?: string | IntrinsicFunction; - region?: string | IntrinsicFunction; - serviceRoleArn?: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - }; -}; - -export type LambdaConfig = - | { - functionName: string; - functionAlias?: string; - } - | { - functionArn: string | IntrinsicFunction; - } - | { - function: Record; - }; - -export type DsLambdaConfig = { - type: 'AWS_LAMBDA'; - config: { - serviceRoleArn?: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - } & LambdaConfig; -}; - -export type DsHttpConfig = { - type: 'HTTP'; - config: { - endpoint: string | IntrinsicFunction; - serviceRoleArn?: string | IntrinsicFunction; - iamRoleStatements?: IamStatement[]; - authorizationConfig?: { - authorizationType: 'AWS_IAM'; - awsIamConfig: { - signingRegion: string | IntrinsicFunction; - signingServiceName?: string | IntrinsicFunction; - }; - }; - }; -}; - -export type DsNone = { - type: 'NONE'; -}; - export type DataSourceConfig = { name: string; description?: string; @@ -295,25 +80,15 @@ export type DataSourceConfig = { | DsNone ); -export type VisibilityConfig = { - name?: string; - cloudWatchMetricsEnabled?: boolean; - sampledRequestsEnabled?: boolean; -}; - -export type LoggingConfig = { - level: 'ERROR' | 'NONE' | 'ALL'; - enabled?: boolean; - excludeVerboseContent?: boolean; - retentionInDays?: number; - roleArn?: string | IntrinsicFunction; -}; - -export type CachingConfig = { - enabled?: boolean; - behavior: 'FULL_REQUEST_CACHING' | 'PER_RESOLVER_CACHING'; - type?: string; - ttl?: number; - atRestEncryption?: boolean; - transitEncryption?: boolean; +export type PipelineFunctionConfig = { + name: string; + dataSource: string; + description?: string; + code?: string; + request?: string; + response?: string; + maxBatchSize?: number; + substitutions?: Substitutions; + sync?: SyncConfig; }; +export { Substitutions };