Metadata-Version: 2.1
Name: crow-api.core
Version: 2.1.0
Summary: AWS CDK Construct to create a serverless API based on file structure.
Home-page: https://github.com/thomasstep/crow-api
Author: Thomas Step<thomas@thomasstep.com>
License: Apache-2.0
Project-URL: Source, https://github.com/thomasstep/crow-api.git
Platform: UNKNOWN
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: JavaScript
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Typing :: Typed
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE

# Crow API

Crow API lets you build an API intuitively based on the file structure of a project. Provide API Gateway and Lambda function configurations and crow will build out the appropriate paths and methods to the API Gateway. All created resources are available after initialization. `lambdaFunctions` will expose all Lambda functions created for further operations like adding environment variables and providing permissions.

| `crow-api` version | `aws-cdk` version | Notes                   |
| ------------------ | ----------------- | ----------------------- |
| 0                  | 1                 |                         |
| 1                  | 2                 | Not recommended for use |
| 2                  | 2                 |                         |

Contents:

1. [Getting Started](#gettingstarted)

## Getting Started

[Start your application as a normal CDK app](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html)

```sh
npm install -g aws-cdk
cdk bootstrap # If this is your first cdk app, you will need to bootstrap your AWS account
cdk init app --language typescript
```

Next, install the Crow API package

```sh
npm install --save crow-api
```

In the `lib/` folder generated by the `cdk`, there should be a single file named `<your-app>-stack.js`. Create your Crow API construct inside of that file like so

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import Stack, StackProps
from constructs import Construct
from crow_api import CrowApi, ICrowApiProps

class YourAppStack(Stack):
    def __init__(self, scope, id, props):
        super().__init__(scope, id, props)

        {
              crowApiProps,
            } = props

        api = CrowApi(self, "api", {
            (SpreadAssignment ...crowApiProps
              crow_api_props)
        })
```

Your API will start to take shape as you create folders to define paths and methods (see Example File Structure below). To deploy your API, simply run `cdk synth` and `cdk deploy`. Follow the instructions as they are prompted, and you will end up receiving a URL where your API now lives.

## Example File Structure

```
|-- src/
    |-- authorizer/
        |-- index.js
    |-- v1/
        |-- book/
            |-- get/
                |-- index.js
            |-- post/
                |-- index.js
        |-- chapters/
            |-- get/
                |-- index.js
        |-- authors/
            |-- get/
                |-- index.js
            |-- post/
                |-- index.js
```

The preceding file structure will create an API with the following routes:

* GET /v1/book
* POST /v1/book
* GET /v1/book/chapters
* GET /v1/authors
* POST /v1/authors

There needs to be an `index.js` file inside of a folder named after an HTTP method in order for a path to be created. The `index.js` file needs to export a `handler` method that will process the payload and return like the following.

```javascript
exports.handler = async function (event, context, callback) {
  try {
    const data = {
      statusCode: 201,
    };
    return data;
  } catch (uncaughtError) {
    console.error(uncaughtError);
    throw uncaughtError;
  }
}
```

## Crow API Props

Crow API takes in a few props to help you customize away from defaults.

#### `sourceDirectory`

By default, Crow walks through the `src` directory in the root of the repository to determine routes and methods, but you can change the top level directory by passing in the `sourceDirectory` prop. The string passed in should not start with or end with a slash (`/`). For example, `src`, `api/src`, or `source` are all valid options to pass in through that prop.

#### `sharedDirectory`

By default, Crow creates a Lambda layer out of the `shared` directory in the source directory of the repository, but you can change the name of the shared directory by passing in the `sharedDirectory` prop. The string passed in should not start with or end with a slash (`/`) and must be a direct child of the source directory. For example, `common` or `utils` are valid but `shared/utils` is not.

The Lambda layer created will be prepended to any the of the layers passed in through `lambdaConfigurations` and added to all Lambda functions created.

#### `useAuthorizerLambda`

Crow will create and attach an authorizer Lambda to specific methods if requested. The `useAuthorizerLambda` prop tells the `CrowApi` Construct that it should create an authorizer Lambda and accepts a boolean value. This is `false` by default.

#### `authorizerDirectory`

Crow will allow for a Lambda authorizer to be created and used by specific methods if requested. The `authorizerDirectory` prop tells Crow where to find the code for the Lambda authorizer **within the source directory which can be specified in the `sourceDirectory` prop**. It expects to find an `index.js` file that exports a `handler` function within the `authorizerDirectory`.

By default, Crow expects to find a directory called `src/authorizer` containing the authorizer Lambda source if the `useAuthorizerLambda` prop is `true`. If a different directory within the source directory should be looked at for this code, it should be specified by passing in a string to the `authorizerDirectory` prop. The string passed in should not start with nor end with a slash (`/`). For example, `auth` or `authLambdaSrc` are valid.

#### `authorizerLambdaConfiguration`

The `authorizerLambdaConfiguration` prop is passed directly to the Lambda functions which will be in charge of your API's authorization. The configuration allowed is exactly the same as the [Lambda Function props](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html).

#### `tokenAuthorizerConfiguration`

The `tokenAuthorizerConfiguration` prop is passed directly to the `APIGateway.TokenAuthorizer` construct which will be in charge of your API's authorization. Anything available in the [class constructor for the `TokenAuthorizer`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.TokenAuthorizer.html) can be overridden.

**Note:**

Be careful with this configuration item as all configuration here takes precedence over Crow defaults. I suggest not using this configuration item unless you are experienced with the AWS CDK, API Gateway, and Lambda.

#### `createApiKey`

By default, Crow does not create an API key associated with the API. If an API key is desired, pass in the `createApiKey` prop as `true`.

#### `logRetention`

By default, Crow creates log groups for resources it creates and sets the log retention to one week. If a different retention is desired pass in the `logRetention` prop of [enum type `RetentionDays`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-logs.RetentionDays.html).

#### `apiGatewayName`

This is a simple prop that names the API Gateway. This is how the API will be identified in the AWS console. The value should be a string without spaces and defaults to `crow-api`.

#### `apiGatewayConfiguration`

This props allows for more complex overrides to the API Gateway that fronts your API. The configuration allowed is exactly the same as the [LambdaRestApi props](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.LambdaRestApi.html).

**Note:**

Be careful with this configuration item as all configuration here takes precedence over Crow defaults. I suggest not using this configuration item unless you are experienced with the AWS CDK and API Gateway.

An example of this prop might look like the following:

```python
# Example automatically generated from non-compiling source. May contain errors.
from source_map_support.register import
import aws_cdk as cdk
import aws_cdk.aws_apigateway as apigateway
from ...lib.crow_api_stack import CrowApiStack

dev_environment = {
    "account": "123456789012",
    "region": "us-east-1"
}

app = cdk.App()

CrowApiStack(app, "CrowApiStack",
    env=dev_environment,
    api_gateway_configuration={
        "endpoint_configuration": {
            "types": [apigateway.EndpointType.REGIONAL]
        }
    }
)
```

#### `lambdaConfigurations`

This props allows for more complex overrides to Lambda functions. The prop is an object with keys corresponding to the API path of a Lambda function and a value corresponding to the configuration that should be applied to the Lambda. The configuration allowed is exactly the same as the [Lambda Function props](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html).

**Note:**

Be careful with this configuration item as all configuration here takes precedence over Crow defaults. I suggest not using this configuration item unless you are experienced with the AWS CDK and Lambda.

An example of this prop might look like the following:

```python
# Example automatically generated from non-compiling source. May contain errors.
from source_map_support.register import
import aws_cdk as cdk
from ...lib.crow_api_stack import CrowApiStack

dev_environment = {
    "account": "123456789012",
    "region": "us-east-1"
}

app = cdk.App()

CrowApiStack(app, "CrowApiStack",
    env=dev_environment,
    lambda_configurations={
        "/v1/book/get": {
            "timeout": cdk.Duration.seconds(5)
        }
    }
)
```

#### `methodConfigurations`

This props allows for more complex overrides to individual methods. The prop is an object with keys corresponding to the API path of a method and a value corresponding to the configuration that should be applied to the method as well as the key `useAuthorizerLambda` which will invoke the authorizer Lambda whenever the method is called. The configuration allowed is exactly the same as [`MethodOptions`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.MethodOptions.html) plus the `useAuthorizerLambda` boolean.

**Note:**

If `createApiKey` is `true`, then the `apiKeyRequired` parameter will need to be set for the methods needing the API key.

An example of this prop might look like the following:

```python
# Example automatically generated from non-compiling source. May contain errors.
from source_map_support.register import
import aws_cdk as cdk
from ...lib.crow_api_stack import CrowApiStack

dev_environment = {
    "account": "123456789012",
    "region": "us-east-1"
}

app = cdk.App()

CrowApiStack(app, "CrowApiStack",
    env=dev_environment,
    method_configurations={
        "/v1/book/get": {
            "use_authorizer_lambda": True
        },
        "/v1/book/post": {
            "api_key_required": True
        }
    }
)
```

## Properties

A `CrowApi` construct will give full access to all of the resources it created.

#### `authorizerLambda`

This is the `lambda.Function` that authorizes API Gateway requests.

#### `gateway`

This is the `apigateway.RestApi` that all of the created Lambda functions sit behind.

#### `lambdaLayer`

If the `sharedDirectory` is populated, this is the `lambda.LayerVersion` created for that code. If the `sharedDirectory` is not populated, then this is `undefined`.

#### `lambdaFunctions`

This is an object with keys being the API paths and the values being the `lambda.Function`s sitting being them. Continuing off of the example file structure from above, the following would be an example of referencing `GET` `/v1/book/chapters`.

```python
# Example automatically generated from non-compiling source. May contain errors.
from aws_cdk import Stack, StackProps
from constructs import Construct
from crow_api import CrowApi, ICrowApiProps

class YourAppStack(Stack):
    def __init__(self, scope, id, props):
        super().__init__(scope, id, props)

        {
              crowApiProps,
            } = props

        api = CrowApi(self, "api", {
            (SpreadAssignment ...crowApiProps
              crow_api_props)
        })

        lambda_ = api.lambda_functions["/v1/book/chapters/get"]
        lambda_.add_environment("FOO", "bar")
```


