Skip to content

Instantly share code, notes, and snippets.

@zirkelc
Last active February 13, 2023 09:27
Show Gist options
  • Save zirkelc/084fcec40849e4189749fd9076d5350c to your computer and use it in GitHub Desktop.
Save zirkelc/084fcec40849e4189749fd9076d5350c to your computer and use it in GitHub Desktop.
Serverless Step Function Type Defintions
import type { AWS } from '@serverless/typescript';
export interface CustomServerless extends AWS {
stepFunctions: {
stateMachines: StateMachines;
validate?: boolean;
};
}
type StateMachines = {
[stateMachine: string]: {
id: string;
name: string;
definition: Definition;
tracingConfig?: TracingConfig;
};
};
type TracingConfig = {
enabled: boolean;
};
type Definition = {
Comment?: string;
StartAt: string;
States: States;
};
type States = {
[state: string]: Choice | Fail | Map | Task | Parallel | Pass | Wait;
};
type StateBase = {
Catch?: Catcher[];
Retry?: Retrier[];
End?: boolean;
InputPath?: string;
Next?: string;
OutputPath?: string;
ResultPath?: string;
ResultSelector?: { [key: string]: string | { [key: string]: string } };
Type: string;
Comment?: string;
};
type ChoiceRuleComparison = {
Variable: string;
BooleanEquals?: number;
BooleanEqualsPath?: string;
IsBoolean?: boolean;
IsNull?: boolean;
IsNumeric?: boolean;
IsPresent?: boolean;
IsString?: boolean;
IsTimestamp?: boolean;
NumericEquals?: number;
NumericEqualsPath?: string;
NumericGreaterThan?: number;
NumericGreaterThanPath?: string;
NumericGreaterThanEquals?: number;
NumericGreaterThanEqualsPath?: string;
NumericLessThan?: number;
NumericLessThanPath?: string;
NumericLessThanEquals?: number;
NumericLessThanEqualsPath?: string;
StringEquals?: string;
StringEqualsPath?: string;
StringGreaterThan?: string;
StringGreaterThanPath?: string;
StringGreaterThanEquals?: string;
StringGreaterThanEqualsPath?: string;
StringLessThan?: string;
StringLessThanPath?: string;
StringLessThanEquals?: string;
StringLessThanEqualsPath?: string;
StringMatches?: string;
TimestampEquals?: string;
TimestampEqualsPath?: string;
TimestampGreaterThan?: string;
TimestampGreaterThanPath?: string;
TimestampGreaterThanEquals?: string;
TimestampGreaterThanEqualsPath?: string;
TimestampLessThan?: string;
TimestampLessThanPath?: string;
TimestampLessThanEquals?: string;
TimestampLessThanEqualsPath?: string;
};
type ChoiceRuleNot = {
Not: ChoiceRuleComparison;
Next: string;
};
type ChoiceRuleAnd = {
And: ChoiceRuleComparison[];
Next: string;
};
type ChoiceRuleOr = {
Or: ChoiceRuleComparison[];
Next: string;
};
type ChoiceRuleSimple = ChoiceRuleComparison & {
Next: string;
};
type ChoiceRule = ChoiceRuleSimple | ChoiceRuleNot | ChoiceRuleAnd | ChoiceRuleOr;
interface Choice extends StateBase {
Type: 'Choice';
Choices: ChoiceRule[];
Default?: string;
}
interface Fail extends StateBase {
Type: 'Fail';
Cause?: string;
Error?: string;
}
interface Map extends StateBase {
Type: 'Map';
ItemsPath: string;
Iterator: Definition;
}
type Resource = string | { 'Fn::GetAtt': [string, 'Arn'] } | { 'Fn::Join': [string, Resource[]] };
interface TaskParametersForLambda {
FunctionName?: Resource;
Payload?: {
'token.$': string;
[key: string]: string;
};
[key: string]: unknown;
}
interface TaskParametersForStepFunction {
StateMachineArn: Resource;
Input?: {
'AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$': '$$.Execution.Id';
[key: string]: string;
};
Retry?: [{ ErrorEquals?: string[] }];
End?: boolean;
}
interface Task extends StateBase {
Type: 'Task';
Resource: Resource;
Parameters?:
| TaskParametersForLambda
| TaskParametersForStepFunction
| { [key: string]: string | { [key: string]: string } };
}
interface Pass extends StateBase {
Type: 'Pass';
Parameters?: {
[key: string]: string | Array<unknown> | { [key: string]: string };
};
}
interface Parallel extends StateBase {
Type: 'Parallel';
Branches: Definition[];
}
interface Wait extends StateBase {
Type: 'Wait';
Next?: string;
Seconds: number;
}
type Catcher = {
ErrorEquals: ErrorName[];
Next: string;
ResultPath?: string;
};
type Retrier = {
ErrorEquals: string[];
IntervalSeconds?: number;
MaxAttempts?: number;
BackoffRate?: number;
};
type ErrorName =
| 'States.ALL'
| 'States.DataLimitExceeded'
| 'States.Runtime'
| 'States.Timeout'
| 'States.TaskFailed'
| 'States.Permissions'
| string;
@zirkelc
Copy link
Author

