mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-27 18:52:14 +03:00
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16 - removed GQL dependency - replaced GQL with our brand new NQL implementation - fixed all known filter limitations - GQL suffered from some underlying filter bugs, which NQL tried to fix - the bugs were mostly in how we query the database for relation filtering - the underlying problem was caused by a too simple implementation of querying the relations - mongo-knex has implemented a more robust and complex filtering mechanism for relations - replaced logic in our bookshelf filter plugin - we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex. NQL: https://github.com/NexesJS/NQL mongo-knex: https://github.com/NexesJS/mongo-knex
This commit is contained in:
parent
48923ac327
commit
9d7c3bd726
@ -12,21 +12,20 @@ module.exports = {
|
||||
browse(apiConfig, frame) {
|
||||
debug('browse');
|
||||
|
||||
// CASE: the content api endpoints for pages forces the model layer to return static pages only.
|
||||
// we have to enforce the filter.
|
||||
/**
|
||||
* CASE:
|
||||
*
|
||||
* - the content api endpoints for pages forces the model layer to return static pages only
|
||||
* - we have to enforce the filter
|
||||
*
|
||||
* @TODO: https://github.com/TryGhost/Ghost/issues/10268
|
||||
*/
|
||||
if (frame.options.filter) {
|
||||
if (frame.options.filter.match(/page:\w+\+?/)) {
|
||||
frame.options.filter = frame.options.filter.replace(/page:\w+\+?/, '');
|
||||
}
|
||||
|
||||
if (frame.options.filter) {
|
||||
frame.options.filter = frame.options.filter + '+page:true';
|
||||
} else {
|
||||
frame.options.filter = 'page:true';
|
||||
}
|
||||
frame.options.filter = `${frame.options.filter}+page:true`;
|
||||
} else {
|
||||
frame.options.filter = 'page:true';
|
||||
}
|
||||
|
||||
removeMobiledocFormat(frame);
|
||||
|
||||
debug(frame.options);
|
||||
|
@ -32,24 +32,25 @@ module.exports = {
|
||||
* - user exists? admin api access
|
||||
*/
|
||||
if (utils.isContentAPI(frame)) {
|
||||
// CASE: the content api endpoints for posts should only return non page type resources
|
||||
/**
|
||||
* CASE:
|
||||
*
|
||||
* - the content api endpoints for posts should only return non page type resources
|
||||
* - we have to enforce the filter
|
||||
*
|
||||
* @TODO: https://github.com/TryGhost/Ghost/issues/10268
|
||||
*/
|
||||
if (frame.options.filter) {
|
||||
if (frame.options.filter.match(/page:\w+\+?/)) {
|
||||
frame.options.filter = frame.options.filter.replace(/page:\w+\+?/, '');
|
||||
}
|
||||
|
||||
if (frame.options.filter) {
|
||||
frame.options.filter = frame.options.filter + '+page:false';
|
||||
} else {
|
||||
frame.options.filter = 'page:false';
|
||||
}
|
||||
frame.options.filter = `${frame.options.filter}+page:false`;
|
||||
} else {
|
||||
frame.options.filter = 'page:false';
|
||||
}
|
||||
|
||||
// CASE: the content api endpoint for posts should not return mobiledoc
|
||||
removeMobiledocFormat(frame);
|
||||
|
||||
// CASE: Members needs to have the tags to check if its allowed access
|
||||
if (labs.isSet('members')) {
|
||||
// CASE: Members needs to have the tags to check if its allowed access
|
||||
includeTags(frame);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ const _ = require('lodash'),
|
||||
bookshelf = require('bookshelf'),
|
||||
moment = require('moment'),
|
||||
Promise = require('bluebird'),
|
||||
gql = require('ghost-gql'),
|
||||
ObjectId = require('bson-objectid'),
|
||||
debug = require('ghost-ignition').debug('models:base'),
|
||||
config = require('../../config'),
|
||||
@ -1012,6 +1011,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
fetchAll: function (options) {
|
||||
options = options || {};
|
||||
|
||||
const nql = require('@nexes/nql');
|
||||
const modelName = options.modelName;
|
||||
const tableNames = {
|
||||
Post: 'posts',
|
||||
@ -1072,8 +1072,8 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
query.select(toSelect);
|
||||
}
|
||||
|
||||
// filter data
|
||||
gql.knexify(query, gql.parse(filter));
|
||||
// @NOTE: We can't use the filter plugin, because we are not using bookshelf.
|
||||
nql(filter).querySQL(query);
|
||||
|
||||
return query.then((objects) => {
|
||||
debug('fetched', modelName, filter);
|
||||
|
@ -1,210 +1,95 @@
|
||||
var _ = require('lodash'),
|
||||
gql = require('ghost-gql'),
|
||||
common = require('../../lib/common'),
|
||||
filter,
|
||||
filterUtils;
|
||||
const debug = require('ghost-ignition').debug('models:plugins:filter');
|
||||
const common = require('../../lib/common');
|
||||
|
||||
filterUtils = {
|
||||
/**
|
||||
* ## Combine Filters
|
||||
* Util to combine the enforced, default and custom filters such that they behave accordingly
|
||||
* @param {String|Object} enforced - filters which must ALWAYS be applied
|
||||
* @param {String|Object} defaults - filters which must be applied if a matching filter isn't provided
|
||||
* @param {...String|Object} [custom] - custom filters which are additional
|
||||
* @returns {*}
|
||||
*/
|
||||
combineFilters: function combineFilters(enforced, defaults, custom /* ...custom */) {
|
||||
custom = Array.prototype.slice.call(arguments, 2);
|
||||
|
||||
// Ensure everything has been run through the gql parser
|
||||
try {
|
||||
enforced = enforced ? (_.isString(enforced) ? gql.parse(enforced) : enforced) : null;
|
||||
defaults = defaults ? (_.isString(defaults) ? gql.parse(defaults) : defaults) : null;
|
||||
custom = _.map(custom, function (arg) {
|
||||
return _.isString(arg) ? gql.parse(arg) : arg;
|
||||
});
|
||||
} catch (err) {
|
||||
throw new common.errors.ValidationError({
|
||||
err: err,
|
||||
property: 'filter',
|
||||
context: common.i18n.t('errors.models.plugins.filter.errorParsing'),
|
||||
help: common.i18n.t('errors.models.plugins.filter.forInformationRead', {url: 'https://api.ghost.org/docs/filter'})
|
||||
});
|
||||
}
|
||||
|
||||
// Merge custom filter options into a single set of statements
|
||||
custom = gql.json.mergeStatements.apply(this, custom);
|
||||
|
||||
// if there is no enforced or default statements, return just the custom statements;
|
||||
if (!enforced && !defaults) {
|
||||
return custom;
|
||||
}
|
||||
|
||||
// Reduce custom filters based on enforced filters
|
||||
if (custom && !_.isEmpty(custom.statements) && enforced && !_.isEmpty(enforced.statements)) {
|
||||
custom.statements = gql.json.rejectStatements(custom.statements, function (customStatement) {
|
||||
return gql.json.findStatement(enforced.statements, customStatement, 'prop');
|
||||
});
|
||||
}
|
||||
|
||||
// Reduce default filters based on custom filters
|
||||
if (defaults && !_.isEmpty(defaults.statements) && custom && !_.isEmpty(custom.statements)) {
|
||||
defaults.statements = gql.json.rejectStatements(defaults.statements, function (defaultStatement) {
|
||||
return gql.json.findStatement(custom.statements, defaultStatement, 'prop');
|
||||
});
|
||||
}
|
||||
|
||||
// Merge enforced and defaults
|
||||
enforced = gql.json.mergeStatements(enforced, defaults);
|
||||
|
||||
if (_.isEmpty(custom.statements)) {
|
||||
return enforced;
|
||||
}
|
||||
|
||||
if (_.isEmpty(enforced.statements)) {
|
||||
return custom;
|
||||
}
|
||||
|
||||
return {
|
||||
statements: [
|
||||
{group: enforced.statements},
|
||||
{group: custom.statements, func: 'and'}
|
||||
]
|
||||
};
|
||||
const RELATIONS = {
|
||||
tags: {
|
||||
tableName: 'tags',
|
||||
type: 'manyToMany',
|
||||
joinTable: 'posts_tags',
|
||||
joinFrom: 'post_id',
|
||||
joinTo: 'tag_id'
|
||||
},
|
||||
authors: {
|
||||
tableName: 'users',
|
||||
tableNameAs: 'authors',
|
||||
type: 'manyToMany',
|
||||
joinTable: 'posts_authors',
|
||||
joinFrom: 'post_id',
|
||||
joinTo: 'author_id'
|
||||
}
|
||||
};
|
||||
|
||||
filter = function filter(Bookshelf) {
|
||||
var Model = Bookshelf.Model.extend({
|
||||
const EXPANSIONS = [{
|
||||
key: 'primary_tag',
|
||||
replacement: 'tags.slug',
|
||||
expansion: 'posts_tags.sort_order:0+tags.visibility:public'
|
||||
}, {
|
||||
key: 'primary_author',
|
||||
replacement: 'authors.slug',
|
||||
expansion: 'posts_authors.sort_order:0+authors.visibility:public'
|
||||
}, {
|
||||
key: 'authors',
|
||||
replacement: 'authors.slug'
|
||||
}, {
|
||||
key: 'author',
|
||||
replacement: 'authors.slug'
|
||||
}, {
|
||||
key: 'tag',
|
||||
replacement: 'tags.slug'
|
||||
}, {
|
||||
key: 'tags',
|
||||
replacement: 'tags.slug'
|
||||
}];
|
||||
|
||||
const filter = function filter(Bookshelf) {
|
||||
const Model = Bookshelf.Model.extend({
|
||||
// Cached copy of the filters setup for this model instance
|
||||
_filters: null,
|
||||
// Override these on the various models
|
||||
enforcedFilters: function enforcedFilters() {
|
||||
},
|
||||
defaultFilters: function defaultFilters() {
|
||||
},
|
||||
extraFilters: function extraFilters() {
|
||||
},
|
||||
|
||||
preProcessFilters: function preProcessFilters() {
|
||||
this._filters.statements = gql.json.replaceStatements(this._filters.statements, {prop: /primary_tag/}, function (statement) {
|
||||
statement.prop = 'tags.slug';
|
||||
return {
|
||||
group: [
|
||||
statement,
|
||||
{prop: 'posts_tags.sort_order', op: '=', value: 0},
|
||||
{prop: 'tags.visibility', op: '=', value: 'public'}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this._filters.statements = gql.json.replaceStatements(this._filters.statements, {prop: /primary_author/}, function (statement) {
|
||||
statement.prop = 'authors.slug';
|
||||
return {
|
||||
group: [
|
||||
statement,
|
||||
{prop: 'posts_authors.sort_order', op: '=', value: 0},
|
||||
{prop: 'authors.visibility', op: '=', value: 'public'}
|
||||
]
|
||||
};
|
||||
});
|
||||
},
|
||||
enforcedFilters() {},
|
||||
defaultFilters() {},
|
||||
extraFilters() {},
|
||||
|
||||
/**
|
||||
* ## Post process Filters
|
||||
* Post Process filters looking for joins etc
|
||||
* @TODO refactor this
|
||||
* @param {object} options
|
||||
*/
|
||||
postProcessFilters: function postProcessFilters(options) {
|
||||
var joinTables = this._filters.joins;
|
||||
|
||||
if (joinTables && joinTables.indexOf('tags') > -1) {
|
||||
// We need to use leftOuterJoin to insure we still include posts which don't have tags in the result
|
||||
// The where clause should restrict which items are returned
|
||||
this
|
||||
.query('leftOuterJoin', 'posts_tags', 'posts_tags.post_id', '=', 'posts.id')
|
||||
.query('leftOuterJoin', 'tags', 'posts_tags.tag_id', '=', 'tags.id');
|
||||
|
||||
// We need to add a group by to counter the double left outer join
|
||||
// TODO improve on the group by handling
|
||||
options.groups = options.groups || [];
|
||||
options.groups.push('posts.id');
|
||||
}
|
||||
|
||||
if (joinTables && joinTables.indexOf('authors') > -1) {
|
||||
// We need to use leftOuterJoin to insure we still include posts which don't have tags in the result
|
||||
// The where clause should restrict which items are returned
|
||||
this
|
||||
.query('leftOuterJoin', 'posts_authors', 'posts_authors.post_id', '=', 'posts.id')
|
||||
.query('leftOuterJoin', 'users as authors', 'posts_authors.author_id', '=', 'authors.id');
|
||||
|
||||
// We need to add a group by to counter the double left outer join
|
||||
// TODO improve on the group by handling
|
||||
options.groups = options.groups || [];
|
||||
options.groups.push('posts.id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated: `author`, will be removed in Ghost 3.0
|
||||
*/
|
||||
if (joinTables && joinTables.indexOf('author') > -1) {
|
||||
this
|
||||
.query('join', 'users as author', 'author.id', '=', 'posts.author_id');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* ## fetchAndCombineFilters
|
||||
* Helper method, uses the combineFilters util to apply filters to the current model instance
|
||||
* based on options and the set enforced/default filters for this resource
|
||||
* @param {Object} options
|
||||
* @returns {Bookshelf.Model}
|
||||
*/
|
||||
fetchAndCombineFilters: function fetchAndCombineFilters(options) {
|
||||
options = options || {};
|
||||
|
||||
this._filters = filterUtils.combineFilters(
|
||||
this.enforcedFilters(options),
|
||||
this.defaultFilters(options),
|
||||
options.filter,
|
||||
this.extraFilters(options)
|
||||
);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* ## Apply Filters
|
||||
* Method which makes the necessary query builder calls (through knex) for the filters set
|
||||
* on this model instance
|
||||
* @param {Object} options
|
||||
* @returns {Bookshelf.Model}
|
||||
* Method which makes the necessary query builder calls (through knex) for the filters set on this model
|
||||
* instance.
|
||||
*/
|
||||
applyDefaultAndCustomFilters: function applyDefaultAndCustomFilters(options) {
|
||||
var self = this;
|
||||
const nql = require('@nexes/nql');
|
||||
|
||||
// @TODO figure out a better place/way to trigger loading filters
|
||||
if (!this._filters) {
|
||||
this.fetchAndCombineFilters(options);
|
||||
}
|
||||
let custom = options.filter;
|
||||
let extra = this.extraFilters(options);
|
||||
let overrides = this.enforcedFilters(options);
|
||||
let defaults = this.defaultFilters(options);
|
||||
|
||||
if (this._filters) {
|
||||
if (this.debug) {
|
||||
gql.json.printStatements(this._filters.statements);
|
||||
debug('custom', custom);
|
||||
debug('extra', extra);
|
||||
debug('enforced', overrides);
|
||||
debug('default', defaults);
|
||||
|
||||
if (extra) {
|
||||
if (custom) {
|
||||
custom = `${custom}+${extra}`;
|
||||
} else {
|
||||
custom = extra;
|
||||
}
|
||||
|
||||
this.preProcessFilters(options);
|
||||
|
||||
this.query(function (qb) {
|
||||
gql.knexify(qb, self._filters);
|
||||
});
|
||||
|
||||
// Replaces processGQLResult
|
||||
this.postProcessFilters(options);
|
||||
}
|
||||
|
||||
return this;
|
||||
try {
|
||||
this.query((qb) => {
|
||||
nql(custom, {
|
||||
relations: RELATIONS,
|
||||
expansions: EXPANSIONS,
|
||||
overrides: overrides,
|
||||
defaults: defaults
|
||||
}).querySQL(qb);
|
||||
});
|
||||
} catch (err) {
|
||||
throw new common.errors.BadRequestError({
|
||||
message: common.i18n.t('errors.models.plugins.filter.errorParsing'),
|
||||
err: err
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -199,6 +199,16 @@ pagination = function pagination(bookshelf) {
|
||||
|
||||
throw err;
|
||||
});
|
||||
}).catch((err) => {
|
||||
// CASE: SQL syntax is incorrect
|
||||
if (err.errno === 1054 || err.errno === 1) {
|
||||
throw new common.errors.BadRequestError({
|
||||
message: common.i18n.t('errors.models.general.sql'),
|
||||
err: err
|
||||
});
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -587,12 +587,12 @@ Post = ghostBookshelf.Model.extend({
|
||||
|
||||
// CASE: if the filter contains an `IN` operator, we should return the posts first, which match both tags
|
||||
if (options.filter && options.filter.match(/(tags|tag):\s?\[.*\]/)) {
|
||||
order = `count(tags.id) DESC, ${order}`;
|
||||
order = `(SELECT count(*) FROM posts_tags WHERE post_id = posts.id) DESC, ${order}`;
|
||||
}
|
||||
|
||||
// CASE: if the filter contains an `IN` operator, we should return the posts first, which match both authors
|
||||
if (options.filter && options.filter.match(/(authors|author):\s?\[.*\]/)) {
|
||||
order = `count(authors.id) DESC, ${order}`;
|
||||
order = `(SELECT count(*) FROM posts_authors WHERE post_id = posts.id) DESC, ${order}`;
|
||||
}
|
||||
|
||||
return order;
|
||||
|
@ -4,6 +4,18 @@ var _ = require('lodash'),
|
||||
parseContext = require('./parse-context'),
|
||||
_private = {};
|
||||
|
||||
/**
|
||||
* @TODO:
|
||||
*
|
||||
* - remove if we drop `extraFilters` (see e.g. post model)
|
||||
* - we currently accept `?status={value}` in the API
|
||||
* - we currently accept `?staticPages={value}` in the API
|
||||
* - but instead people should use the `?filter=status:{value}`
|
||||
*
|
||||
* This function protects against:
|
||||
*
|
||||
* - public context cannot fetch draft/scheduled posts
|
||||
*/
|
||||
_private.applyStatusRules = function applyStatusRules(docName, method, opts) {
|
||||
var err = new common.errors.NoPermissionError({message: common.i18n.t('errors.permissions.applyStatusRules.error', {docName: docName})});
|
||||
|
||||
|
@ -2,8 +2,20 @@ const _ = require('lodash'),
|
||||
nql = require('@nexes/nql'),
|
||||
debug = require('ghost-ignition').debug('services:url:generator'),
|
||||
localUtils = require('./utils'),
|
||||
|
||||
aliases = {author: 'authors.slug', tags: 'tags.slug', tag: 'tags.slug', authors: 'authors.slug'};
|
||||
// @TODO: merge with filter plugin
|
||||
EXPANSIONS = [{
|
||||
key: 'author',
|
||||
replacement: 'authors.slug'
|
||||
}, {
|
||||
key: 'tags',
|
||||
replacement: 'tags.slug'
|
||||
}, {
|
||||
key: 'tag',
|
||||
replacement: 'tags.slug'
|
||||
}, {
|
||||
key: 'authors',
|
||||
replacement: 'authors.slug'
|
||||
}];
|
||||
|
||||
class UrlGenerator {
|
||||
constructor(router, queue, resources, urls, position) {
|
||||
@ -18,7 +30,7 @@ class UrlGenerator {
|
||||
// CASE: routers can define custom filters, but not required.
|
||||
if (this.router.getFilter()) {
|
||||
this.filter = this.router.getFilter();
|
||||
this.nql = nql(this.filter, {aliases});
|
||||
this.nql = nql(this.filter, {expansions: EXPANSIONS});
|
||||
debug('filter', this.filter);
|
||||
}
|
||||
|
||||
|
@ -212,6 +212,9 @@
|
||||
"reason": " Reason: {reason}."
|
||||
},
|
||||
"models": {
|
||||
"general": {
|
||||
"sql": "Could not understand request."
|
||||
},
|
||||
"subscriber": {
|
||||
"notEnoughPermission": "You do not have permission to perform this action"
|
||||
},
|
||||
|
@ -298,6 +298,98 @@ describe('Post API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve posts filtered by related tag', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?filter=tags.slug:[kitchen-sink]`))
|
||||
.set('Authorization', 'Bearer ' + ownerAccessToken)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(2);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts[0].slug.should.equal('ghostly-kitchen-sink');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve posts filtered by related author', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?filter=authors.slug:joe-bloggs`))
|
||||
.set('Authorization', 'Bearer ' + ownerAccessToken)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(4);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts[0].slug.should.equal('not-so-short-bit-complex');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve posts filtered by primary_tag', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?filter=primary_tag:kitchen-sink`))
|
||||
.set('Authorization', 'Bearer ' + ownerAccessToken)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(2);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts[0].slug.should.equal('ghostly-kitchen-sink');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve posts filtered by primary_author', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?filter=primary_author:joe-bloggs`))
|
||||
.set('Authorization', 'Bearer ' + ownerAccessToken)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(4);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts[0].slug.should.equal('not-so-short-bit-complex');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve just featured posts', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('posts/?filter=featured:true'))
|
||||
.set('Authorization', 'Bearer ' + ownerAccessToken)
|
||||
|
@ -132,6 +132,35 @@ describe('Public API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with inverse filters', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('posts/?client_id=ghost-admin&client_secret=not_available&filter=tag:-[bacon,pollo,getting-started]&include=tags'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
|
||||
jsonResponse.posts.should.have.length(2);
|
||||
|
||||
jsonResponse.posts[0].slug.should.eql('not-so-short-bit-complex');
|
||||
jsonResponse.posts[0].tags.length.should.eql(0);
|
||||
jsonResponse.posts[1].slug.should.eql('short-and-sweet');
|
||||
jsonResponse.posts[1].tags.length.should.eql(1);
|
||||
jsonResponse.posts[1].tags[0].slug.should.eql('chorizo');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with author filter', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('posts/?client_id=ghost-admin&client_secret=not_available&filter=authors:[joe-bloggs,pat,ghost]&include=authors'))
|
||||
.expect('Content-Type', /json/)
|
||||
@ -836,7 +865,7 @@ describe('Public API', function () {
|
||||
// Each user should have the correct count
|
||||
_.find(jsonResponse.users, {slug:'joe-bloggs'}).count.posts.should.eql(4);
|
||||
_.find(jsonResponse.users, {slug:'contributor'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.users, {slug:'slimer-mcectoplasm'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.users, {slug:'slimer-mcectoplasm'}).count.posts.should.eql(1);
|
||||
_.find(jsonResponse.users, {slug:'jimothy-bogendath'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.users, {slug: 'smith-wellingsworth'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.users, {slug:'ghost'}).count.posts.should.eql(7);
|
||||
@ -850,8 +879,8 @@ describe('Public API', function () {
|
||||
ids.should.eql([
|
||||
testUtils.DataGenerator.Content.users[1].id,
|
||||
testUtils.DataGenerator.Content.users[2].id,
|
||||
testUtils.DataGenerator.Content.users[3].id,
|
||||
testUtils.DataGenerator.Content.users[7].id,
|
||||
testUtils.DataGenerator.Content.users[3].id,
|
||||
testUtils.DataGenerator.Content.users[0].id
|
||||
]);
|
||||
|
||||
|
@ -147,7 +147,7 @@ describe('Authors Content API V2', function () {
|
||||
// Each user should have the correct count
|
||||
_.find(jsonResponse.authors, {slug:'joe-bloggs'}).count.posts.should.eql(4);
|
||||
_.find(jsonResponse.authors, {slug:'contributor'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.authors, {slug:'slimer-mcectoplasm'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.authors, {slug:'slimer-mcectoplasm'}).count.posts.should.eql(1);
|
||||
_.find(jsonResponse.authors, {slug:'jimothy-bogendath'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.authors, {slug: 'smith-wellingsworth'}).count.posts.should.eql(0);
|
||||
_.find(jsonResponse.authors, {slug:'ghost'}).count.posts.should.eql(7);
|
||||
@ -161,8 +161,8 @@ describe('Authors Content API V2', function () {
|
||||
ids.should.eql([
|
||||
testUtils.DataGenerator.Content.users[1].id,
|
||||
testUtils.DataGenerator.Content.users[2].id,
|
||||
testUtils.DataGenerator.Content.users[3].id,
|
||||
testUtils.DataGenerator.Content.users[7].id,
|
||||
testUtils.DataGenerator.Content.users[3].id,
|
||||
testUtils.DataGenerator.Content.users[0].id
|
||||
]);
|
||||
|
||||
|
@ -49,6 +49,26 @@ describe('Pages', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('browse pages with page:false', function () {
|
||||
const key = localUtils.getValidKey();
|
||||
return request.get(localUtils.API.getApiQuery(`pages/?key=${key}&filter=page:false`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers.vary.should.eql('Accept-Encoding');
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.pages);
|
||||
should.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.pages.should.have.length(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('read page', function () {
|
||||
const key = localUtils.getValidKey();
|
||||
return request.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[5].id}/?key=${key}`))
|
||||
|
@ -168,6 +168,28 @@ describe('Posts', function () {
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts.should.have.length(0);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with basic page filter should not return pages', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=(page:true,page:false)`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.posts);
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts.should.have.length(11);
|
||||
|
||||
jsonResponse.posts.forEach((post) => {
|
||||
post.page.should.be.false();
|
||||
@ -178,7 +200,7 @@ describe('Posts', function () {
|
||||
});
|
||||
|
||||
it('browse posts with author filter', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=authors:[joe-bloggs,pat,ghost]&include=authors`))
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=authors:[joe-bloggs,pat,ghost,slimer-mcectoplasm]&include=authors`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
@ -198,12 +220,18 @@ describe('Posts', function () {
|
||||
// We should have 2 matching items
|
||||
jsonResponse.posts.should.be.an.Array().with.lengthOf(11);
|
||||
|
||||
// The API orders by number of matched authors.
|
||||
jsonResponse.posts[0].slug.should.eql('not-so-short-bit-complex');
|
||||
|
||||
// Each post must either have the author 'joe-bloggs' or 'ghost', 'pat' is non existing author
|
||||
const authors = _.map(jsonResponse.posts, function (post) {
|
||||
const primaryAuthors = _.map(jsonResponse.posts, function (post) {
|
||||
return post.primary_author.slug;
|
||||
});
|
||||
|
||||
authors.should.matchAny(/joe-bloggs|ghost'/);
|
||||
primaryAuthors.should.matchAny(/joe-bloggs|ghost'/);
|
||||
_.filter(primaryAuthors, (value) => {return value === 'ghost';}).length.should.eql(7);
|
||||
_.filter(primaryAuthors, (value) => {return value === 'joe-bloggs';}).length.should.eql(4);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -28,7 +28,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
|
||||
frame.options.filter.should.eql('status:published+tag:eins+page:true');
|
||||
});
|
||||
|
||||
it('remove existing page filter', function () {
|
||||
it('combine filters', function () {
|
||||
const apiConfig = {};
|
||||
const frame = {
|
||||
options: {
|
||||
@ -38,10 +38,10 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
|
||||
};
|
||||
|
||||
serializers.input.pages.browse(apiConfig, frame);
|
||||
frame.options.filter.should.eql('tag:eins+page:true');
|
||||
frame.options.filter.should.eql('page:false+tag:eins+page:true');
|
||||
});
|
||||
|
||||
it('remove existing page filter', function () {
|
||||
it('combine filters', function () {
|
||||
const apiConfig = {};
|
||||
const frame = {
|
||||
options: {
|
||||
@ -51,7 +51,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
|
||||
};
|
||||
|
||||
serializers.input.pages.browse(apiConfig, frame);
|
||||
frame.options.filter.should.eql('page:true');
|
||||
frame.options.filter.should.eql('page:false+page:true');
|
||||
});
|
||||
|
||||
it('remove mobiledoc option from formats', function () {
|
||||
|
@ -49,7 +49,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
|
||||
frame.options.filter.should.eql('status:published+tag:eins+page:false');
|
||||
});
|
||||
|
||||
it('remove existing page filter', function () {
|
||||
it('combine filters', function () {
|
||||
const apiConfig = {};
|
||||
const frame = {
|
||||
options: {
|
||||
@ -62,10 +62,10 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
|
||||
};
|
||||
|
||||
serializers.input.posts.browse(apiConfig, frame);
|
||||
frame.options.filter.should.eql('tag:eins+page:false');
|
||||
frame.options.filter.should.eql('page:true+tag:eins+page:false');
|
||||
});
|
||||
|
||||
it('remove existing page filter', function () {
|
||||
it('combine filters', function () {
|
||||
const apiConfig = {};
|
||||
const frame = {
|
||||
options: {
|
||||
@ -78,7 +78,23 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
|
||||
};
|
||||
|
||||
serializers.input.posts.browse(apiConfig, frame);
|
||||
frame.options.filter.should.eql('page:false');
|
||||
frame.options.filter.should.eql('page:true+page:false');
|
||||
});
|
||||
|
||||
it('combine filters', function () {
|
||||
const apiConfig = {};
|
||||
const frame = {
|
||||
options: {
|
||||
context: {
|
||||
user: 0,
|
||||
api_key_id: 1
|
||||
},
|
||||
filter: '(page:true,page:false)'
|
||||
}
|
||||
};
|
||||
|
||||
serializers.input.posts.browse(apiConfig, frame);
|
||||
frame.options.filter.should.eql('(page:true,page:false)+page:false');
|
||||
});
|
||||
|
||||
it('remove mobiledoc option from formats', function () {
|
||||
|
@ -1,663 +0,0 @@
|
||||
var should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
rewire = require('rewire'),
|
||||
_ = require('lodash'),
|
||||
filter = rewire('../../../../server/models/plugins/filter'),
|
||||
models = require('../../../../server/models'),
|
||||
ghostBookshelf,
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('Filter', function () {
|
||||
before(function () {
|
||||
models.init();
|
||||
ghostBookshelf = _.cloneDeep(models.Base);
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
// re-initialise the plugin with the rewired version
|
||||
filter(ghostBookshelf);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
filter = rewire('../../../../server/models/plugins/filter');
|
||||
});
|
||||
|
||||
describe('Base Model', function () {
|
||||
describe('Enforced & Default Filters', function () {
|
||||
it('should add filter functions to prototype', function () {
|
||||
ghostBookshelf.Model.prototype.enforcedFilters.should.be.a.Function();
|
||||
ghostBookshelf.Model.prototype.defaultFilters.should.be.a.Function();
|
||||
});
|
||||
|
||||
it('filter functions should return undefined', function () {
|
||||
should(ghostBookshelf.Model.prototype.enforcedFilters()).be.undefined();
|
||||
should(ghostBookshelf.Model.prototype.defaultFilters()).be.undefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fetch And Combine Filters', function () {
|
||||
var filterUtils;
|
||||
|
||||
beforeEach(function () {
|
||||
filterUtils = filter.__get__('filterUtils');
|
||||
filterUtils.combineFilters = sandbox.stub();
|
||||
});
|
||||
|
||||
it('should add function to prototype', function () {
|
||||
ghostBookshelf.Model.prototype.fetchAndCombineFilters.should.be.a.Function();
|
||||
});
|
||||
|
||||
it('should set _filters to be the result of combineFilters', function () {
|
||||
filterUtils.combineFilters.returns({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: true}
|
||||
]
|
||||
});
|
||||
var result = ghostBookshelf.Model.prototype.fetchAndCombineFilters();
|
||||
|
||||
result._filters.should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: true}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should call combineFilters with undefined x4 if passed no options', function () {
|
||||
var result = ghostBookshelf.Model.prototype.fetchAndCombineFilters();
|
||||
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql([undefined, undefined, undefined, undefined]);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with enforced filters if set', function () {
|
||||
var filterSpy = sandbox.stub(ghostBookshelf.Model.prototype, 'enforcedFilters')
|
||||
.returns('status:published'),
|
||||
result;
|
||||
|
||||
result = ghostBookshelf.Model.prototype.fetchAndCombineFilters();
|
||||
|
||||
filterSpy.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql(['status:published', undefined, undefined, undefined]);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with default filters if set', function () {
|
||||
var filterSpy = sandbox.stub(ghostBookshelf.Model.prototype, 'defaultFilters')
|
||||
.returns('page:false'),
|
||||
result;
|
||||
|
||||
result = ghostBookshelf.Model.prototype.fetchAndCombineFilters();
|
||||
|
||||
filterSpy.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql([undefined, 'page:false', undefined, undefined]);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with custom filters if set', function () {
|
||||
var result = ghostBookshelf.Model.prototype.fetchAndCombineFilters({
|
||||
filter: 'tag:photo'
|
||||
});
|
||||
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql([undefined, undefined, 'tag:photo', undefined]);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with old-style custom filters if set', function () {
|
||||
sandbox.stub(ghostBookshelf.Model.prototype, 'extraFilters').returns('author:cameron');
|
||||
|
||||
const result = ghostBookshelf.Model.prototype.fetchAndCombineFilters({});
|
||||
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql([undefined, undefined, undefined, 'author:cameron']);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with enforced and defaults if set', function () {
|
||||
var filterSpy = sandbox.stub(ghostBookshelf.Model.prototype, 'enforcedFilters')
|
||||
.returns('status:published'),
|
||||
filterSpy2 = sandbox.stub(ghostBookshelf.Model.prototype, 'defaultFilters')
|
||||
.returns('page:false'),
|
||||
result;
|
||||
|
||||
result = ghostBookshelf.Model.prototype.fetchAndCombineFilters();
|
||||
|
||||
filterSpy.calledOnce.should.be.true();
|
||||
filterSpy2.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args.should.eql(['status:published', 'page:false', undefined, undefined]);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
|
||||
it('should call combineFilters with all values if set', function () {
|
||||
sandbox.stub(ghostBookshelf.Model.prototype, 'defaultFilters').returns('page:false');
|
||||
sandbox.stub(ghostBookshelf.Model.prototype, 'enforcedFilters').returns('status:published');
|
||||
sandbox.stub(ghostBookshelf.Model.prototype, 'extraFilters').returns('author:cameron');
|
||||
|
||||
const result = ghostBookshelf.Model.prototype.fetchAndCombineFilters({
|
||||
filter: 'tag:photo'
|
||||
});
|
||||
|
||||
ghostBookshelf.Model.prototype.enforcedFilters.calledOnce.should.be.true();
|
||||
ghostBookshelf.Model.prototype.defaultFilters.calledOnce.should.be.true();
|
||||
|
||||
filterUtils.combineFilters.calledOnce.should.be.true();
|
||||
filterUtils.combineFilters.firstCall.args
|
||||
.should.eql(['status:published', 'page:false', 'tag:photo', 'author:cameron']);
|
||||
should(result._filters).be.undefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Apply Default and Custom Filters', function () {
|
||||
var fetchSpy,
|
||||
restoreGQL,
|
||||
filterGQL;
|
||||
|
||||
beforeEach(function () {
|
||||
filterGQL = {};
|
||||
fetchSpy = sandbox.stub(ghostBookshelf.Model.prototype, 'fetchAndCombineFilters');
|
||||
filterGQL.knexify = sandbox.stub();
|
||||
filterGQL.json = {
|
||||
printStatements: sandbox.stub(),
|
||||
replaceStatements: sandbox.stub().returnsArg(0)
|
||||
};
|
||||
|
||||
restoreGQL = filter.__set__('gql', filterGQL);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
restoreGQL();
|
||||
});
|
||||
|
||||
it('should call fetchAndCombineFilters if _filters not set', function () {
|
||||
var result = ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.calledOnce.should.be.true();
|
||||
should(result._filters).be.null();
|
||||
});
|
||||
|
||||
it('should NOT call fetchAndCombineFilters if _filters IS set', function () {
|
||||
ghostBookshelf.Model.prototype._filters = 'test';
|
||||
|
||||
var result = ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.called.should.be.false();
|
||||
result._filters.should.eql('test');
|
||||
});
|
||||
|
||||
it('should call knexify with the filters that are set', function () {
|
||||
ghostBookshelf.Model.prototype._filters = {
|
||||
statements: [
|
||||
{prop: 'title', op: '=', value: 'Hello Word'}
|
||||
]
|
||||
};
|
||||
ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.called.should.be.false();
|
||||
filterGQL.knexify.called.should.be.true();
|
||||
filterGQL.knexify.firstCall.args[1].should.eql({
|
||||
statements: [
|
||||
{prop: 'title', op: '=', value: 'Hello Word'}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should print statements in debug mode', function () {
|
||||
ghostBookshelf.Model.prototype.debug = true;
|
||||
ghostBookshelf.Model.prototype._filters = {
|
||||
statements: [
|
||||
{prop: 'tags', op: 'IN', value: ['photo', 'video']}
|
||||
]
|
||||
};
|
||||
|
||||
ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
filterGQL.json.printStatements.calledOnce.should.be.true();
|
||||
filterGQL.json.printStatements.firstCall.args[0].should.eql([
|
||||
{prop: 'tags', op: 'IN', value: ['photo', 'video']}
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Pre Process Filters', function () {
|
||||
it('should not have tests yet, as this needs to be removed');
|
||||
});
|
||||
|
||||
describe('Post Process Filters', function () {
|
||||
it('should not have tests yet, as this needs to be removed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Utils', function () {
|
||||
describe('Combine Filters', function () {
|
||||
var gql, combineFilters, parseSpy, mergeSpy, findSpy, rejectSpy;
|
||||
|
||||
beforeEach(function () {
|
||||
combineFilters = filter.__get__('filterUtils').combineFilters;
|
||||
gql = filter.__get__('gql');
|
||||
parseSpy = sandbox.spy(gql, 'parse');
|
||||
mergeSpy = sandbox.spy(gql.json, 'mergeStatements');
|
||||
findSpy = sandbox.spy(gql.json, 'findStatement');
|
||||
rejectSpy = sandbox.spy(gql.json, 'rejectStatements');
|
||||
});
|
||||
|
||||
it('should return empty statement object when there are no filters', function () {
|
||||
combineFilters().should.eql({statements: []});
|
||||
parseSpy.called.should.be.false();
|
||||
mergeSpy.calledOnce.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
describe('Single filter rules', function () {
|
||||
it('should return enforced filters if only those are set', function () {
|
||||
combineFilters('status:published').should.eql({
|
||||
statements: [
|
||||
{prop: 'status', op: '=', value: 'published'}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('should return default filters if only those are set (undefined)', function () {
|
||||
combineFilters(undefined, 'page:false').should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('should return default filters if only those are set (null)', function () {
|
||||
combineFilters(null, 'page:false').should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('should return custom filters if only those are set', function () {
|
||||
combineFilters(null, null, 'tags:[photo,video]').should.eql({
|
||||
statements: [
|
||||
{prop: 'tags', op: 'IN', value: ['photo', 'video']}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.true();
|
||||
mergeSpy.calledOnce.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('does NOT call parse on enforced filter if it is NOT a string', function () {
|
||||
var statement = {
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
};
|
||||
combineFilters(statement, null, null).should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.false();
|
||||
mergeSpy.calledOnce.should.be.false();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('does NOT call parse on default filter if it is NOT a string', function () {
|
||||
var statement = {
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
};
|
||||
combineFilters(null, statement, null).should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.false();
|
||||
mergeSpy.calledOnce.should.be.false();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('does NOT call parse on custom filter if it is NOT a string', function () {
|
||||
var statement = {
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
};
|
||||
combineFilters(null, null, statement).should.eql({
|
||||
statements: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
});
|
||||
parseSpy.calledOnce.should.be.false();
|
||||
mergeSpy.calledOnce.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Combo filter rules', function () {
|
||||
it('should merge enforced and default filters if both are provided', function () {
|
||||
combineFilters('status:published', 'page:false').should.eql({
|
||||
statements: [
|
||||
{prop: 'status', op: '=', value: 'published'},
|
||||
{prop: 'page', op: '=', value: false, func: 'and'}
|
||||
]
|
||||
});
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('should merge custom filters if more than one is provided', function () {
|
||||
combineFilters(null, null, 'tag:photo', 'featured:true').should.eql({
|
||||
statements: [
|
||||
{prop: 'tag', op: '=', value: 'photo'},
|
||||
{prop: 'featured', op: '=', value: true, func: 'and'}
|
||||
]
|
||||
});
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledOnce.should.be.true();
|
||||
findSpy.called.should.be.false();
|
||||
rejectSpy.called.should.be.false();
|
||||
});
|
||||
|
||||
it('should try to reduce custom filters if custom and enforced are provided', function () {
|
||||
combineFilters('status:published', null, 'tag:photo').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
{prop: 'status', op: '=', value: 'published'}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: '=', value: 'photo'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: 'photo', prop: 'tag'}]);
|
||||
|
||||
findSpy.calledOnce.should.be.true();
|
||||
findSpy.getCall(0).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: '=', value: 'photo', prop: 'tag'},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should actually reduce custom filters if one matches enforced', function () {
|
||||
combineFilters('status:published', null, 'tag:photo,status:draft').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
{prop: 'status', op: '=', value: 'published'}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: '=', value: 'photo'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: 'photo', prop: 'tag'},
|
||||
{op: '=', value: 'draft', prop: 'status', func: 'or'}]);
|
||||
|
||||
findSpy.calledTwice.should.be.true();
|
||||
findSpy.getCall(0).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: '=', value: 'photo', prop: 'tag'},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.getCall(1).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: '=', value: 'draft', prop: 'status', func: 'or'},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return only enforced if custom filters are reduced to nothing', function () {
|
||||
combineFilters('status:published', null, 'status:draft').should.eql({
|
||||
statements: [
|
||||
{prop: 'status', op: '=', value: 'published'}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: 'draft', prop: 'status'}]);
|
||||
|
||||
findSpy.calledOnce.should.be.true();
|
||||
findSpy.getCall(0).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: '=', value: 'draft', prop: 'status'},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should try to reduce default filters if default and custom are provided', function () {
|
||||
combineFilters(null, 'page:false', 'tag:photo').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
{prop: 'page', op: '=', value: false}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: '=', value: 'photo'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: false, prop: 'page'}]);
|
||||
|
||||
findSpy.calledOnce.should.be.true();
|
||||
findSpy.firstCall.args.should.eql([
|
||||
[{op: '=', prop: 'tag', value: 'photo'}],
|
||||
{op: '=', prop: 'page', value: false},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should actually reduce default filters if one matches custom', function () {
|
||||
combineFilters(null, 'page:false,author:cameron', 'tag:photo+page:true').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
// currently has func: or needs fixing
|
||||
{prop: 'author', op: '=', value: 'cameron'}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: '=', value: 'photo'},
|
||||
{prop: 'page', op: '=', value: true, func: 'and'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
|
||||
rejectSpy.firstCall.args[0].should.eql([
|
||||
{op: '=', value: false, prop: 'page'},
|
||||
{op: '=', value: 'cameron', prop: 'author'}
|
||||
]);
|
||||
|
||||
findSpy.calledTwice.should.be.true();
|
||||
findSpy.firstCall.args.should.eql([
|
||||
[
|
||||
{op: '=', prop: 'tag', value: 'photo'},
|
||||
{func: 'and', op: '=', prop: 'page', value: true}
|
||||
],
|
||||
{op: '=', prop: 'page', value: false},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.secondCall.args.should.eql([
|
||||
[
|
||||
{op: '=', prop: 'tag', value: 'photo'},
|
||||
{func: 'and', op: '=', prop: 'page', value: true}
|
||||
],
|
||||
{op: '=', prop: 'author', value: 'cameron'},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return only custom if default filters are reduced to nothing', function () {
|
||||
combineFilters(null, 'page:false', 'tag:photo,page:true').should.eql({
|
||||
statements: [
|
||||
{prop: 'tag', op: '=', value: 'photo'},
|
||||
{prop: 'page', op: '=', value: true, func: 'or'}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledTwice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledOnce.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: false, prop: 'page'}]);
|
||||
|
||||
findSpy.calledOnce.should.be.true();
|
||||
findSpy.firstCall.args.should.eql([
|
||||
[
|
||||
{op: '=', prop: 'tag', value: 'photo'},
|
||||
{func: 'or', op: '=', prop: 'page', value: true}
|
||||
],
|
||||
{op: '=', prop: 'page', value: false},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return a merger of enforced and defaults plus custom filters if provided', function () {
|
||||
combineFilters('status:published', 'page:false', 'tag:photo').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
{prop: 'status', op: '=', value: 'published'},
|
||||
{prop: 'page', op: '=', value: false, func: 'and'}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: '=', value: 'photo'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.calledThrice.should.be.true();
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.calledTwice.should.be.true();
|
||||
rejectSpy.firstCall.args[0].should.eql([{op: '=', value: 'photo', prop: 'tag'}]);
|
||||
rejectSpy.secondCall.args[0].should.eql([{op: '=', value: false, prop: 'page', func: 'and'}]);
|
||||
|
||||
findSpy.calledTwice.should.be.true();
|
||||
findSpy.firstCall.args.should.eql([
|
||||
[{op: '=', prop: 'status', value: 'published'}],
|
||||
{op: '=', prop: 'tag', value: 'photo'},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.secondCall.args.should.eql([
|
||||
[{op: '=', prop: 'tag', value: 'photo'}],
|
||||
{func: 'and', op: '=', prop: 'page', value: false},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle getting enforced, default and multiple custom filters', function () {
|
||||
combineFilters('status:published', 'page:false', 'tag:[photo,video],author:cameron', 'status:draft,page:false').should.eql({
|
||||
statements: [
|
||||
{
|
||||
group: [
|
||||
{prop: 'status', op: '=', value: 'published'}
|
||||
]
|
||||
},
|
||||
{
|
||||
group: [
|
||||
{prop: 'tag', op: 'IN', value: ['photo', 'video']},
|
||||
{prop: 'author', op: '=', value: 'cameron', func: 'or'},
|
||||
{prop: 'page', op: '=', value: false, func: 'or'}
|
||||
], func: 'and'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
parseSpy.callCount.should.eql(4);
|
||||
mergeSpy.calledTwice.should.be.true();
|
||||
rejectSpy.callCount.should.eql(2);
|
||||
rejectSpy.getCall(0).args[0].should.eql([{op: 'IN', value: ['photo', 'video'], prop: 'tag'},
|
||||
{op: '=', value: 'cameron', prop: 'author', func: 'or'},
|
||||
{op: '=', value: 'draft', prop: 'status', func: 'and'},
|
||||
{op: '=', value: false, prop: 'page', func: 'or'}]);
|
||||
rejectSpy.getCall(1).args[0].should.eql([{op: '=', value: false, prop: 'page'}]);
|
||||
|
||||
findSpy.callCount.should.eql(5);
|
||||
findSpy.getCall(0).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: 'IN', prop: 'tag', value: ['photo', 'video']},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.getCall(1).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{prop: 'author', op: '=', value: 'cameron', func: 'or'},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.getCall(2).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{op: '=', value: 'draft', prop: 'status', func: 'and'},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.getCall(3).args.should.eql([
|
||||
[{op: '=', value: 'published', prop: 'status'}],
|
||||
{prop: 'page', op: '=', value: false, func: 'or'},
|
||||
'prop'
|
||||
]);
|
||||
findSpy.getCall(4).args.should.eql([
|
||||
[
|
||||
{op: 'IN', value: ['photo', 'video'], prop: 'tag'},
|
||||
{op: '=', value: 'cameron', prop: 'author', func: 'or'},
|
||||
{op: '=', value: false, prop: 'page', func: 'or'}
|
||||
],
|
||||
{op: '=', value: false, prop: 'page'},
|
||||
'prop'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,21 +1,16 @@
|
||||
/* eslint no-invalid-this:0 */
|
||||
|
||||
const should = require('should'),
|
||||
url = require('url'),
|
||||
sinon = require('sinon'),
|
||||
_ = require('lodash'),
|
||||
Promise = require('bluebird'),
|
||||
testUtils = require('../../utils'),
|
||||
knex = require('../../../server/data/db').knex,
|
||||
db = require('../../../server/data/db'),
|
||||
urlService = require('../../../server/services/url'),
|
||||
schema = require('../../../server/data/schema'),
|
||||
models = require('../../../server/models'),
|
||||
common = require('../../../server/lib/common'),
|
||||
security = require('../../../server/lib/security'),
|
||||
sandbox = sinon.sandbox.create(),
|
||||
userIdFor = testUtils.users.ids,
|
||||
context = testUtils.context;
|
||||
const _ = require('lodash');
|
||||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const Promise = require('bluebird');
|
||||
const testUtils = require('../../utils');
|
||||
const knex = require('../../../server/data/db').knex;
|
||||
const urlService = require('../../../server/services/url');
|
||||
const schema = require('../../../server/data/schema');
|
||||
const models = require('../../../server/models');
|
||||
const common = require('../../../server/lib/common');
|
||||
const security = require('../../../server/lib/security');
|
||||
const sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('Unit: models/post', function () {
|
||||
const mockDb = require('mock-knex');
|
||||
@ -51,22 +46,22 @@ describe('Unit: models/post', function () {
|
||||
withRelated: ['tags']
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`tags`.`slug` in (?, ?) and `posts`.`id` != ?)');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` != ? and `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
testUtils.filterData.data.posts[3].id,
|
||||
'photo',
|
||||
'video',
|
||||
testUtils.filterData.data.posts[3].id
|
||||
false,
|
||||
'published'
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`tags`.`slug` in (?, ?) and `posts`.`id` != ?) group by `posts`.`id` order by count(tags.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where ((`posts`.`id` != ? and `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by (SELECT count(*) FROM posts_tags WHERE post_id = posts.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
testUtils.filterData.data.posts[3].id,
|
||||
'photo',
|
||||
'video',
|
||||
testUtils.filterData.data.posts[3].id,
|
||||
false,
|
||||
'published',
|
||||
3
|
||||
]);
|
||||
});
|
||||
@ -86,22 +81,22 @@ describe('Unit: models/post', function () {
|
||||
withRelated: ['authors', 'tags']
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` left outer join `posts_authors` on `posts_authors`.`post_id` = `posts`.`id` left outer join `users` as `authors` on `posts_authors`.`author_id` = `authors`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`authors`.`slug` in (?, ?) and (`tags`.`slug` = ? or `posts`.`feature_image` is not null))');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (((`posts`.`feature_image` is not null or `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` = ?)) and `posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` where `authors`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'hash-audio',
|
||||
'leslie',
|
||||
'pat',
|
||||
'hash-audio'
|
||||
false,
|
||||
'published'
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` left outer join `posts_authors` on `posts_authors`.`post_id` = `posts`.`id` left outer join `users` as `authors` on `posts_authors`.`author_id` = `authors`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`authors`.`slug` in (?, ?) and (`tags`.`slug` = ? or `posts`.`feature_image` is not null)) group by `posts`.`id`, `posts`.`id` order by count(authors.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where (((`posts`.`feature_image` is not null or `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` = ?)) and `posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` where `authors`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by (SELECT count(*) FROM posts_authors WHERE post_id = posts.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'hash-audio',
|
||||
'leslie',
|
||||
'pat',
|
||||
'hash-audio',
|
||||
false,
|
||||
'published',
|
||||
15
|
||||
]);
|
||||
});
|
||||
@ -122,18 +117,18 @@ describe('Unit: models/post', function () {
|
||||
withRelated: ['tags']
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`posts`.`published_at` > ?)');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (`posts`.`published_at` > ? and (`posts`.`page` = ? and `posts`.`status` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
'2015-07-20',
|
||||
false,
|
||||
'published',
|
||||
'2015-07-20'
|
||||
'published'
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where (`posts`.`page` = ? and `posts`.`status` = ?) and (`posts`.`published_at` > ?) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where (`posts`.`published_at` > ? and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].bindings.should.eql([
|
||||
'2015-07-20',
|
||||
false,
|
||||
'published',
|
||||
'2015-07-20',
|
||||
5
|
||||
]);
|
||||
});
|
||||
@ -154,22 +149,20 @@ describe('Unit: models/post', function () {
|
||||
withRelated: ['tags']
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and ((`tags`.`slug` = ? and `posts_tags`.`sort_order` = ? and `tags`.`visibility` = ?))');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` and `posts_tags`.`sort_order` = 0 where `tags`.`slug` = ? and `tags`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'photo',
|
||||
0,
|
||||
'public'
|
||||
'public',
|
||||
false,
|
||||
'published'
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` left outer join `posts_tags` on `posts_tags`.`post_id` = `posts`.`id` left outer join `tags` on `posts_tags`.`tag_id` = `tags`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and ((`tags`.`slug` = ? and `posts_tags`.`sort_order` = ? and `tags`.`visibility` = ?)) group by `posts`.`id` order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where ((`posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` and `posts_tags`.`sort_order` = 0 where `tags`.`slug` = ? and `tags`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].bindings.should.eql([
|
||||
'photo',
|
||||
'public',
|
||||
false,
|
||||
'published',
|
||||
'photo',
|
||||
0,
|
||||
'public',
|
||||
15
|
||||
]);
|
||||
});
|
||||
@ -189,22 +182,20 @@ describe('Unit: models/post', function () {
|
||||
withRelated: ['authors']
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` left outer join `posts_authors` on `posts_authors`.`post_id` = `posts`.`id` left outer join `users` as `authors` on `posts_authors`.`author_id` = `authors`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and ((`authors`.`slug` = ? and `posts_authors`.`sort_order` = ? and `authors`.`visibility` = ?))');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` and `posts_authors`.`sort_order` = 0 where `authors`.`slug` = ? and `authors`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'leslie',
|
||||
0,
|
||||
'public'
|
||||
'public',
|
||||
false,
|
||||
'published'
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` left outer join `posts_authors` on `posts_authors`.`post_id` = `posts`.`id` left outer join `users` as `authors` on `posts_authors`.`author_id` = `authors`.`id` where (`posts`.`page` = ? and `posts`.`status` = ?) and ((`authors`.`slug` = ? and `posts_authors`.`sort_order` = ? and `authors`.`visibility` = ?)) group by `posts`.`id` order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where ((`posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` and `posts_authors`.`sort_order` = 0 where `authors`.`slug` = ? and `authors`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?');
|
||||
queries[1].bindings.should.eql([
|
||||
'leslie',
|
||||
'public',
|
||||
false,
|
||||
'published',
|
||||
'leslie',
|
||||
0,
|
||||
'public',
|
||||
15
|
||||
]);
|
||||
});
|
||||
@ -234,20 +225,20 @@ describe('Unit: models/post', function () {
|
||||
}
|
||||
}).then(() => {
|
||||
queries.length.should.eql(2);
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (`posts`.`page` = ?) and (`posts`.`status` in (?, ?) and `posts`.`status` = ?)');
|
||||
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`page` = ?))');
|
||||
queries[0].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'draft',
|
||||
'published'
|
||||
'published',
|
||||
false,
|
||||
]);
|
||||
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where (`posts`.`page` = ?) and (`posts`.`status` in (?, ?) and `posts`.`status` = ?) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC');
|
||||
queries[1].sql.should.eql('select `posts`.* from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`page` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC');
|
||||
queries[1].bindings.should.eql([
|
||||
false,
|
||||
'published',
|
||||
'draft',
|
||||
'published'
|
||||
'published',
|
||||
false,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -761,25 +761,25 @@ DataGenerator.forKnex = (function () {
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[1].id,
|
||||
tag_id: DataGenerator.Content.tags[0].id,
|
||||
sort_order: 2
|
||||
sort_order: 0
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[1].id,
|
||||
tag_id: DataGenerator.Content.tags[1].id,
|
||||
sort_order: 3
|
||||
sort_order: 1
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[2].id,
|
||||
tag_id: DataGenerator.Content.tags[2].id,
|
||||
sort_order: 4
|
||||
sort_order: 0
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[3].id,
|
||||
tag_id: DataGenerator.Content.tags[3].id,
|
||||
sort_order: 5
|
||||
sort_order: 0
|
||||
}
|
||||
];
|
||||
|
||||
@ -820,6 +820,12 @@ DataGenerator.forKnex = (function () {
|
||||
author_id: DataGenerator.Content.users[0].id,
|
||||
sort_order: 0
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[4].id,
|
||||
author_id: _.find(DataGenerator.Content.users, {slug: 'slimer-mcectoplasm'}).id,
|
||||
sort_order: 1
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
post_id: DataGenerator.Content.posts[5].id,
|
||||
|
@ -32,7 +32,7 @@
|
||||
"cli": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nexes/nql": "0.1.0",
|
||||
"@nexes/nql": "0.2.1",
|
||||
"amperize": "0.3.8",
|
||||
"analytics-node": "2.4.1",
|
||||
"archiver": "1.3.0",
|
||||
@ -60,7 +60,6 @@
|
||||
"express-session": "1.15.6",
|
||||
"extract-zip": "1.6.7",
|
||||
"fs-extra": "3.0.1",
|
||||
"ghost-gql": "0.0.11",
|
||||
"ghost-ignition": "2.9.6",
|
||||
"ghost-storage-base": "0.0.3",
|
||||
"glob": "5.0.15",
|
||||
|
410
yarn.lock
410
yarn.lock
@ -2,21 +2,31 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@nexes/mongo-knex@0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/mongo-knex/-/mongo-knex-0.0.1.tgz#141c8ca380e95c1460fe2abcd777d7fd2bb14e8f"
|
||||
"@nexes/mongo-knex@0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/mongo-knex/-/mongo-knex-0.3.0.tgz#e0078f8ddf7fcd4d907fe5cf2390644218753cf0"
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
lodash "^4.17.10"
|
||||
|
||||
"@nexes/mongo-utils@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/mongo-utils/-/mongo-utils-0.2.0.tgz#28b483e88f2433ee269aa6b91f7339b7ab1e7d45"
|
||||
dependencies:
|
||||
bluebird "^3.5.3"
|
||||
ghost-ignition "^2.9.6"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@nexes/nql-lang@0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/nql-lang/-/nql-lang-0.0.1.tgz#a13c023873f9bc11b9e4e284449c6cfbeccc8011"
|
||||
|
||||
"@nexes/nql@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/nql/-/nql-0.1.0.tgz#b63614d5874bebb387b58d3f1b9fb9602115cf62"
|
||||
"@nexes/nql@0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@nexes/nql/-/nql-0.2.1.tgz#cc314f77d9fcbb0d321669db3dd74de880b0c694"
|
||||
dependencies:
|
||||
"@nexes/mongo-knex" "0.0.1"
|
||||
"@nexes/mongo-knex" "0.3.0"
|
||||
"@nexes/mongo-utils" "0.2.0"
|
||||
"@nexes/nql-lang" "0.0.1"
|
||||
mingo "2.2.2"
|
||||
|
||||
@ -27,11 +37,11 @@
|
||||
component-type "^1.2.1"
|
||||
join-component "^1.1.0"
|
||||
|
||||
"@sinonjs/formatio@3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.0.0.tgz#9d282d81030a03a03fa0c5ce31fd8786a4da311a"
|
||||
"@sinonjs/commons@^1.0.2":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.3.0.tgz#50a2754016b6f30a994ceda6d9a0a8c36adda849"
|
||||
dependencies:
|
||||
"@sinonjs/samsam" "2.1.0"
|
||||
type-detect "4.0.8"
|
||||
|
||||
"@sinonjs/formatio@^2.0.0":
|
||||
version "2.0.0"
|
||||
@ -39,11 +49,19 @@
|
||||
dependencies:
|
||||
samsam "1.3.0"
|
||||
|
||||
"@sinonjs/samsam@2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.1.0.tgz#b8b8f5b819605bd63601a6ede459156880f38ea3"
|
||||
"@sinonjs/formatio@^3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.1.0.tgz#6ac9d1eb1821984d84c4996726e45d1646d8cce5"
|
||||
dependencies:
|
||||
"@sinonjs/samsam" "^2 || ^3"
|
||||
|
||||
"@sinonjs/samsam@^2 || ^3":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.0.2.tgz#304fb33bd5585a0b2df8a4c801fcb47fa84d8e43"
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.0.2"
|
||||
array-from "^2.1.1"
|
||||
lodash.get "^4.4.2"
|
||||
|
||||
"@tryghost/extract-zip@1.6.6":
|
||||
version "1.6.6"
|
||||
@ -104,6 +122,15 @@ ajv@^5.2.3, ajv@^5.3.0:
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.3.0"
|
||||
|
||||
ajv@^6.5.5:
|
||||
version "6.6.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.1.tgz#6360f5ed0d80f232cc2b294c362d5dc2e538dd61"
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
align-text@^0.1.1, align-text@^0.1.3:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
|
||||
@ -155,7 +182,7 @@ analytics-node@2.4.1:
|
||||
|
||||
ansi-escapes@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
|
||||
resolved "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
@ -196,7 +223,7 @@ archiver-utils@^1.3.0:
|
||||
|
||||
archiver@1.3.0, archiver@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22"
|
||||
resolved "http://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22"
|
||||
dependencies:
|
||||
archiver-utils "^1.3.0"
|
||||
async "^2.0.0"
|
||||
@ -250,7 +277,7 @@ array-find-index@^1.0.1:
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
resolved "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
|
||||
array-from@^2.1.1:
|
||||
version "2.1.1"
|
||||
@ -260,13 +287,7 @@ array-slice@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
|
||||
|
||||
array-union@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
|
||||
dependencies:
|
||||
array-uniq "^1.0.1"
|
||||
|
||||
array-uniq@^1.0.1, array-uniq@^1.0.2:
|
||||
array-uniq@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
|
||||
|
||||
@ -274,10 +295,6 @@ array-unique@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||
|
||||
arrify@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
||||
|
||||
asn1@~0.2.3:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||
@ -547,10 +564,14 @@ block-stream@*:
|
||||
dependencies:
|
||||
inherits "~2.0.0"
|
||||
|
||||
bluebird@3.5.2, bluebird@^3.0.5, bluebird@^3.4.1, bluebird@^3.4.3, bluebird@^3.4.6, bluebird@^3.5.1:
|
||||
bluebird@3.5.2:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a"
|
||||
|
||||
bluebird@^3.0.5, bluebird@^3.4.1, bluebird@^3.4.3, bluebird@^3.4.6, bluebird@^3.5.1, bluebird@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
|
||||
|
||||
body-parser@1.18.3:
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
|
||||
@ -585,7 +606,7 @@ bookshelf-relations@0.2.1:
|
||||
|
||||
bookshelf@0.13.3:
|
||||
version "0.13.3"
|
||||
resolved "https://registry.yarnpkg.com/bookshelf/-/bookshelf-0.13.3.tgz#aa73d9159b6cac92830dc1ff37325490c3c6dfba"
|
||||
resolved "http://registry.npmjs.org/bookshelf/-/bookshelf-0.13.3.tgz#aa73d9159b6cac92830dc1ff37325490c3c6dfba"
|
||||
dependencies:
|
||||
babel-runtime "^6.26.0"
|
||||
bluebird "^3.4.3"
|
||||
@ -690,11 +711,11 @@ builtin-modules@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||
|
||||
bunyan-loggly@^1.3.1:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/bunyan-loggly/-/bunyan-loggly-1.3.5.tgz#857bbabe9a2f26c3b03eeab1db9e86c092227bde"
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/bunyan-loggly/-/bunyan-loggly-1.4.0.tgz#a10b61d7b32422e1c648031185d8e0413427db8f"
|
||||
dependencies:
|
||||
json-stringify-safe "^5.0.1"
|
||||
node-loggly-bulk "^2.2.2"
|
||||
node-loggly-bulk "^2.2.4"
|
||||
|
||||
bunyan@1.8.12:
|
||||
version "1.8.12"
|
||||
@ -746,7 +767,7 @@ caller@1.0.1:
|
||||
|
||||
callsites@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
|
||||
resolved "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
|
||||
|
||||
camelcase-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
@ -773,8 +794,8 @@ caniuse-api@^1.5.2:
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000899"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000899.tgz#f66d667d507c2aa19603a4a3763d71aa89cc360f"
|
||||
version "1.0.30000918"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000918.tgz#650a34372ced440a79fa600644667802c6a4b9c2"
|
||||
|
||||
caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
@ -853,7 +874,7 @@ cheerio@0.22.0:
|
||||
lodash.reject "^4.4.0"
|
||||
lodash.some "^4.4.0"
|
||||
|
||||
chownr@^1.0.1:
|
||||
chownr@^1.0.1, chownr@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
||||
|
||||
@ -930,7 +951,7 @@ code-point-at@^1.0.0:
|
||||
|
||||
coffee-script@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4"
|
||||
resolved "http://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4"
|
||||
|
||||
coffeescript@~1.10.0:
|
||||
version "1.10.0"
|
||||
@ -959,7 +980,7 @@ color-name@^1.0.0:
|
||||
|
||||
color-string@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
|
||||
resolved "http://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
|
||||
dependencies:
|
||||
color-name "^1.0.0"
|
||||
|
||||
@ -995,19 +1016,19 @@ colormin@^1.0.5:
|
||||
|
||||
colors@0.5.x:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
|
||||
resolved "http://registry.npmjs.org/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
|
||||
|
||||
colors@^1.1.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b"
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
|
||||
|
||||
colors@~0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc"
|
||||
resolved "http://registry.npmjs.org/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc"
|
||||
|
||||
colors@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
||||
resolved "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.7"
|
||||
@ -1166,8 +1187,8 @@ copy-descriptor@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||
|
||||
core-js@^2.4.0, core-js@^2.5.0:
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4"
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
@ -1333,6 +1354,12 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87"
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
@ -1388,18 +1415,6 @@ defined@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
|
||||
del@^2.0.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
|
||||
dependencies:
|
||||
globby "^5.0.0"
|
||||
is-path-cwd "^1.0.0"
|
||||
is-path-in-cwd "^1.0.0"
|
||||
object-assign "^4.0.1"
|
||||
pify "^2.0.0"
|
||||
pinkie-promise "^2.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
@ -1488,13 +1503,9 @@ dom-serializer@0, dom-serializer@~0.1.0:
|
||||
domelementtype "~1.1.1"
|
||||
entities "~1.1.1"
|
||||
|
||||
domelementtype@1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.2.1.tgz#578558ef23befac043a1abb0db07635509393479"
|
||||
|
||||
domelementtype@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
|
||||
domelementtype@1, domelementtype@^1.3.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||
|
||||
domelementtype@~1.1.1:
|
||||
version "1.1.3"
|
||||
@ -1574,10 +1585,10 @@ ee-first@1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
||||
electron-to-chromium@^1.2.7:
|
||||
version "1.3.82"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz#7d13ae4437d2a783de3f4efba96b186c540b67b1"
|
||||
version "1.3.90"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.90.tgz#b4c51b8303beff18f2b74817402bf4898e09558a"
|
||||
|
||||
ember-rfc176-data@^0.3.3:
|
||||
ember-rfc176-data@^0.3.5:
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.5.tgz#f630e550572c81a5e5c7220f864c0f06eee9e977"
|
||||
|
||||
@ -1662,10 +1673,10 @@ escodegen@^1.8.1:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-plugin-ember@^5.0.3:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-5.2.0.tgz#fa436e0497dfc01d1d38608229cd616e7c5b6067"
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-5.4.0.tgz#2980a4389119b37d0450fff8e82d59c9aab126d0"
|
||||
dependencies:
|
||||
ember-rfc176-data "^0.3.3"
|
||||
ember-rfc176-data "^0.3.5"
|
||||
snake-case "^2.1.0"
|
||||
|
||||
eslint-plugin-ghost@0.0.27:
|
||||
@ -1818,6 +1829,10 @@ expand-template@^1.0.2:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.1.tgz#981f188c0c3a87d2e28f559bc541426ff94f21dd"
|
||||
|
||||
expand-template@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
|
||||
expand-tilde@^2.0.0, expand-tilde@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
|
||||
@ -1924,7 +1939,7 @@ extend@^3.0.0, extend@~3.0.2:
|
||||
|
||||
extendr@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.0.1.tgz#d8ab375fcbb833e4ba2cd228540f04e4aa07de90"
|
||||
resolved "http://registry.npmjs.org/extendr/-/extendr-2.0.1.tgz#d8ab375fcbb833e4ba2cd228540f04e4aa07de90"
|
||||
dependencies:
|
||||
typechecker "~2.0.1"
|
||||
|
||||
@ -1970,6 +1985,10 @@ fast-deep-equal@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
|
||||
|
||||
fast-deep-equal@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
@ -2076,8 +2095,8 @@ findup-sync@~0.3.0:
|
||||
glob "~5.0.0"
|
||||
|
||||
fined@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.1.tgz#95d88ff329123dd1a6950fdfcd321f746271e01f"
|
||||
dependencies:
|
||||
expand-tilde "^2.0.2"
|
||||
is-plain-object "^2.0.3"
|
||||
@ -2090,12 +2109,12 @@ flagged-respawn@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7"
|
||||
|
||||
flat-cache@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f"
|
||||
dependencies:
|
||||
circular-json "^0.3.1"
|
||||
del "^2.0.2"
|
||||
graceful-fs "^4.1.2"
|
||||
rimraf "~2.6.2"
|
||||
write "^0.2.1"
|
||||
|
||||
flatten@^1.0.2:
|
||||
@ -2166,7 +2185,7 @@ fs-extra@3.0.1, fs-extra@^3.0.1:
|
||||
|
||||
fs-extra@^0.26.2:
|
||||
version "0.26.7"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9"
|
||||
resolved "http://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^2.1.0"
|
||||
@ -2262,12 +2281,6 @@ getsetdeep@~2.0.0:
|
||||
dependencies:
|
||||
typechecker "~2.0.1"
|
||||
|
||||
ghost-gql@0.0.11:
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ghost-gql/-/ghost-gql-0.0.11.tgz#f0bc85305d0be80e5131011bf48b0ffd7c058b6b"
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
|
||||
ghost-ignition@2.9.2:
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/ghost-ignition/-/ghost-ignition-2.9.2.tgz#e68de88fa4a20fc09c833fe3278bdc20dca6d525"
|
||||
@ -2285,7 +2298,7 @@ ghost-ignition@2.9.2:
|
||||
prettyjson "^1.1.3"
|
||||
uuid "^3.0.0"
|
||||
|
||||
ghost-ignition@2.9.6:
|
||||
ghost-ignition@2.9.6, ghost-ignition@^2.9.6:
|
||||
version "2.9.6"
|
||||
resolved "https://registry.yarnpkg.com/ghost-ignition/-/ghost-ignition-2.9.6.tgz#cc8358f0a356bae490e5abeca3c3bda8383352fe"
|
||||
dependencies:
|
||||
@ -2410,24 +2423,13 @@ global-prefix@^1.0.1:
|
||||
which "^1.2.14"
|
||||
|
||||
globals@^11.0.1:
|
||||
version "11.8.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d"
|
||||
version "11.9.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249"
|
||||
|
||||
globals@^9.18.0:
|
||||
version "9.18.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||
|
||||
globby@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
|
||||
dependencies:
|
||||
array-union "^1.0.1"
|
||||
arrify "^1.0.0"
|
||||
glob "^7.0.3"
|
||||
object-assign "^4.0.1"
|
||||
pify "^2.0.0"
|
||||
pinkie-promise "^2.0.0"
|
||||
|
||||
globule@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
|
||||
@ -2456,12 +2458,12 @@ got@7.1.0, got@^7.1.0:
|
||||
url-to-options "^1.0.1"
|
||||
|
||||
graceful-fs@^4.1.0, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||
version "4.1.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
||||
version "4.1.15"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||
|
||||
graceful-fs@~1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
|
||||
resolved "http://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
|
||||
|
||||
"graceful-readlink@>= 1.0.0":
|
||||
version "1.0.1"
|
||||
@ -2491,7 +2493,7 @@ grunt-cli@1.3.1:
|
||||
|
||||
grunt-cli@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8"
|
||||
resolved "http://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8"
|
||||
dependencies:
|
||||
findup-sync "~0.3.0"
|
||||
grunt-known-options "~1.1.0"
|
||||
@ -2684,7 +2686,7 @@ grunt@1.0.3:
|
||||
|
||||
grunt@~0.4.0:
|
||||
version "0.4.5"
|
||||
resolved "https://registry.yarnpkg.com/grunt/-/grunt-0.4.5.tgz#56937cd5194324adff6d207631832a9d6ba4e7f0"
|
||||
resolved "http://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz#56937cd5194324adff6d207631832a9d6ba4e7f0"
|
||||
dependencies:
|
||||
async "~0.1.22"
|
||||
coffee-script "~1.3.3"
|
||||
@ -2759,10 +2761,10 @@ har-schema@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
|
||||
har-validator@~5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29"
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
|
||||
dependencies:
|
||||
ajv "^5.3.0"
|
||||
ajv "^6.5.5"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
has-ansi@^2.0.0:
|
||||
@ -3174,22 +3176,6 @@ is-object@^1.0.1, is-object@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
|
||||
|
||||
is-path-cwd@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
||||
|
||||
is-path-in-cwd@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
|
||||
dependencies:
|
||||
is-path-inside "^1.0.0"
|
||||
|
||||
is-path-inside@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
|
||||
dependencies:
|
||||
path-is-inside "^1.0.1"
|
||||
|
||||
is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
@ -3381,12 +3367,16 @@ jsbn@~0.1.0:
|
||||
|
||||
jsesc@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
|
||||
resolved "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
|
||||
|
||||
json-schema-traverse@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
@ -3623,14 +3613,14 @@ liftoff@2.5.0, liftoff@~2.5.0:
|
||||
resolve "^1.1.7"
|
||||
|
||||
linkify-it@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db"
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
livereload-js@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.3.0.tgz#c3ab22e8aaf5bf3505d80d098cbad67726548c9a"
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c"
|
||||
|
||||
load-json-file@^1.0.0:
|
||||
version "1.1.0"
|
||||
@ -3825,7 +3815,7 @@ lodash@4.17.10:
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
|
||||
|
||||
lodash@4.17.11, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.7.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.5:
|
||||
lodash@4.17.11, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.7.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.5:
|
||||
version "4.17.11"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
|
||||
|
||||
@ -3876,17 +3866,17 @@ lowercase-keys@^1.0.0:
|
||||
|
||||
lru-cache@2:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
||||
resolved "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
||||
|
||||
lru-cache@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee"
|
||||
resolved "http://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee"
|
||||
dependencies:
|
||||
pseudomap "^1.0.1"
|
||||
|
||||
lru-cache@^4.0.0, lru-cache@^4.0.1:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
dependencies:
|
||||
pseudomap "^1.0.2"
|
||||
yallist "^2.1.2"
|
||||
@ -4044,7 +4034,7 @@ mime@^1.4.1:
|
||||
|
||||
mime@~1.2.11:
|
||||
version "1.2.11"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10"
|
||||
resolved "http://registry.npmjs.org/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10"
|
||||
|
||||
mimelib@~0.2.15:
|
||||
version "0.2.19"
|
||||
@ -4097,16 +4087,16 @@ minimist@~0.0.1:
|
||||
version "0.0.10"
|
||||
resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||
|
||||
minipass@^2.2.1, minipass@^2.3.3:
|
||||
minipass@^2.2.1, minipass@^2.3.4:
|
||||
version "2.3.5"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848"
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minizlib@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42"
|
||||
minizlib@^1.1.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614"
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
@ -4315,10 +4305,10 @@ netjet@1.3.0:
|
||||
posthtml "^0.9.0"
|
||||
|
||||
nise@^1.2.0:
|
||||
version "1.4.6"
|
||||
resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.6.tgz#76cc3915925056ae6c405dd8ad5d12bde570c19f"
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.7.tgz#180d723df5071a3d3fc0e83fe8eb0c02b7db1f59"
|
||||
dependencies:
|
||||
"@sinonjs/formatio" "3.0.0"
|
||||
"@sinonjs/formatio" "^3.1.0"
|
||||
just-extend "^3.0.0"
|
||||
lolex "^2.3.2"
|
||||
path-to-regexp "^1.7.0"
|
||||
@ -4345,14 +4335,14 @@ nock@9.4.0:
|
||||
semver "^5.5.0"
|
||||
|
||||
node-abi@^2.2.0:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.4.5.tgz#1fd1fb66641bf3c4dcf55a5490ba10c467ead80c"
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.5.0.tgz#942e1a78bce764bc0c1672d5821e492b9d032052"
|
||||
dependencies:
|
||||
semver "^5.4.1"
|
||||
|
||||
node-fetch@^2.1.2:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.2.0.tgz#4ee79bde909262f9775f731e3656d0db55ced5b5"
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5"
|
||||
|
||||
node-forge@^0.7.6:
|
||||
version "0.7.6"
|
||||
@ -4395,7 +4385,7 @@ node-jose@1.1.0:
|
||||
node-forge "^0.7.6"
|
||||
uuid "^3.3.2"
|
||||
|
||||
node-loggly-bulk@^2.2.2:
|
||||
node-loggly-bulk@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/node-loggly-bulk/-/node-loggly-bulk-2.2.4.tgz#bdd8638d97c43ecf1e1831ca98b250968fa6dee9"
|
||||
dependencies:
|
||||
@ -4634,7 +4624,7 @@ optionator@^0.8.1, optionator@^0.8.2:
|
||||
|
||||
os-homedir@^1.0.0, os-homedir@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||
resolved "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||
|
||||
os-locale@^1.4.0:
|
||||
version "1.4.0"
|
||||
@ -4644,7 +4634,7 @@ os-locale@^1.4.0:
|
||||
|
||||
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
resolved "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
|
||||
osenv@0, osenv@^0.1.4:
|
||||
version "0.1.5"
|
||||
@ -4669,7 +4659,7 @@ p-timeout@^1.1.1:
|
||||
|
||||
pako@~0.2.0:
|
||||
version "0.2.9"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||
resolved "http://registry.npmjs.org/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||
|
||||
parse-filepath@^1.0.1:
|
||||
version "1.0.2"
|
||||
@ -4728,9 +4718,9 @@ path-exists@^2.0.0:
|
||||
|
||||
path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
resolved "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
|
||||
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
|
||||
path-is-inside@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
||||
|
||||
@ -5076,11 +5066,11 @@ prebuild-install@^2.3.0:
|
||||
which-pm-runs "^1.0.0"
|
||||
|
||||
prebuild-install@^5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.1.tgz#87ba8cf17c65360a75eefeb3519e87973bf9791d"
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.2.tgz#237888f21bfda441d0ee5f5612484390bccd4046"
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
expand-template "^1.0.2"
|
||||
expand-template "^2.0.3"
|
||||
github-from-package "0.0.0"
|
||||
minimist "^1.2.0"
|
||||
mkdirp "^0.5.1"
|
||||
@ -5106,14 +5096,14 @@ prepend-http@^1.0.0, prepend-http@^1.0.1:
|
||||
|
||||
pretty-bytes@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84"
|
||||
resolved "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84"
|
||||
dependencies:
|
||||
get-stdin "^4.0.1"
|
||||
meow "^3.1.0"
|
||||
|
||||
pretty-bytes@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
|
||||
resolved "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
|
||||
|
||||
prettyjson@^1.1.3:
|
||||
version "1.2.1"
|
||||
@ -5131,8 +5121,8 @@ process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
|
||||
|
||||
progress@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31"
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
|
||||
promise-wtf@^1.2.4:
|
||||
version "1.2.4"
|
||||
@ -5191,6 +5181,10 @@ punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
|
||||
punycode@~1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.2.4.tgz#54008ac972aec74175def9cba6df7fa9d3918740"
|
||||
@ -5208,10 +5202,14 @@ q@^1.1.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
||||
qs@6.5.2, qs@^6.4.0, qs@^6.5.1, qs@~6.5.2:
|
||||
qs@6.5.2, qs@~6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
|
||||
qs@^6.4.0, qs@^6.5.1:
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2"
|
||||
|
||||
query-string@^4.1.0:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
|
||||
@ -5280,7 +5278,7 @@ readable-stream@1.1.x, readable-stream@~1.1.9:
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@2.3.6, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5:
|
||||
readable-stream@2.3.6, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
dependencies:
|
||||
@ -5413,7 +5411,7 @@ require-dir@^0.3.2:
|
||||
|
||||
require-uncached@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
|
||||
resolved "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
|
||||
dependencies:
|
||||
caller-path "^0.1.0"
|
||||
resolve-from "^1.0.0"
|
||||
@ -5435,11 +5433,11 @@ resolve-url@^0.2.1:
|
||||
|
||||
resolve@1.1.x, resolve@~1.1.0:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
resolved "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
|
||||
resolve@1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
|
||||
resolved "http://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
@ -5526,7 +5524,7 @@ safe-json-stringify@~1:
|
||||
|
||||
safe-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
|
||||
resolved "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
|
||||
dependencies:
|
||||
ret "~0.1.10"
|
||||
|
||||
@ -5721,7 +5719,7 @@ simple-concat@^1.0.0:
|
||||
|
||||
simple-dom@0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/simple-dom/-/simple-dom-0.3.2.tgz#0663d10f1556f1500551d518f56e3aba0871371d"
|
||||
resolved "http://registry.npmjs.org/simple-dom/-/simple-dom-0.3.2.tgz#0663d10f1556f1500551d518f56e3aba0871371d"
|
||||
|
||||
simple-get@^2.7.0:
|
||||
version "2.8.1"
|
||||
@ -5843,7 +5841,7 @@ source-map-url@^0.4.0:
|
||||
|
||||
source-map@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
|
||||
resolved "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
@ -5857,13 +5855,13 @@ source-map@^0.6.1, source-map@~0.6.1:
|
||||
|
||||
source-map@~0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
|
||||
resolved "http://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
spdx-correct@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e"
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
|
||||
dependencies:
|
||||
spdx-expression-parse "^3.0.0"
|
||||
spdx-license-ids "^3.0.0"
|
||||
@ -5880,8 +5878,8 @@ spdx-expression-parse@^3.0.0:
|
||||
spdx-license-ids "^3.0.0"
|
||||
|
||||
spdx-license-ids@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f"
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2"
|
||||
|
||||
split-string@^3.0.1, split-string@^3.0.2:
|
||||
version "3.1.0"
|
||||
@ -5896,14 +5894,14 @@ split2@^2.1.0:
|
||||
through2 "^2.0.2"
|
||||
|
||||
sprintf-js@^1.0.3:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
resolved "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
||||
sqlite3@4.0.3, sqlite3@^4.0.0:
|
||||
sqlite3@4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-4.0.3.tgz#da8c167a87941657fd22e27b248aa371e192b715"
|
||||
dependencies:
|
||||
@ -5911,6 +5909,14 @@ sqlite3@4.0.3, sqlite3@^4.0.0:
|
||||
node-pre-gyp "^0.10.3"
|
||||
request "^2.87.0"
|
||||
|
||||
sqlite3@^4.0.0:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-4.0.4.tgz#1f75e3ededad6e26f7dd819929460ce44a49dfcd"
|
||||
dependencies:
|
||||
nan "~2.10.0"
|
||||
node-pre-gyp "^0.10.3"
|
||||
request "^2.87.0"
|
||||
|
||||
sqlstring@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
|
||||
@ -5923,8 +5929,8 @@ srcset@^1.0.0:
|
||||
number-is-nan "^1.0.0"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2"
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629"
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
@ -5994,11 +6000,17 @@ string-width@^1.0.1:
|
||||
|
||||
string_decoder@0.10, string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
resolved "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
|
||||
string_decoder@^1.1.1, string_decoder@~1.1.1:
|
||||
string_decoder@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
resolved "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
@ -6130,20 +6142,20 @@ tar-stream@^1.1.2, tar-stream@^1.5.0:
|
||||
|
||||
tar@^2.0.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
|
||||
resolved "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
|
||||
dependencies:
|
||||
block-stream "*"
|
||||
fstream "^1.0.2"
|
||||
inherits "2"
|
||||
|
||||
tar@^4, tar@^4.4.6:
|
||||
version "4.4.6"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b"
|
||||
version "4.4.8"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
|
||||
dependencies:
|
||||
chownr "^1.0.1"
|
||||
chownr "^1.1.1"
|
||||
fs-minipass "^1.2.5"
|
||||
minipass "^2.3.3"
|
||||
minizlib "^1.1.0"
|
||||
minipass "^2.3.4"
|
||||
minizlib "^1.1.1"
|
||||
mkdirp "^0.5.0"
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.2"
|
||||
@ -6168,15 +6180,15 @@ text-table@~0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
||||
through2@^2.0.2, through2@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
|
||||
dependencies:
|
||||
readable-stream "^2.1.5"
|
||||
readable-stream "~2.3.6"
|
||||
xtend "~4.0.1"
|
||||
|
||||
through2@~0.2.1:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"
|
||||
resolved "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"
|
||||
dependencies:
|
||||
readable-stream "~1.1.9"
|
||||
xtend "~2.1.1"
|
||||
@ -6273,7 +6285,7 @@ type-check@~0.3.2:
|
||||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
type-detect@^4.0.0, type-detect@^4.0.5:
|
||||
type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||
|
||||
@ -6366,15 +6378,15 @@ underscore@, underscore@^1.8.3:
|
||||
|
||||
underscore@1.1.x:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.1.7.tgz#40bab84bad19d230096e8d6ef628bff055d83db0"
|
||||
resolved "http://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz#40bab84bad19d230096e8d6ef628bff055d83db0"
|
||||
|
||||
underscore@1.7.0, underscore@~1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
resolved "http://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
|
||||
underscore@~1.8.3:
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
|
||||
resolved "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
|
||||
|
||||
unidecode@0.1.8:
|
||||
version "0.1.8"
|
||||
@ -6412,6 +6424,12 @@ unset-value@^1.0.0:
|
||||
has-value "^0.3.1"
|
||||
isobject "^3.0.0"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
uri-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uri-path/-/uri-path-1.0.0.tgz#9747f018358933c31de0fccfd82d138e67262e32"
|
||||
@ -6495,7 +6513,7 @@ walkdir@^0.0.11:
|
||||
|
||||
watchr@~2.3.3:
|
||||
version "2.3.10"
|
||||
resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.3.10.tgz#2fe0af537071cae6a776d4523356f8f3a230b7ce"
|
||||
resolved "http://registry.npmjs.org/watchr/-/watchr-2.3.10.tgz#2fe0af537071cae6a776d4523356f8f3a230b7ce"
|
||||
dependencies:
|
||||
bal-util "~1.18.0"
|
||||
|
||||
@ -6612,8 +6630,8 @@ yallist@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|
||||
|
||||
yallist@^3.0.0, yallist@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
|
||||
|
||||
yargs@^3.19.0:
|
||||
version "3.32.0"
|
||||
|
Loading…
Reference in New Issue
Block a user