Meteor-Community-Packages / Meteor-CollectionFS

Reactive file manager for Meteor
MIT License
1.05k stars 237 forks source link

How to use with js modules #955

Open mmintel opened 8 years ago

mmintel commented 8 years ago

hi there,

first off: CollectionFS is working fine with Meteor 1.3, but now I wanted to use React Hotloader (https://github.com/gadicc/meteor-react-hotloader) as well and (I guess) this package forces the use of js modules. So now I am getting this error here: TypeError: Cannot read property 'Collection' of undefined Which makes sense because I didn't import CollectionFS now.

My question is: how do I import it properly? The code below doesnt work.

import {Mongo} from 'meteor/mongo';
import {FS} from 'meteor/cfs:standard-packages';
// import {FS.Collection} from 'meteor/cfs:collection';
import {GridFS} from 'meteor/cfs:gridfs';

var createThumb = function(fileObj, readStream, writeStream) {
  gm(readStream, fileObj.name()).resize('256', '256').stream().pipe(writeStream);
};

var createMedium = function(fileObj, readStream, writeStream) {
  gm(readStream, fileObj.name()).resize('800', '800').stream().pipe(writeStream);
};

var Images = new FS.Collection("images", {
  stores: [
      new FS.Store.GridFS("thumbs", { transformWrite: createThumb }),
      new FS.Store.GridFS("medium", { transformWrite: createMedium })
  ],
  filter: {
    maxSize: 5242880, // matches 5mb
    allow: {
      contentTypes: ['image/*'],
    //   extensions: ['png', 'jpg', 'jpeg']
    },
    // deny: {
    //   contentTypes: ['image/*'],
    //   extensions: ['gif', 'bmp']
    // },
    onInvalid: function (message) {
      if (Meteor.isClient) {
        alert(message);
      } else {
        console.log(message);
      }
    }
  }
});

export default Images;
appdrop commented 8 years ago

@mmintel I just deleted import statements of all CollectionFS packages and it's working now for me:

// installed packages:
// cfs:standard-packages, cfs:collection, cfs:gridfs

// import {FS} from 'meteor/cfs:standard-packages'

console.log(!!FS) // true
console.log(!!FS.Collection) // true
console.log(!!FS.Store) // true
console.log(!!FS.Store.GridFS) // true

As I understand cfs:standard-packages just assign FS to global object and don't use any kind of import-export module system. And import of non-existing object (=== undefined) produces your error.

Using other packages should not be a problem as long as they don't use same name on global object ;)

mmintel commented 8 years ago

@EliasKovv thanks you were right! it was another import that was crashing my app actually. but anyway it would be nice to know which files you'd need to import (and how). I prefer to use the imports just to know about my dependencies.

appdrop commented 8 years ago

@mmintel agree, imports are very helpful, hope to use it with CollectionFS someday

raix commented 8 years ago

I agree - but it requires some refactoring and a dependency on Meteor 1.3

jebarjonet commented 8 years ago

You can access FS this way without adding anything to your current code/packages :

import { FS } from 'meteor/cfs:base-package';
zeroasterisk commented 8 years ago

Yup, I've got that working, basic FS exists...

But what I don't yet understand is how to have a server and client config (where the client doesn't know about the server store, for real) and they differ.

import { CreativeFilesServer } from './collection.server.jsx';
import { CreativeFilesClient } from './collection.client.jsx';
export const CreativeFiles = {};
if (Meteor.isServer) {
  CreativeFilesFiles = CreativeFilesServer;
} else {
  CreativeFilesFiles = CreativeFilesClient;
}
jebarjonet commented 8 years ago

Why do they differ ? Not sure but I always declared collections and stores on both server and client on the same file/config

zeroasterisk commented 8 years ago

There are times where they might differ... I think I figured it out... server imports functions which configure, client imports different functions.

// collection.client.jsx
export function makeStoresClient() {
  let cfsStoreFilesystem = new FS.Store.FileSystem('tmp');
  let cfsStoreS3 = new FS.Store.S3('s3');
  return [
    cfsStoreFilesystem,
    cfsStoreS3
  ];
}

// collection.server.jsx
export function makeStoresServer() {
  if (!Meteor.isServer) {
    throw new Meteor.Error(500, 'CreativeFiles.server being run on client');
  }
  if (!(Meteor.settings && Meteor.settings.aws)) {
    console.log(
      'WARNING: Started without Meteor.settings.aws ' +
      ' in creative collection server s3'
    );
    Meteor.settings.aws = {region: '', accessKeyId: '', secretAccessKey: ''};
  }

  let cfsStoreFilesystem = new FS.Store.FileSystem('tmp', {
    path: '/tmp'
  });

  let cfsStoreS3 = new FS.Store.S3('s3', {
    region: Meteor.settings.aws.region,
    accessKeyId: Meteor.settings.aws.accessKeyId,
    secretAccessKey: Meteor.settings.aws.secretAccessKey,
    bucket: 'example',
    ACL: 'public-read',
    // Custom fileKey function
    fileKey: (fileObj) => {
      let id = String(fileObj._id);
      let path = [];
      path.push(id.substring(0, 1));
      path.push(id.substring(1, 2));
      path.push(id.substring(2, 3));
      path.push(id + '-' + fileObj.name());
      return path.join('/');
    }
  });
  return [
    cfsStoreFilesystem,
    cfsStoreS3
  ];
}

// fscollection.js
import { Meteor } from 'meteor/meteor';
import { FS } from 'meteor/cfs:base-package';
import { makeStoresServer } from './collection.server.jsx';
import { makeStoresClient } from './collection.client.jsx';
export const CreativeFiles = {};
if (Meteor.isServer) {
  CreativeFiles = new FS.Collection('creative_files', {
    stores: makeStoresServer(),
    filter: {
      allow: {
        contentTypes: [
          'image/*',
          'video/*'
        ]
      }
    }
  });
} else {
  CreativeFiles = new FS.Collection('creative_files', {
    stores: makeStoresClient(),
    filter: {
      allow: {
        contentTypes: [
          'image/*',
          'video/*'
        ]
      }
    }
  });
}