zirkelc commented Feb 10, 2023

@zoiman the definition follows the official AWS State Language specification: https://states-language.net/spec.html

There is no event attribute described. Do you mean events like the Serverless Framework provides as triggers?

@zoiman
Copy link

zoiman commented Feb 11, 2023

yes exactly events. Here is an example:

stepFunctions:
validate: true
stateMachines:
MyStatemachine:
name: mystatemachine
events:
- http:
path: /
method: POST

@zirkelc
Copy link
Author

zirkelc commented Feb 11, 2023

Yeah these events come from the severless-step-functions plugin and are not an inherent part of AWS StepFunctions. You can find the full list of supported events here: https://github.com/serverless-operations/serverless-step-functions#events

It might be possible to copy the event definition from the types for Lambda functions, something like this:

type StateMachines = {
  [stateMachine: string]: {
      id: string;
      name: string;
      definition: Definition;
      tracingConfig?: TracingConfig;
      events?: (
        | {
            __schemaWorkaround__: null;
          }
        | {
            schedule:
              | string
              | {
                  rate: string[];
                  enabled?: boolean;
                  name?: string;
                  description?: string;
                  input?:
                    | string
                    | (
                        | {
                            body: string;
                          }
                        | {
                            [k: string]: unknown;
                          }
                      );
                  inputPath?: string;
                  inputTransformer?: {
                    inputTemplate: string;
                    inputPathsMap?: {
                      [k: string]: unknown;
                    };
                  };
                };
          }
        | {
            s3:
              | string
              | {
                  bucket: string | AwsCfFunction | AwsCfIf;
                  event?: string;
                  existing?: boolean;
                  forceDeploy?: boolean;
                  rules?: {
                    prefix?: string | AwsCfFunction;
                    suffix?: string | AwsCfFunction;
                  }[];
                };
          }
        | {
            http:
              | string
              | {
                  async?: boolean;
                  authorizer?:
                    | string
                    | {
                        arn?: AwsArn;
                        authorizerId?: AwsCfInstruction;
                        claims?: string[];
                        identitySource?: string;
                        identityValidationExpression?: string;
                        managedExternally?: boolean;
                        name?: string;
                        resultTtlInSeconds?: number;
                        scopes?: (string | AwsCfInstruction)[];
                        type?: string | string | string | string | string;
                      };
                  connectionId?: AwsCfInstruction;
                  connectionType?: string | string;
                  cors?:
                    | boolean
                    | {
                        allowCredentials?: boolean;
                        cacheControl?: string;
                        headers?: string[];
                        maxAge?: number;
                        methods?: ("GET" | "POST" | "PUT" | "PATCH" | "OPTIONS" | "HEAD" | "DELETE" | "ANY")[];
                        origin?: string;
                        origins?: string[];
                      };
                  integration?: string | string | string | string | string | string | string | string | string | string;
                  method: string;
                  operationId?: string;
                  path: string;
                  private?: boolean;
                  request?: {
                    contentHandling?: "CONVERT_TO_BINARY" | "CONVERT_TO_TEXT";
                    method?: string;
                    parameters?: {
                      querystrings?: {
                        [k: string]:
                          | boolean
                          | {
                              required?: boolean;
                              mappedValue?: AwsCfInstruction;
                            };
                      };
                      headers?: {
                        [k: string]:
                          | boolean
                          | {
                              required?: boolean;
                              mappedValue?: AwsCfInstruction;
                            };
                      };
                      paths?: {
                        [k: string]:
                          | boolean
                          | {
                              required?: boolean;
                              mappedValue?: AwsCfInstruction;
                            };
                      };
                    };
                    passThrough?: "NEVER" | "WHEN_NO_MATCH" | "WHEN_NO_TEMPLATES";
                    schemas?: {
                      [k: string]:
                        | {
                            [k: string]: unknown;
                          }
                        | string;
                    };
                    template?: {
                      [k: string]: string;
                    };
                    uri?: AwsCfInstruction;
                  };
                  response?: {
                    contentHandling?: "CONVERT_TO_BINARY" | "CONVERT_TO_TEXT";
                    headers?: {
                      [k: string]: string;
                    };
                    template?: string;
                    statusCodes?: {
                      [k: string]: {
                        headers?: {
                          [k: string]: string;
                        };
                        pattern?: string;
                        template?:
                          | string
                          | {
                              [k: string]: string;
                            };
                      };
                    };
                  };
                };
          }
        | {
            websocket:
              | string
              | {
                  route: string;
                  routeResponseSelectionExpression?: "$default";
                  authorizer?:
                    | AwsArnString
                    | FunctionName
                    | (
                        | {
                            [k: string]: unknown;
                          }
                        | {
                            [k: string]: unknown;
                          }
                      );
                };
          }
        | {
            sns:
              | string
              | AwsArnString
              | (
                  | {
                      [k: string]: unknown;
                    }
                  | {
                      [k: string]: unknown;
                    }
                );
          }
        | {
            stream:
              | AwsArnString
              | (
                  | {
                      arn: AwsCfFunction;
                      [k: string]: unknown;
                    }
                  | {
                      arn: AwsArnString;
                      [k: string]: unknown;
                    }
                );
          }
        | {
            kafka: {
              accessConfigurations: {
                vpcSubnet?: string[];
                vpcSecurityGroup?: string[];
                saslPlainAuth?: AwsSecretsManagerArnString[];
                saslScram256Auth?: AwsSecretsManagerArnString[];
                saslScram512Auth?: AwsSecretsManagerArnString[];
                clientCertificateTlsAuth?: AwsSecretsManagerArnString[];
                serverRootCaCertificate?: AwsSecretsManagerArnString[];
              };
              batchSize?: number;
              maximumBatchingWindow?: number;
              enabled?: boolean;
              bootstrapServers: string[];
              startingPosition?: "LATEST" | "TRIM_HORIZON" | "AT_TIMESTAMP";
              startingPositionTimestamp?: number;
              topic: string;
              consumerGroupId?: string;
            };
          }
        | {
            activemq: {
              arn: string | AwsCfImport | AwsCfRef;
              basicAuthArn: AwsSecretsManagerArnString | AwsCfImport | AwsCfRef;
              batchSize?: number;
              maximumBatchingWindow?: number;
              enabled?: boolean;
              queue: string;
            };
          }
        | {
            rabbitmq: {
              arn: string | AwsCfImport | AwsCfRef;
              basicAuthArn: AwsSecretsManagerArnString | AwsCfImport | AwsCfRef;
              batchSize?: number;
              maximumBatchingWindow?: number;
              enabled?: boolean;
              queue: string;
              virtualHost?: string;
            };
          }
        | {
            msk: {
              arn: AwsArnString | AwsCfImport | AwsCfRef;
              batchSize?: number;
              maximumBatchingWindow?: number;
              enabled?: boolean;
              startingPosition?: "LATEST" | "TRIM_HORIZON";
              topic: string;
              saslScram512?: AwsArnString;
              consumerGroupId?: string;
            };
          }
        | {
            alb: {
              authorizer?: string[];
              conditions: {
                header?: {
                  name: string;
                  values: string[];
                };
                host?: string[];
                ip?: (string | string)[];
                method?: string[];
                path?: string[];
                query?: {
                  [k: string]: string;
                };
              };
              healthCheck?:
                | boolean
                | {
                    healthyThresholdCount?: number;
                    intervalSeconds?: number;
                    matcher?: {
                      httpCode?: string;
                    };
                    path?: string;
                    timeoutSeconds?: number;
                    unhealthyThresholdCount?: number;
                  };
              listenerArn: AwsAlbListenerArn | AwsCfRef;
              multiValueHeaders?: boolean;
              priority: number;
              targetGroupName?: string;
            };
          }
        | {
            alexaSkill:
              | AwsAlexaEventToken
              | {
                  appId: AwsAlexaEventToken;
                  enabled?: boolean;
                };
          }
        | {
            alexaSmartHome:
              | AwsAlexaEventToken
              | {
                  appId: AwsAlexaEventToken;
                  enabled?: boolean;
                };
          }
        | {
            iot: {
              sql: string;
              sqlVersion?: "2015-10-08" | "2016-03-23" | "beta";
              name?: string;
              enabled?: boolean;
              description?: string;
            };
          }
        | {
            iotFleetProvisioning: {
              enabled?: boolean;
              provisioningRoleArn: AwsArn;
              templateBody: {
                [k: string]: unknown;
              };
              templateName?: string;
            };
          }
        | {
            cloudwatchEvent: {
              event?: {
                [k: string]: unknown;
              };
              input?:
                | string
                | {
                    [k: string]: unknown;
                  };
              inputPath?: string;
              inputTransformer?: {
                inputPathsMap?: {
                  [k: string]: string;
                };
                inputTemplate: string;
              };
              description?: string;
              name?: string;
              enabled?: boolean;
            };
          }
        | {
            cloudwatchLog:
              | AwsLogGroupName
              | {
                  logGroup: AwsLogGroupName;
                  filter?: string;
                };
          }
        | {
            cognitoUserPool: {
              pool: string;
              trigger:
                | "PreSignUp"
                | "PostConfirmation"
                | "PreAuthentication"
                | "PostAuthentication"
                | "PreTokenGeneration"
                | "CustomMessage"
                | "DefineAuthChallenge"
                | "CreateAuthChallenge"
                | "VerifyAuthChallengeResponse"
                | "UserMigration"
                | "CustomSMSSender"
                | "CustomEmailSender";
              existing?: boolean;
              forceDeploy?: boolean;
              kmsKeyId?: AwsKmsArn;
            };
          }
        | {
            eventBridge:
              | {
                  [k: string]: unknown;
                }
              | {
                  [k: string]: unknown;
                };
          }
        | {
            sqs:
              | AwsArnString
              | {
                  arn: AwsArn;
                  batchSize?: number;
                  enabled?: boolean;
                  maximumBatchingWindow?: number;
                  functionResponseType?: "ReportBatchItemFailures";
                  filterPatterns?: FilterPatterns;
                };
          }
        | {
            cloudFront: {
              behavior?: {
                AllowedMethods?:
                  | ("GET" | "HEAD")[]
                  | ("GET" | "HEAD" | "OPTIONS")[]
                  | ("GET" | "HEAD" | "OPTIONS" | "PUT" | "PATCH" | "POST" | "DELETE")[];
                CachedMethods?: ("GET" | "HEAD")[] | ("GET" | "HEAD" | "OPTIONS")[];
                CachePolicyId?: string;
                Compress?: boolean;
                FieldLevelEncryptionId?: string;
                OriginRequestPolicyId?: string;
                SmoothStreaming?: boolean;
                TrustedSigners?: string[];
                ViewerProtocolPolicy?: "allow-all" | "redirect-to-https" | "https-only";
                TrustedKeyGroups?: (string | AwsCfRef)[];
                MaxTTL?: number;
                MinTTL?: number;
                DefaultTTL?: number;
                ForwardedValues?: {
                  Cookies?:
                    | {
                        Forward: "all" | "none";
                      }
                    | {
                        Forward: "whitelist";
                        WhitelistedNames: string[];
                      };
                  Headers?: string[];
                  QueryString: boolean;
                  QueryStringCacheKeys?: string[];
                };
              };
              cachePolicy?:
                | {
                    [k: string]: unknown;
                  }
                | {
                    [k: string]: unknown;
                  };
              eventType?: "viewer-request" | "origin-request" | "origin-response" | "viewer-response";
              isDefaultOrigin?: boolean;
              includeBody?: boolean;
              origin?:
                | string
                | (
                    | {
                        [k: string]: unknown;
                      }
                    | {
                        [k: string]: unknown;
                      }
                  );
              pathPattern?: string;
            };
          }
        | {
            httpApi:
              | string
              | {
                  authorizer?:
                    | string
                    | (
                        | {
                            [k: string]: unknown;
                          }
                        | {
                            [k: string]: unknown;
                          }
                        | {
                            [k: string]: unknown;
                          }
                      );
                  method?: string;
                  path: string;
                };
          }
      )[];
}

But I'm not sure if the official definitions from Serverless Framework match those of the plugin: https://github.com/serverless-operations/serverless-step-functions#events

@zoiman
Copy link

zoiman commented Feb 12, 2023

thanks!
Yea that's what I did, and it works so far. However the schema part in the http event does not create a corresponding schema model when its used in a event for a stepfunction... not sure why

@zirkelc
Copy link
Author

zirkelc commented Feb 13, 2023

The events when specified on a normal Lambda function are being created by the core Serverless Framework. That means, all events on this list are supported out of the box.

However, the events on stepFunctions are a plugin specific implementation of serverless-step-functions. That means, not necessarily all events are supported and even if the the same events are supported, they might be implemented differently. I would suggest you go to serverless-step-funcrtions and open a new issue as feature request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment