Skip to content

Commit 95ec78b

Browse files
committed
WIP make putItem logic
1 parent df93399 commit 95ec78b

File tree

8 files changed

+260
-1274
lines changed

8 files changed

+260
-1274
lines changed

package-lock.json

Lines changed: 0 additions & 1265 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"dependencies": {
2525
"aws-sdk": "^2.50.0",
2626
"busboy": "^0.2.14",
27+
"dynamoose": "^0.7.0",
2728
"gm": "^1.23.0",
2829
"uuid": "^3.0.1"
2930
}

serverless.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ functions:
3232
method: post
3333
cors: true
3434

35-
Resources:
35+
resources:
36+
Resources:
3637
DynamoDbTable:
3738
Type: AWS::DynamoDB::Table
3839
Properties:
@@ -42,8 +43,6 @@ Resources:
4243
AttributeType: S
4344
- AttributeName: version
4445
AttributeType: S
45-
- AttributeName: downloadCount
46-
AttributeType: N
4746
KeySchema:
4847
- AttributeName: id
4948
KeyType: HASH
@@ -56,12 +55,14 @@ Resources:
5655
Type: AWS::IAM::Policy
5756
DependsOn: DynamoDbTable
5857
Properties:
59-
PolicyName: lambda-dynamodb
58+
PolicyName: AmazonDynamoDBFullAccess
6059
PolicyDocument:
6160
Version: '2012-10-17'
6261
Statement:
6362
- Effect: Allow
64-
Action: "dynamodb:*"
63+
Action: [
64+
"dynamodb:*"
65+
]
6566
Resource: "arn:aws:dynamodb:*:*:table/${file(./env/${opt:stage}.yml):DYNAMO_DB_TABLE_NAME}"
6667
Roles:
6768
- Ref: IamRoleLambdaExecution

src/db/model/imageMeta.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const dynamoose = require("dynamoose");
2+
3+
const Schema = dynamoose.Schema;
4+
5+
const imageMetaSchema = new Schema({
6+
id: {
7+
type: String,
8+
hashKey: true,
9+
},
10+
version: {
11+
type: String,
12+
rangeKey: true,
13+
},
14+
url: {
15+
type: String,
16+
},
17+
downloadCount: {
18+
type: Number,
19+
},
20+
});
21+
22+
const ImageMeta = dynamoose.model("lambda-image-manager-stats", imageMetaSchema);
23+
24+
export default ImageMeta;

src/handlers/getImage/index.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as GraphicMagick from "gm";
22
import setSize from "./setSize";
33
import S3Manager from "../../helpers/s3Manager";
4+
import ImageMeta from "../../db/model/imageMeta";
45
// interfaces
56
import FileNameMaker, { IImageProcessOptions } from "../../helpers/filenameMaker";
67

