Skip to content

Commit

Permalink
Merge pull request #89 from dburles/meteor-3
Browse files Browse the repository at this point in the history
Meteor 2.3 and 3 support
  • Loading branch information
dburles authored Dec 9, 2024
2 parents 6603180 + 4856638 commit 67f177c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 84 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/testsuite.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Tests
on: [push, pull_request]
jobs:
tests:
name: tests
runs-on: ubuntu-latest
strategy:
matrix:
meteor-release:
- "--release 2.8.2"
- "--release 3.1"
steps:
- name: checkout
uses: actions/checkout@v3

- name: Install Dependencies
run: |
curl https://install.meteor.com | /bin/sh
npm i -g @zodern/mtest
- name: Run Tests
run: |
# Fix using old versions of Meteor
export NODE_TLS_REJECT_UNAUTHORIZED=0
mtest --package ./ --once ${{ matrix.meteorRelease }}
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ Collection helpers automatically sets up a transformation on your collections us
## Installation

```sh
$ meteor add dburles:collection-helpers
meteor add dburles:collection-helpers
```

## Usage

Write your helpers somewhere seen by both client and server.

```javascript
Books = new Mongo.Collection('books');
Authors = new Mongo.Collection('authors');
const Books = new Mongo.Collection('books');
const Authors = new Mongo.Collection('authors');

Books.helpers({
author() {
return Authors.findOne(this.authorId);
return Authors.findOne(this.authorId); // Client only (Meteor 3+)
},
authorAsync() {
return Authors.findOneAsync(this.authorId);
}
});

Expand All @@ -35,9 +38,17 @@ Authors.helpers({
This will then allow you to do:

```javascript
Books.findOne().author().firstName; // Charles
Books.findOne().author().fullName(); // Charles Darwin
Authors.findOne().books()
const book = await Books.findOneAsync();
const author = await book.authorAsync();
author.firstName; // Charles
author.fullName(); // Charles Darwin
```

and:

```javascript
const author = await Authors.findOneAsync();
await author.books().fetchAsync();
```

Our relationships are resolved by the collection helper, avoiding unnecessary template helpers. So we can simply write:
Expand All @@ -62,7 +73,7 @@ Template.books.helpers({
</template>
```

## Meteor.users
### Meteor.users

You can also apply helpers to the Meteor.users collection

Expand All @@ -77,16 +88,22 @@ Meteor.users.helpers({
Sometimes it may be useful to apply the transformation directly to an object.

```js
var doc = {
const doc = {
firstName: 'Charles',
lastName: 'Darwin'
};

var transformedDoc = Authors._transform(doc);
const transformedDoc = Authors._transform(doc);

transformedDoc.fullName(); // Charles Darwin
```

### Testing

```sh
meteor test-packages ./
```

### License

MIT
18 changes: 6 additions & 12 deletions collection-helpers.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
Mongo.Collection.prototype.helpers = function(helpers) {
var self = this;

if (self._transform && ! self._helpers)
if (this._transform && !this._helpers)
throw new Meteor.Error("Can't apply helpers to '" +
self._name + "' a transform function already exists!");
this._name + "' a transform function already exists!");

if (! self._helpers) {
self._helpers = function Document(doc) { return _.extend(this, doc); };
self._transform = function(doc) {
return new self._helpers(doc);
};
if (!this._helpers) {
this._helpers = function Document(doc) { return Object.assign(this, doc); };
this._transform = doc => new this._helpers(doc);
}

_.each(helpers, function(helper, key) {
self._helpers.prototype[key] = helper;
});
Object.keys(helpers).forEach(key => (this._helpers.prototype[key] = helpers[key]));
};
184 changes: 128 additions & 56 deletions collection-helpers_tests.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,146 @@
Tinytest.add("works", function(test) {
Books = new Mongo.Collection('books' + test.id);
Authors = new Mongo.Collection('authors' + test.id);
const meteorVersion = Meteor.release
? parseFloat(Meteor.release.split("@")[1])
: null;

var author1 = Authors.insert({
firstName: 'Charles',
lastName: 'Darwin'
});
if (meteorVersion && meteorVersion >= 3) {
Tinytest.addAsync("works", async function (test) {
const Books = new Mongo.Collection(
Meteor.isClient ? null : "books" + test.id
);
const Authors = new Mongo.Collection(
Meteor.isClient ? null : "authors" + test.id
);

var author2 = Authors.insert({
firstName: 'Carl',
lastName: 'Sagan'
});
const author1 = await Authors.insertAsync({
firstName: "Charles",
lastName: "Darwin",
});

var book1 = Books.insert({
authorId: author1,
name: 'On the Origin of Species'
});
const author2 = await Authors.insertAsync({
firstName: "Carl",
lastName: "Sagan",
});

var book2 = Books.insert({
authorId: author2,
name: 'Contact'
});
const book1 = await Books.insertAsync({
authorId: author1,
name: "On the Origin of Species",
});

Books.helpers({
author: function() {
return Authors.findOne(this.authorId);
}
});
const book2 = await Books.insertAsync({
authorId: author2,
name: "Contact",
});

// We should be able to apply more if we wish
Books.helpers({
foo: 'bar'
});
Books.helpers({
author() {
return Authors.findOneAsync(this.authorId);
},
});

// We should be able to apply more if we wish
Books.helpers({
foo: "bar",
});

Authors.helpers({
fullName() {
return this.firstName + " " + this.lastName;
},
books() {
return Books.find({ authorId: this._id });
},
});

const book = await Books.findOneAsync(book1);
const author = await book.author();

Authors.helpers({
fullName: function() {
return this.firstName + ' ' + this.lastName;
},
books: function() {
return Books.find({ authorId: this._id });
}
test.equal(author.firstName, "Charles");
test.equal(author.fullName(), "Charles Darwin");
test.equal(book.foo, "bar");

const authorCarl = await Authors.findOneAsync(author2);
const booksByCarl = await authorCarl.books().fetchAsync();

test.equal(booksByCarl.length, 1);
});
} else {
// Meteor < 3.0
Tinytest.add("works", function (test) {
const Books = new Mongo.Collection("books" + test.id);
const Authors = new Mongo.Collection("authors" + test.id);

var book = Books.findOne(book1);
var author = book.author();
test.equal(author.firstName, 'Charles');
test.equal(book.foo, 'bar');
const author1 = Authors.insert({
firstName: "Charles",
lastName: "Darwin",
});

book = Books.findOne(book2);
author = book.author();
test.equal(author.fullName(), 'Carl Sagan');
const author2 = Authors.insert({
firstName: "Carl",
lastName: "Sagan",
});

author = Authors.findOne(author1);
books = author.books();
test.equal(books.count(), 1);
});
const book1 = Books.insert({
authorId: author1,
name: "On the Origin of Species",
});

Tinytest.add("throw error if transform function already exists", function(test) {
Author = function(doc) { return _.extend(this, doc); };
const book2 = Books.insert({
authorId: author2,
name: "Contact",
});

Author.prototype.fullName = 'Charles Darwin';
Books.helpers({
author: function () {
return Authors.findOne(this.authorId);
},
});

Authors = new Meteor.Collection('authors' + test.id, {
transform: function(doc) { return new Author(doc); }});
// We should be able to apply more if we wish
Books.helpers({
foo: "bar",
});

test.throws(function() {
Authors.helpers({
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
fullName: function () {
return this.firstName + " " + this.lastName;
},
books: function () {
return Books.find({ authorId: this._id });
},
});

const book = Books.findOne(book1);
const author = book.author();
test.equal(author.firstName, "Charles");
test.equal(book.foo, "bar");

const authorCarl = Authors.findOne(author1);
const booksByCarl = author.books();
test.equal(booksByCarl.count(), 1);
});
});
}

Tinytest.add(
"throw error if transform function already exists",
function (test) {
Author = function (doc) {
return _.extend(this, doc);
};

Author.prototype.fullName = "Charles Darwin";

Authors = new Meteor.Collection("authors" + test.id, {
transform: function (doc) {
return new Author(doc);
},
});

test.throws(function () {
Authors.helpers({
fullName: function () {
return this.firstName + " " + this.lastName;
},
});
});
}
);
9 changes: 3 additions & 6 deletions package.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
Package.describe({
name: "dburles:collection-helpers",
summary: "Transform your collections with helpers that you define",
version: "1.1.0",
version: "2.0.0",
documentation: "README.md",
git: "/~https://github.com/dburles/meteor-collection-helpers.git",
});

Package.onUse(function(api) {
api.versionsFrom('1.4.2');
api.use([
'underscore',
'mongo']);
api.versionsFrom(['2.3', '3.0']);
api.use(['mongo']);

api.addFiles('collection-helpers.js');
});

Package.onTest(function(api) {
api.use([
'tinytest',
'underscore',
'mongo',
'dburles:collection-helpers']);

Expand Down

0 comments on commit 67f177c

Please sign in to comment.