Skip to content

Commit

Permalink
address PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinsgoodman committed Jan 15, 2023
1 parent b33cd7b commit 5012a6a
Show file tree
Hide file tree
Showing 14 changed files with 30 additions and 20 deletions.
2 changes: 2 additions & 0 deletions starters/serverless-framework-sqs-dynamodb/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
IS_OFFLINE=true
# connection info for Redis used for caching
REDIS_CACHE_URL=redis://:sOmE_sEcUrE_pAsS@localhost:6379
# how long should items last in the cache by default
DEFAULT_CACHE_TIME=300000
10 changes: 6 additions & 4 deletions starters/serverless-framework-sqs-dynamodb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ git clone https://github.com/thisdot/starter.dev.git

This README uses `npm` for commands. If you're using `yarn` or `pnpm`, utilize the equivalent version of the commands.

1. Create a `.env` file:
1. Create a `.env` file. This is to support any variable in the Serverless Configuration being read from `env:` and test running:

```bash
cp .env.example .env
Expand Down Expand Up @@ -92,11 +92,11 @@ npm start

### General Commands

- `build` bundles the project using the serverless packaging serverless. The produced artifacts will ship bundles shipped to AWS on deployment. You can optionally pass `--analyze <function name>` to run the bundle analyzer and visualize the results to understand your handler bundles.
- `build` bundles the project using the Serverless Framework's out of the box `package` command. The produced artifacts will be shipped to AWS on deployment. You can optionally pass `--analyze <function name>` to run the bundle analyzer and visualize the results to understand your handler bundles.
- `deploy` ships the project to the configured AWS account using the Serverless Framework CLI command.
- `start` runs the `serverless-offline` provided server for local development and testing. Be sure to have the local docker infrastructure running to emulate the related services.
- `test` runs `jest` under the hood.
- `lint` runs `eslint` under the hood. You can use all the eslint available command line arguments. To lint the entire project, run `npm run lint .`, or equivalent. You can affix `--fix` to auto-correct linting issues that eslint can handle.
- `lint` runs `eslint` under the hood. You can use all the available eslint command line arguments. To lint the entire project, run `npm run lint .`, or equivalent. You can affix `--fix` to auto-correct linting issues that eslint can handle.
- `format:check` runs prettier format checking on all project files.
- `format:write` runs prettier format writing on all project files.

Expand Down Expand Up @@ -141,7 +141,7 @@ This starter kit ships with a set of RESTful APIs. All routes are served via `ht

## Serverless Configuration

This kit uses the TypeScript option for configuration. It is type checked using the `@serverless/typescript` definitions over the DefinitelyTyped definitions because DefinitelyTyped is currently behind on its definition. However, the `@serverless/typescript` types have known issues with certain fields are noted directly in the configuration.
This kit uses the TypeScript option for configuration. It is type checked using the `@serverless/typescript` definitions over the DefinitelyTyped definitions because DefinitelyTyped is currently behind on its definition. However, the `@serverless/typescript` types have known issues with certain fields, which are noted directly in the configuration.

