New things for GCS Adapter

This commit is contained in:
Mike McDonald
2016-03-07 00:30:21 -08:00
parent 84635352e3
commit ce35b81cc6
5 changed files with 50 additions and 35 deletions

View File

@@ -1,35 +1,34 @@
var FilesController = require('../src/Controllers/FilesController').FilesController; var FilesController = require('../src/Controllers/FilesController').FilesController;
var Config = require("../src/Config"); var Config = require("../src/Config");
var testAdapter = function(name, adapter) { var testAdapter = function(name, adapter) {
// Small additional tests to improve overall coverage // Small additional tests to improve overall coverage
var config = new Config(Parse.applicationId); var config = new Config(Parse.applicationId);
var filesController = new FilesController(adapter); var filesController = new FilesController(adapter);
describe("FilesController with "+name,()=>{ describe("FilesController with "+name,()=>{
it("should properly expand objects", (done) => { it("should properly expand objects", (done) => {
var result = filesController.expandFilesInObject(config, function(){}); var result = filesController.expandFilesInObject(config, function(){});
expect(result).toBeUndefined(); expect(result).toBeUndefined();
var fullFile = { var fullFile = {
type: '__type', type: '__type',
url: "http://an.url" url: "http://an.url"
} }
var anObject = { var anObject = {
aFile: fullFile aFile: fullFile
} }
filesController.expandFilesInObject(config, anObject); filesController.expandFilesInObject(config, anObject);
expect(anObject.aFile.url).toEqual("http://an.url"); expect(anObject.aFile.url).toEqual("http://an.url");
done(); done();
}) })
it("should properly create, read, delete files", (done) => { it("should properly create, read, delete files", (done) => {
var filename; var filename;
filesController.createFile(config, "file.txt", "hello world").then( (result) => { filesController.createFile(config, "file.txt", "hello world").then( (result) => {
@@ -51,14 +50,14 @@ var testAdapter = function(name, adapter) {
console.error(err); console.error(err);
done(); done();
}).then((result) => { }).then((result) => {
filesController.getFileData(config, filename).then((res) => { filesController.getFileData(config, filename).then((res) => {
fail("the file should be deleted"); fail("the file should be deleted");
done(); done();
}, (err) => { }, (err) => {
done(); done();
}); });
}, (err) => { }, (err) => {
fail("The adapter should delete the file"); fail("The adapter should delete the file");
console.error(err); console.error(err);

View File

@@ -1,6 +1,5 @@
export function loadAdapter(adapter, defaultAdapter, options) { export function loadAdapter(adapter, defaultAdapter, options) {
if (!adapter)
if (!adapter)
{ {
if (!defaultAdapter) { if (!defaultAdapter) {
return options; return options;
@@ -20,7 +19,7 @@ export function loadAdapter(adapter, defaultAdapter, options) {
if (adapter.default) { if (adapter.default) {
adapter = adapter.default; adapter = adapter.default;
} }
return loadAdapter(adapter, undefined, options); return loadAdapter(adapter, undefined, options);
} else if (adapter.module) { } else if (adapter.module) {
return loadAdapter(adapter.module, undefined, adapter.options); return loadAdapter(adapter.module, undefined, adapter.options);
@@ -30,7 +29,7 @@ export function loadAdapter(adapter, defaultAdapter, options) {
return loadAdapter(adapter.adapter, undefined, adapter.options); return loadAdapter(adapter.adapter, undefined, adapter.options);
} }
// return the adapter as provided // return the adapter as provided
return adapter; return adapter;
} }
export default loadAdapter; export default loadAdapter;

View File

@@ -4,18 +4,33 @@ import { storage } from 'gcloud';
import { FilesAdapter } from './FilesAdapter'; import { FilesAdapter } from './FilesAdapter';
import requiredParameter from '../../requiredParameter'; import requiredParameter from '../../requiredParameter';
function requiredOrFromEnvironment(env, name) {
let environmentVariable = process.env[env];
if (!environmentVariable) {
requiredParameter(`GCSAdapter requires an ${name}`);
}
return environmentVariable;
}
function fromEnvironmentOrDefault(env, defaultValue) {
let environmentVariable = process.env[env];
if (environmentVariable) {
return environmentVariable;
}
return defaultValue;
}
export class GCSAdapter extends FilesAdapter { export class GCSAdapter extends FilesAdapter {
// GCS Project ID and the name of a corresponding Keyfile are required. // GCS Project ID and the name of a corresponding Keyfile are required.
// Unlike the S3 adapter, you must create a new Cloud Storage bucket, as this is not created automatically. // Unlike the S3 adapter, you must create a new Cloud Storage bucket, as this is not created automatically.
// See https://googlecloudplatform.github.io/gcloud-node/#/docs/master/guides/authentication // See https://googlecloudplatform.github.io/gcloud-node/#/docs/master/guides/authentication
// for more details. // for more details.
constructor( constructor(
projectId = requiredParameter('GCSAdapter requires a GCP Project ID'), projectId = requiredOrFromEnvironment('GCP_PROJECT_ID', 'projectId'),
keyFilename = requiredParameter('GCSAdapter requires a GCP keyfile'), keyFilename = requiredOrFromEnvironment('GCP_KEYFILE_PATH', 'keyfile path'),
bucket = requiredParameter('GCSAdapter requires a GCS bucket name'), bucket = requiredOrFromEnvironment('GCS_BUCKET_NAME', 'bucket name'),
{ bucketPrefix = '', { bucketPrefix = fromEnvironmentOrDefault('GCS_BUCKET_PREFIX', ''),
directAccess = false } = {} directAccess = fromEnvironmentOrDefault('GCS_DIRECT_ACCESS', false) } = {}) {
) {
super(); super();
this._bucket = bucket; this._bucket = bucket;

View File

@@ -2,7 +2,7 @@
AdaptableController.js AdaptableController.js
AdaptableController is the base class for all controllers AdaptableController is the base class for all controllers
that support adapter, that support adapter,
The super class takes care of creating the right instance for the adapter The super class takes care of creating the right instance for the adapter
based on the parameters passed based on the parameters passed
@@ -28,30 +28,30 @@ export class AdaptableController {
this.validateAdapter(adapter); this.validateAdapter(adapter);
this[_adapter] = adapter; this[_adapter] = adapter;
} }
get adapter() { get adapter() {
return this[_adapter]; return this[_adapter];
} }
get config() { get config() {
return new Config(this.appId); return new Config(this.appId);
} }
expectedAdapterType() { expectedAdapterType() {
throw new Error("Subclasses should implement expectedAdapterType()"); throw new Error("Subclasses should implement expectedAdapterType()");
} }
validateAdapter(adapter) { validateAdapter(adapter) {
if (!adapter) { if (!adapter) {
throw new Error(this.constructor.name+" requires an adapter"); throw new Error(this.constructor.name+" requires an adapter");
} }
let Type = this.expectedAdapterType(); let Type = this.expectedAdapterType();
// Allow skipping for testing // Allow skipping for testing
if (!Type) { if (!Type) {
return; return;
} }
// Makes sure the prototype matches // Makes sure the prototype matches
let mismatches = Object.getOwnPropertyNames(Type.prototype).reduce( (obj, key) => { let mismatches = Object.getOwnPropertyNames(Type.prototype).reduce( (obj, key) => {
const adapterType = typeof adapter[key]; const adapterType = typeof adapter[key];
@@ -64,7 +64,7 @@ export class AdaptableController {
} }
return obj; return obj;
}, {}); }, {});
if (Object.keys(mismatches).length > 0) { if (Object.keys(mismatches).length > 0) {
throw new Error("Adapter prototype don't match expected prototype", adapter, mismatches); throw new Error("Adapter prototype don't match expected prototype", adapter, mismatches);
} }

View File

@@ -13,11 +13,11 @@ export class FilesController extends AdaptableController {
} }
createFile(config, filename, data, contentType) { createFile(config, filename, data, contentType) {
let extname = path.extname(filename); let extname = path.extname(filename);
const hasExtension = extname.length > 0; const hasExtension = extname.length > 0;
if (!hasExtension && contentType && mime.extension(contentType)) { if (!hasExtension && contentType && mime.extension(contentType)) {
filename = filename + '.' + mime.extension(contentType); filename = filename + '.' + mime.extension(contentType);
} else if (hasExtension && !contentType) { } else if (hasExtension && !contentType) {
@@ -27,6 +27,8 @@ export class FilesController extends AdaptableController {
filename = randomHexString(32) + '_' + filename; filename = randomHexString(32) + '_' + filename;
var location = this.adapter.getFileLocation(config, filename); var location = this.adapter.getFileLocation(config, filename);
console.log(this.adapter);
console.log(location);
return this.adapter.createFile(config, filename, data, contentType).then(() => { return this.adapter.createFile(config, filename, data, contentType).then(() => {
return Promise.resolve({ return Promise.resolve({
url: location, url: location,