Skip to content
This repository has been archived by the owner on Oct 2, 2021. It is now read-only.

Commit

Permalink
feat(session): Add rule
Browse files Browse the repository at this point in the history
  • Loading branch information
dferber90 committed Oct 25, 2015
1 parent dfc95e5 commit 8d44769
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ For a more thorough introduction, read [setting up a Meteor project](docs/SETUP_
* [check](docs/rules/check.md): Core API for check and Match
* [connections](docs/rules/connections.md): Core API for connections
* [collections](docs/rules/collections.md): Core API for collections
* [session](docs/rules/session.md): Core API for Session

## Best Practices
* [audit-argument-checks](docs/rules/audit-argument-checks.md): Enforce check on all arguments passed to methods and publish functions
Expand Down
114 changes: 114 additions & 0 deletions docs/rules/session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Core API for Session (session)

Prevent misusage of [Session](http://docs.meteor.com/#/full/session).


## Rule Details

This rule aims to prevent errors when using Publications and Subscriptions. It verifies `Session` is used in the correct environments.

The following patterns are considered warnings:

```js

Session.set('foo')

```

```js

Session.setDefault('foo')

```


```js

Session.set('foo', true, 'bar')

```


```js

if (Meteor.isServer) {
Session.set('foo')
}

```


```js

Session.get('foo', true)

```


```js

Session.get()

```


```js

Session.equals('foo')

```

The following patterns are not warnings:

```js

Session.set('foo', true)

```

```js

Session.setDefault('foo', true)

```

```js

Session.get('foo')

```

```js

Session.equals('foo', true)

```

### Options

#### no-equal

By default this rule does not warn when trying to call `Session.equal`. Usually a call to `Session.equals` is meant instead.
To warn when using `Session.equal`, configure the rule as

```
session: [2, "no-equal"]
```

With this configuration, the rule will warn on this pattern:

```js

Session.equal('foo', 'bar')

```

## When Not To Use It

Disable this rule if you are using [no-session](./no-session.md).

## Further Reading

- http://docs.meteor.com/#/full/session
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module.exports = {
check: unpack('./rules/check'),
connections: unpack('./rules/connections'),
collections: unpack('./rules/collections'),
session: unpack('./rules/session'),

// Best Practices
'audit-argument-checks': unpack('./rules/audit-argument-checks'),
Expand All @@ -39,6 +40,7 @@ module.exports = {
check: 0,
connections: 0,
collections: 0,
session: 0,

// Best Practices
'audit-argument-checks': 0,
Expand Down
73 changes: 73 additions & 0 deletions lib/rules/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @fileoverview Core API for Session
* @author Dominik Ferber
* @copyright 2015 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/

// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------

import {NON_METEOR, SERVER} from '../util/environment'
import {getExecutors} from '../util'
import {getPropertyName} from '../util/ast'

module.exports = getMeta => context => {
const {env} = getMeta(context)

// ---------------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------------

if (env === NON_METEOR || env === SERVER) {
return {}
}

return {

CallExpression: function (node) {
if (
node.callee.type === 'MemberExpression' &&
node.callee.object.type === 'Identifier' &&
node.callee.object.name === 'Session'
) {
const executors = getExecutors(env, context.getAncestors())
if (executors.size === 0) {
return
}
if (executors.has('server')) {
context.report(node, 'Allowed on client only')
return
}

switch (getPropertyName(node.callee.property)) {
case 'set':
case 'setDefault':
case 'equals':
if (node.arguments.length !== 2) {
context.report(node, 'Expected two arguments')
}
break
case 'get':
if (node.arguments.length !== 1) {
context.report(node, 'Expected one argument')
}
break
case 'equal':
if (context.options.length > 0 && context.options[0] === 'no-equal') {
context.report(node.callee.property, 'Did you mean "Session.equals" instead?')
}
break
}
}
}

}
}

module.exports.schema = [
{
enum: ['equal', 'no-equal']
}
]
121 changes: 121 additions & 0 deletions tests/lib/rules/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* @fileoverview Core API for Session
* @author Dominik Ferber
* @copyright 2015 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/

// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------

import {NON_METEOR, UNIVERSAL, CLIENT, SERVER} from '../../../dist/util/environment'
const rule = require('../../../dist/rules/session')
const RuleTester = require('eslint').RuleTester

const commonValidCode = [
'x()',
'Session.set("foo", true)',
'Session.setDefault("foo", true)',
'Session.get("foo")',
'Session.equals("foo", true)',
{
code: `Session.equal('foo', 'bar')`,
options: ['equal']
},
`
if (Meteor.isServer) {
Session.set('foo')
}
`
]

const commonInvalidCode = [
{
code: `Session.set('foo')`,
errors: [{message: 'Expected two arguments', type: 'CallExpression'}]
},
{
code: `Session.setDefault('foo')`,
errors: [{message: 'Expected two arguments', type: 'CallExpression'}]
},
{
code: `Session.set('foo', true, 'bar')`,
errors: [{message: 'Expected two arguments', type: 'CallExpression'}]
},
{
code: `
Session.get('foo', true)
`,
errors: [{message: 'Expected one argument', type: 'CallExpression'}]
},
{
code: `Session.get()`,
errors: [{message: 'Expected one argument', type: 'CallExpression'}]
},
{
code: `Session.equals('foo')`,
errors: [{message: 'Expected two arguments', type: 'CallExpression'}]
},
{
code: `Session.equal('foo', 'bar')`,
options: ['no-equal'],
errors: [{message: 'Did you mean "Session.equals" instead?', type: 'Identifier'}]
}
]

// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

const ruleTester = new RuleTester()

ruleTester.run('session', rule(() => ({env: CLIENT})), {
valid: [
...commonValidCode
],

invalid: [
...commonInvalidCode
]
})

ruleTester.run('session', rule(() => ({env: UNIVERSAL})), {
valid: [
`
if (Meteor.isClient) {
Session.set('foo', true)
}
`,
`
if (Meteor.isCordova) {
Session.set('foo', true)
}
`
],

invalid: [
{
code: `Session.set('foo', true)`,
errors: [{message: 'Allowed on client only', type: 'CallExpression'}]
}
]
})

ruleTester.run('session', rule(() => ({env: SERVER})), {
valid: [
...commonValidCode,
...commonInvalidCode
],

invalid: []
})

ruleTester.run('session', rule(() => ({env: NON_METEOR})), {
valid: [
...commonValidCode,
...commonInvalidCode
],

invalid: []
})

0 comments on commit 8d44769

Please sign in to comment.