@@ -21,9 +22,9 @@ const handler: AWSLambda.ProxyHandler = async (event, context, _callback) => {
2122
imageProcessOptions.width = size.width;
2223
imageProcessOptions.height = size.height;
2324

24-
if (event.queryStringParameters["id"] && event.queryStringParameters["fileName"]) {
25+
if (event.queryStringParameters["id"] && event.queryStringParameters["filename"]) {
2526
const fileId = event.queryStringParameters["id"];
26-
const fileName = event.queryStringParameters["fileName"];
27+
const fileName = event.queryStringParameters["filename"];
2728

2829
let version = FileNameMaker.getVersion(imageProcessOptions);
2930
if (imageProcessOptions.width === 0 || imageProcessOptions.height === 0) {
@@ -70,6 +71,43 @@ const handler: AWSLambda.ProxyHandler = async (event, context, _callback) => {
7071

7172
await S3Manager.uploadFile(buffer, fileId, fileName, version);
7273
}
74+
75+
// Record download count to DynamoDB
76+
await new Promise((resolve, reject) => {
77+
ImageMeta.get({ id: fileId, version }, (err: Error, imageMeta: any) => {
78+
if (err) {
79+
console.log(err);
80+
reject(err);
81+
} else if (!imageMeta) {
82+
let url: string;
83+
if (version === "original") {
84+
url = `/id=${fileId}&filename=${fileName}`;
85+
} else {
86+
url = `/id=${fileId}&filename=${fileName}&width=${imageProcessOptions.width}&height=${imageProcessOptions.height}`;
87+
}
88+
const newImageMeta = new ImageMeta({
89+
id: fileId,
90+
version,
91+
url,
92+
downloadCount: 1,
93+
});
94+
newImageMeta.save((error: Error) => {
95+
if (error) {
96+
console.log(error);
97+
reject(error);
98+
} else {
99+
console.log("Succeeded to record result to DynamoDB");
100+
resolve();
101+
}
102+
});
103+
} else {
104+
// update count
105+
console.log(imageMeta);
106+
console.log(imageMeta.downloadCount);
107+
resolve();
108+
}
109+
});
110+
});
73111
}
74112
}
75113

src/handlers/uploadImage/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import S3Manager from "../../helpers/s3Manager";
22
import FilenameMaker from "../../helpers/filenameMaker";
33

44
const handler: AWSLambda.ProxyHandler = async (event, context, _callback) => {
5-
65
const buffer = new Buffer(event.body as string, "base64");
76
const fileSize = buffer.byteLength;
87

tslint.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
"no-console": false,
1111
"indent": ["spaces"],
1212
"no-var-requires": false,
13-
"ordered-imports": [false]
13+
"ordered-imports": [false],
14+
"max-line-length": [
15+
false
16+
]
1417
}
1518
}

typings/dynamoose.d.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Type definitions for dynamoose 0.7
2+
// Project: https://github.com/automategreen/dynamoose
3+
// Definitions by: Rahul Vaidya <https://github.com/rvaidya>
4+
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5+
6+
declare module "dynamoose" {
7+
import AWS from 'aws-sdk';
8+
9+
export class Dynamoose {
10+
constructor();
11+
Dynamoose(): void;
12+
Schema(obj: any, options: any): Schema;
13+
Table(name: string, schema: any, options: any, base: any): Table;
14+
VirtualType(options: any, name: string): VirtualType;
15+
ddb(): AWS.DynamoDB;
16+
local(url: string): void;
17+
model(name: string, schema: Schema, options?: ModelOptions): Model;
18+
setDefaults(options: Options): void;
19+
}
20+
export class Schema {
21+
constructor(obj: SchemaObject, options?: SchemaOptions);
22+
method(name: string, fn: any): any;
23+
parseDynamo(model: any, dynamoObj: any): any;
24+
static(name: string, fn: any): any;
25+
toDynamo(model: any): any;
26+
virtual(name: string, options: any): any;
27+
virtualpath(name: string): any;
28+
}
29+
export class Table {
30+
constructor(name: string, schema: any, options: any, base: any);
31+
create(next: any): any;
32+
createIndex(attributes: any, indexSpec: any): any;
33+
delete(next: any): any;
34+
deleteIndex(indexname: string): any;
35+
describe(next: any): any;
36+
init(next: any): any;
37+
update(next: any): any;
38+
waitForActive(timeout: any, next: any): any;
39+
}
40+
export class Model {
41+
constructor(obj: ModelObject);
42+
put(options, callback: (err, obj) => void);
43+
save(options, callback: (err, obj) => void);
44+
delete(callback: (err) => void);
45+
delete(key, options, callback: (err) => void);
46+
get<T>(key, options?, callback?: (err, obj) => void): Promise<T>;
47+
batchPut(items: ModelObject[], options, callback: (err, obj) => void);
48+
create<T>(obj: T, callback: (err, obj: T) => void);
49+
create<T>(obj: T, options, callback: (err, obj: T) => void);
50+
batchGet<T>(keys, options?, callback?: (err, obj) => void): Promise<T[]>;
51+
batchDelete(keys, options, callback: (err) => void);
52+
query<T>(query, options, callback: (err, results: T[]) => void): void;
53+
query<T>(query, callback: (err, results: T[]) => void): void;
54+
query<T>(key: string): Query<T>;
55+
queryOne<T>(query, options, callback: (err, results: T[]) => void): void;
56+
queryOne<T>(query, callback: (err, results: T[]) => void): void;
57+
queryOne<T>(key: string): Query<T>;
58+
scan<T>(filter, options, callback: (err, results: T[]) => void): void;
59+
scan<T>(filter, callback: (err, results: T[]) => void): void;
60+
scan<T>(filter: string): Scan<T>;
61+
update(key, update, options, callback: (err) => void);
62+
}
63+
export class VirtualType {
64+
constructor(options: any, name: string);
65+
applyVirtuals(model: any): void;
66+
get(fn: any): any;
67+
set(fn: any): any;
68+
}
69+
70+
export function ddb(): AWS.DynamoDB;
71+
export function local(url: string): void;
72+
export function model(name: string, schema: Schema, options?: ModelOptions): Model;
73+
export function setDefaults(options: Options): void;
74+
export import AWS = AWS;
75+
76+
export default {
77+
ddb: ddb,
78+
local: local,
79+
model: model,
80+
setDefaults: setDefaults,
81+
AWS: AWS,
82+
Schema: Schema
83+
};
84+
85+
// Global options
86+
export interface Options {
87+
create?: boolean;
88+
prefix?: string;
89+
waitForActive?: boolean;
90+
waitForActiveTimeout?: number;
91+
}
92+
93+
// tslint:disable-next-line:forbidden-types THIS IS INTENTIONAL, THESE ARE ARGUMENTS FOR THE LIBRARY
94+
type ST = String | Number | Boolean | Date | Object;
95+
type TT = ST | ST[] | Buffer;
96+
export interface ModelObject {
97+
[key: string]: TT;
98+
}
99+
export interface SchemaObject {
100+
[key: string]: {
101+
type: TT;
102+
hashKey?: boolean;
103+
rangeKey?: boolean;
104+
required?: boolean;
105+
index?: boolean | {
106+
name: string,
107+
global?: boolean
108+
rangeKey?: string
109+
project?: boolean | string[],
110+
throughput?: number | { read?: number, write?: number };
111+
};
112+
default?: () => TT | TT;
113+
validate?: (value: TT) => boolean | RegExp | TT;
114+
set?: (value: TT) => void;
115+
get?: () => TT;
116+
trim?: boolean;
117+
lowercase?: boolean;
118+
uppercase?: boolean;
119+
};
120+
}
121+
122+
// Schema options
123+
export interface SchemaOptions {
124+
throughput?: number | { read?: number, write?: number };
125+
timestamps?: boolean | { createdAt?: string, updatedAt?: string };
126+
}
127+
128+
// Model options
129+
export interface ModelOptions {
130+
overwrite?: boolean;
131+
condition?: string;
132+
conditionNames: any;
133+
conditionValues: any;
134+
}
135+
136+
export class Query<T> {
137+
exec(callback: (err, objs: T[]) => void): void;
138+
exec(): Promise<T[]>;
139+
where(rangeKey: string): Query<T>;
140+
filter(filter: string): Query<T>;
141+
and(): Query<T>;
142+
or(): Query<T>;
143+
not(): Query<T>;
144+
null(): Query<T>;
145+
eq(value: string): Query<T>;
146+
lt(value): Query<T>;
147+
le(value): Query<T>;
148+
ge(value): Query<T>;
149+
gt(value): Query<T>;
150+
beginsWith(value): Query<T>;
151+
between(valueA, valueB): Query<T>;
152+
contains(value): Query<T>;
153+
beginsWith(value): Query<T>;
154+
in(values): Query<T>;
155+
limit(limit: number): Query<T>;
156+
consistent(): Query<T>;
157+
descending(): Query<T>;
158+
ascending(): Query<T>;
159+
startAt(key): Query<T>;
160+
attributes(attributes): Query<T>;
161+
}
162+
163+
export class Scan<T> {
164+
exec(callback: (err, objs: T[]) => void): void;
165+
exec(): Promise<T[]>;
166+
where(rangeKey: string): Scan<T>;
167+
filter(filter: string): Scan<T>;
168+
and(): Scan<T>;
169+
not(): Scan<T>;
170+
null(): Scan<T>;
171+
eq(value: string): Scan<T>;
172+
lt(value): Scan<T>;
173+
le(value): Scan<T>;
174+
ge(value): Scan<T>;
175+
gt(value): Scan<T>;
176+
beginsWith(value): Scan<T>;
177+
between(valueA, valueB): Scan<T>;
178+
contains(value): Scan<T>;
179+
beginsWith(value): Scan<T>;
180+
in(values): Scan<T>;
181+
limit(limit: number): Scan<T>;
182+
startAt(key): Scan<T>;
183+
attributes(attributes): Scan<T>;
184+
}
185+
}

0 commit comments

Comments
 (0)