It is not compatible with the automated CI/CD of the Serverless Dashboard as they only support the default YAML format. You can read more about [setting up CI/CD using GitHub for this project on the This Dot blog](https://www.thisdot.co/blog/github-actions-for-serverless-framework-deployments).

Expand Down Expand Up @@ -227,6 +227,8 @@ There is an existing [DynamoDB Local preset for Jest](https://github.com/shelfio

## Deployment

<!-- TODO: add note about AWS setup -->

As a serverless implementation, most of the infrastructure will be deployed and configured correctly simply utilizing the `deploy` script provided by this kit which is just an alias for [`serverless deploy`](https://www.serverless.com/framework/docs/providers/aws/cli-reference/deploy). However, the Redis instance is not configurable via the Serverless Configuration and will need to be set up ahead of your first deploy and configured via environment variables. We recommend using [Serverless Framework's interface for AWS Secret Manager](https://www.serverless.com/blog/aws-secrets-management/) for security purposes.

This entire stack can be deployed via CI tools such as GitHub Actions, CircleCI, etc. and is our recommended approach as this kit is incompatible with the Serverless Dashboard. The Serverless Dashboard CI only works with the configuration in the YAML format which we do not use to give developers type-safety in the config file.
3 changes: 2 additions & 1 deletion starters/serverless-framework-sqs-dynamodb/serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ const serverlessConfiguration: AWS = {
environment: {
REGION: '${aws:region}',
SLS_STAGE: '${sls:stage}',
// DynamoDB Tables
DEFAULT_CACHE_TIME: '${env:DEFAULT_CACHE_TIME}',
REDIS_CACHE_URL: '${env:REDIS_CACHE_URL}',
// DynamoDB Tables
TECHNOLOGIES_TABLE: '${param:technologiesTable}',
},
iam: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('demo', () => {
let logMock: jest.SpyInstance;

beforeAll(async () => {
logMock = jest.spyOn(console, 'log').mockImplementation(() => ({}));
logMock = jest.spyOn(console, 'log').mockImplementation(() => {});
subject = await handler(
{
Records: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ describe('demo', () => {
let logMock: jest.SpyInstance;

beforeAll(async () => {
logMock = jest.spyOn(console, 'log').mockImplementation(() => ({}));
logMock = jest.spyOn(console, 'log').mockImplementation(() => {});
subject = await handler(
{
Records: [
{
eventName: 'UNKNOWN',
},
{
eventName: 'INSERT',
dynamodb: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { DynamoDBStreamHandler, DynamoDBRecord } from 'aws-lambda';

const recordHandler = async (record: DynamoDBRecord) => {
if (record.eventName === 'INSERT' && record.dynamodb) {
if (!record.dynamodb) {
return;
}

if (record.eventName === 'INSERT') {
console.log('Inserted Record', record.dynamodb.NewImage);
} else if (record.eventName === 'MODIFY' && record.dynamodb) {
} else if (record.eventName === 'MODIFY') {
console.log('Updated Record');
console.log('New Values', record.dynamodb.NewImage);
console.log('Old Values', record.dynamodb.OldImage);
} else if (record.eventName === 'REMOVE' && record.dynamodb) {
} else if (record.eventName === 'REMOVE') {
console.log('Removed Record', record.dynamodb.OldImage);
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { APIGatewayProxyHandler } from 'aws-lambda';
import { StatusCodes } from 'http-status-codes';
import { sendMessage } from '@/utils/sqs/sendMessage';

export const handler: APIGatewayProxyHandler = async () => {
Expand All @@ -8,7 +9,7 @@ export const handler: APIGatewayProxyHandler = async () => {
});

return {
statusCode: resp.success ? 201 : 400,
statusCode: resp.success ? StatusCodes.CREATED : StatusCodes.BAD_REQUEST,
body: JSON.stringify(resp.data),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import type { APIGatewayProxyResult, APIGatewayProxyEvent, Context, Callback } f
import { PutItemCommand, ServiceInputTypes, ServiceOutputTypes } from '@aws-sdk/client-dynamodb';
import { AwsStub, mockClient } from 'aws-sdk-client-mock';
import { getClient } from '@/utils/dynamodb/getClient';
import { removeFromCache } from '@/utils/cache/removeFromCache';
import * as technologyCreate from '@/models/technology/create';
import { getCacheKey } from '@/models/technology/getCacheKey';
import { handler } from './technology_create';

describe('POST /technology', () => {
Expand Down Expand Up @@ -33,7 +31,6 @@ describe('POST /technology', () => {

afterAll(async () => {
ddbMock.restore();
await removeFromCache(getCacheKey('87af19b1-aa0d-4178-a30c-2fa8cd1f2cff'));
});

it('returns 201 status', () => {
Expand Down Expand Up @@ -63,7 +60,6 @@ describe('POST /technology', () => {

afterAll(async () => {
jest.restoreAllMocks();
await removeFromCache(getCacheKey('87af19b1-aa0d-4178-a30c-2fa8cd1f2cff'));
});

it('returns 400 status', () => {
Expand Down Expand Up @@ -97,7 +93,6 @@ describe('POST /technology', () => {

afterAll(async () => {
jest.restoreAllMocks();
await removeFromCache(getCacheKey('87af19b1-aa0d-4178-a30c-2fa8cd1f2cff'));
});

it('returns 500 status', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { scan } from '@/utils/dynamodb/scan';

export const getAll = async () => {
const items = await scan(process.env.TECHNOLOGIES_TABLE);
return items;
return await scan(process.env.TECHNOLOGIES_TABLE);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare global {
REGION: string;
SLS_STAGE: string;

DEFAULT_CACHE_TIME: string;
REDIS_CACHE_URL: string;
TECHNOLOGIES_TABLE: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const DEFAULT_CACHE_TIME = 300_000; // 5 minutes = 1000 ms/s * 60 s/min * 5 min
export const DEFAULT_CACHE_TIME = parseInt(process.env.DEFAULT_CACHE_TIME, 10);
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('dynamodb.deleteItem()', () => {

describe('when item does not exist', () => {
beforeAll(async () => {
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
ddbMock.on(DeleteItemCommand).resolves({
Attributes: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const deleteItem = async (tableName: string, key: Record<string, unknown>
const response = await client.send(command);

if (!response || !response.Attributes) {
console.warn('dynamodb.deleteItem Warning - ${response}');
return null;
}
return unmarshall(response.Attributes);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Utility function for checking where functions are being run locally via serverless offline
* Utility function for checking if functions are being run locally via serverless offline
* or if they're running on infrastructure. Helpful for detecting which connection string to use.
*
* @returns boolean are we running locally or on infra?
Expand Down

0 comments on commit 5012a6a

Please sign in to comment.