Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Add Cloudinary module
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Nov 13, 2020
1 parent 278ddd5 commit 37c1eb8
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { StripeModule } from './modules/stripe/stripe.module';
import { UsersModule } from './modules/users/users.module';
import { WebhooksModule } from './modules/webhooks/webhooks.module';
import { AirtableModule } from './providers/airtable/airtable.module';
import { CloudinaryModule } from './providers/cloudinary/cloudinary.module';
import { DnsModule } from './providers/dns/dns.module';
import { ElasticSearchModule } from './providers/elasticsearch/elasticsearch.module';
import { GeolocationModule } from './providers/geolocation/geolocation.module';
Expand Down Expand Up @@ -70,6 +71,7 @@ import { TasksModule } from './providers/tasks/tasks.module';
SlackModule,
AirtableModule,
S3Module,
CloudinaryModule,
],
providers: [
{
Expand Down
6 changes: 6 additions & 0 deletions src/config/configuration.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,10 @@ export interface Configuration {
region: string;
bucket?: string;
};

cloudinary: {
cloudName: string;
apiKey: string;
apiSecret: string;
};
}
5 changes: 5 additions & 0 deletions src/config/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ const configuration: Configuration = {
region: process.env.S3_REGION ?? '',
bucket: process.env.S3_BUCKET,
},
cloudinary: {
cloudName: process.env.CLOUDINARY_CLOUD_NAME ?? '',
apiKey: process.env.CLOUDINARY_API_KEY ?? '',
apiSecret: process.env.CLOUDINARY_API_SECRET ?? '',
},
};

const configFunction: ConfigFactory<Configuration> = () => configuration;
Expand Down
10 changes: 10 additions & 0 deletions src/providers/cloudinary/cloudinary.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CloudinaryService } from './cloudinary.service';

@Module({
imports: [ConfigModule],
providers: [CloudinaryService],
exports: [CloudinaryService],
})
export class CloudinaryModule {}
64 changes: 64 additions & 0 deletions src/providers/cloudinary/cloudinary.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import cloudinary, { UploadApiResponse } from 'cloudinary';
import { Readable, Stream } from 'stream';
import { Configuration } from '../../config/configuration.interface';

/**
* MultiStream class helps convert buffers to a streams
* @source https://github.com/gagle/node-streamifier
*/
class MultiStream extends Readable {
_object: Buffer | string | undefined;
constructor(object: Buffer | string, options: any = {}) {
super();
this._object = object;
Stream.Readable.call(this, {
highWaterMark: options.highWaterMark,
encoding: options.encoding,
});
}
_read() {
this.push(this._object);
this._object = undefined;
}
}

/**
*
* @param object - Object to convert
* @param options - Configuration (encoding and highWaterMark)
*/
const createReadStream = (object: Buffer | string, options?: any) =>
new MultiStream(object, options);

@Injectable()
export class CloudinaryService {
private logger = new Logger(CloudinaryService.name);

constructor(private configService: ConfigService) {
const config = this.configService.get<Configuration['cloudinary']>(
'cloudinary',
);
if (config.cloudName)
cloudinary.v2.config({
cloud_name: config.cloudName,
api_key: config.apiKey,
api_secret: config.apiSecret,
});
else this.logger.warn('Cloudinary API key not found');
}

upload(buffer: Buffer | string, folder: string): Promise<UploadApiResponse> {
return new Promise((resolve, reject) => {
const uploadStream = cloudinary.v2.uploader.upload_stream(
{ folder },
(error, result) => {
if (result) return resolve(result);
reject(error);
},
);
createReadStream(buffer).pipe(uploadStream);
});
}
}

0 comments on commit 37c1eb8

Please sign in to comment.