Skip to content

Commit

Permalink
Merge pull request #22 from joshua-williams/feat/create-table-if-not-…
Browse files Browse the repository at this point in the history
…exists

feat(table): create table if not exists
  • Loading branch information
joshua-williams authored Mar 22, 2024
2 parents 2500de9 + b9af58c commit c08a6f7
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 28 deletions.
67 changes: 44 additions & 23 deletions __tests__/table.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import db from "./fixtures/db";
import {Table} from "../index";
import {CookbookTable} from "./fixtures/tables";
import {DynamoDBClient} from "@aws-sdk/client-dynamodb";
import {attribute, Entity, Table, table as TableDecorator} from "../index";
import { CookbookTable } from "./fixtures/tables";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

describe('table', () => {
const config = {endpoint: 'http://localhost:8000'};
Expand Down Expand Up @@ -34,28 +34,49 @@ describe('table', () => {
})
})


it('should output CreateCommandInput', () => {
const expectedCommandInput = {
TableName: 'Cookbooks',
AttributeDefinitions: [
{ AttributeName: 'title', AttributeType: 'S' },
{ AttributeName: 'author', AttributeType: 'S' }
],
KeySchema: [
{ AttributeName: 'title', KeyType: 'HASH' },
{ AttributeName: 'author', KeyType: 'RANGE' }
],
ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }
describe('Create Table', () => {
class TestEntity extends Entity {
@attribute()
pk: string;
@attribute()
sk: string;
}
const createCommandInput = table.toCreateCommandInput();
expect(createCommandInput).toMatchObject(expectedCommandInput)
})

it('should create database table', async () => {
table = new CookbookTable(client);
const result = await table.create();
expect(result).toHaveProperty('TableDescription');
@TableDecorator({
name: 'TestTable',
primaryKey: {pk: 'pk', sk: 'sk'},
entity: TestEntity
})
class TestTable extends Table {}

it('should output CreateCommandInput', () => {
const expectedCommandInput = {
TableName: 'Cookbooks',
AttributeDefinitions: [
{ AttributeName: 'title', AttributeType: 'S' },
{ AttributeName: 'author', AttributeType: 'S' }
],
KeySchema: [
{ AttributeName: 'title', KeyType: 'HASH' },
{ AttributeName: 'author', KeyType: 'RANGE' }
],
ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 }
}
const createCommandInput = table.toCreateCommandInput();
expect(createCommandInput).toMatchObject(expectedCommandInput)
})

it('should create database table', async () => {
table = new CookbookTable(client);
const result = await table.create();
expect(result).toHaveProperty('TableDescription');
})

it('should create database table if not exists', async () => {
table = new TestTable(client);
const result = await table.create('IF_NOT_EXISTS');
expect(result).toHaveProperty('TableDescription');
})
})

it('should getPrimaryKeyDefinition', () => {
Expand Down
1 change: 1 addition & 0 deletions src/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Entity {
public getAttributeDefinitions(): AttributeDefinitions {
const properties = Reflect.ownKeys(this);
const attributes = Reflect.getMetadata('attributes', this);
if (!attributes) return;
const reducer = (attributeDefinitions, name) => {
if (!attributes.hasOwnProperty(name)) return attributeDefinitions;
const { type, required } = attributes[name];
Expand Down
11 changes: 9 additions & 2 deletions src/table.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {EntityConstructor, PrimaryKey, PrimaryKeyDefinition} from "./types";
import {CreateTableOption, EntityConstructor, PrimaryKey, PrimaryKeyDefinition} from "./types";
import {
CreateTableCommand,
CreateTableCommandInput, CreateTableCommandOutput, DescribeTableCommand, DescribeTableCommandOutput,
Expand Down Expand Up @@ -147,7 +147,14 @@ export default class Table {
return Key;
}

public async create() {
public async createIfNotExists() {

}
public async create(option?: CreateTableOption) {
if (option) {
const tableDescription = await this.describe();
if (option === 'IF_NOT_EXISTS' && tableDescription) return;
}
const commandInput = this.toCreateCommandInput();
const command = new CreateTableCommand(commandInput);
let message = `Failed to save table ${this.constructor.name}`;
Expand Down
8 changes: 5 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import QueryBuilder from './query';

export type EntityConstructor = {
name: string,
new(): Entity
new(): Entity,
}

export type Entities = Record<string, EntityConstructor>
Expand Down Expand Up @@ -64,11 +64,13 @@ export type TableConstructor = {

export type TableOptions = {
name: string,
primaryKey: PrimaryKey
primaryKey: PrimaryKey,
entity: EntityConstructor,
autoCreate?: boolean,
entity: any
}

export type CreateTableOption = 'IF_NOT_EXISTS' | 'DROP_IF_EXISTS';

export type ModelConstructor = {
new(client: DynamoDBClient): Model,
}
Expand Down

0 comments on commit c08a6f7

Please sign in to comment.