New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@cubejs-backend/api-gateway

Package Overview
Dependencies
Maintainers
2
Versions
589
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cubejs-backend/api-gateway - npm Package Compare versions

Comparing version 0.10.62 to 0.11.0

LocalSubscriptionStore.js

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

# [0.11.0](https://github.com/statsbotco/cubejs-client/compare/v0.10.62...v0.11.0) (2019-10-15)
### Features
* Sockets Preview ([#231](https://github.com/statsbotco/cubejs-client/issues/231)) ([89fc762](https://github.com/statsbotco/cubejs-client/commit/89fc762)), closes [#221](https://github.com/statsbotco/cubejs-client/issues/221)
## [0.10.62](https://github.com/statsbotco/cubejs-client/compare/v0.10.61...v0.10.62) (2019-10-11)

@@ -8,0 +19,0 @@

14

dateParser.js

@@ -8,4 +8,4 @@ const chrono = require('chrono-node');

dateString = dateString.toLowerCase();
if (dateString.match(/(this|last)\s+(day|week|month|year|quarter)/)) {
const match = dateString.match(/(this|last)\s+(day|week|month|year|quarter)/);
if (dateString.match(/(this|last)\s+(day|week|month|year|quarter|hour|minute|second)/)) {
const match = dateString.match(/(this|last)\s+(day|week|month|year|quarter|hour|minute|second)/);
let start = moment();

@@ -19,4 +19,4 @@ let end = moment();

momentRange = [start.startOf(span), end.endOf(span)];
} else if (dateString.match(/last\s+(\d+)\s+(day|week|month|year|quarter)/)) {
const match = dateString.match(/last\s+(\d+)\s+(day|week|month|year|quarter)/);
} else if (dateString.match(/last\s+(\d+)\s+(day|week|month|year|quarter|hour|minute|second)/)) {
const match = dateString.match(/last\s+(\d+)\s+(day|week|month|year|quarter|hour|minute|second)/);
const span = match[2] === 'week' ? 'isoWeek' : match[2];

@@ -28,6 +28,6 @@ momentRange = [

} else if (dateString.match(/today/)) {
momentRange = [moment(), moment()];
momentRange = [moment().startOf('day'), moment().endOf('day')];
} else if (dateString.match(/yesterday/)) {
const yesterday = moment().add(-1, 'day');
momentRange = [yesterday, yesterday];
momentRange = [yesterday.startOf('day'), yesterday.endOf('day')];
} else {

@@ -46,3 +46,3 @@ const results = chrono.parse(dateString);

}
return momentRange.map(d => d.format(moment.HTML5_FMT.DATE));
return momentRange.map(d => d.format(moment.HTML5_FMT.DATETIME_LOCAL_MS));
};

@@ -8,2 +8,4 @@ const jwt = require('jsonwebtoken');

const UserError = require('./UserError');
const SubscriptionServer = require('./SubscriptionServer');
const LocalSubscriptionStore = require('./LocalSubscriptionStore');

@@ -220,3 +222,3 @@ const toConfigMap = (metaConfig) => (

const coerceForSqlQuery = (query, req) => ({
const coerceForSqlQuery = (query, context) => ({
...query,

@@ -226,3 +228,3 @@ timeDimensions: (query.timeDimensions || [])

contextSymbols: {
userContext: req.authInfo && req.authInfo.u || {}
userContext: context.authInfo && context.authInfo.u || {}
}

@@ -239,5 +241,7 @@ });

this.checkAuthMiddleware = options.checkAuthMiddleware || this.checkAuth.bind(this);
this.checkAuthFn = options.checkAuth || this.defaultCheckAuth.bind(this);
this.basePath = options.basePath || '/cubejs-api';
// eslint-disable-next-line no-unused-vars
this.queryTransformer = options.queryTransformer || (async (query, context) => query);
this.subscriptionStore = options.subscriptionStore || new LocalSubscriptionStore();
}

@@ -247,77 +251,168 @@

app.get(`${this.basePath}/v1/load`, this.checkAuthMiddleware, (async (req, res) => {
try {
if (!req.query.query || req.query.query === 'undefined') {
throw new UserError(`query param is required`);
}
const query = JSON.parse(req.query.query);
this.log(req, {
type: 'Load Request',
query: req.query.query
});
const normalizedQuery = await this.queryTransformer(normalizeQuery(query), this.contextByReq(req));
const [compilerSqlResult, metaConfigResult] = await Promise.all([
this.getCompilerApi(req).getSql(coerceForSqlQuery(normalizedQuery, req)),
this.getCompilerApi(req).metaConfig()
]);
const sqlQuery = compilerSqlResult;
const metaConfig = metaConfigResult;
const annotation = prepareAnnotation(metaConfig, normalizedQuery);
const aliasToMemberNameMap = prepareAliasToMemberNameMap(metaConfig, sqlQuery, normalizedQuery);
const toExecute = {
...sqlQuery,
query: sqlQuery.sql[0],
values: sqlQuery.sql[1],
continueWait: true,
renewQuery: normalizedQuery.renewQuery
};
const response = await this.getAdapterApi(req).executeQuery(toExecute);
this.log(req, {
type: 'Load Request Success',
query: req.query.query,
});
const flattenAnnotation = {
...annotation.measures,
...annotation.dimensions,
...annotation.timeDimensions
};
res.json({
query: normalizedQuery,
data: transformData(aliasToMemberNameMap, flattenAnnotation, response.data),
annotation
});
} catch (e) {
this.handleError(e, req, res);
}
await this.load({
query: req.query.query,
context: this.contextByReq(req),
res: this.resToResultFn(res)
});
}));
app.get(`${this.basePath}/v1/subscribe`, this.checkAuthMiddleware, (async (req, res) => {
await this.load({
query: req.query.query,
context: this.contextByReq(req),
res: this.resToResultFn(res)
});
}));
app.get(`${this.basePath}/v1/sql`, this.checkAuthMiddleware, (async (req, res) => {
try {
if (!req.query.query || req.query.query === 'undefined') {
throw new UserError(`query param is required`);
}
const query = JSON.parse(req.query.query);
const normalizedQuery = await this.queryTransformer(normalizeQuery(query), this.contextByReq(req));
const sqlQuery = await this.getCompilerApi(req).getSql(coerceForSqlQuery(normalizedQuery, req));
res.json({
sql: sqlQuery
});
} catch (e) {
this.handleError(e, req, res);
}
await this.sql({
query: req.query.query,
context: this.contextByReq(req),
res: this.resToResultFn(res)
});
}));
app.get(`${this.basePath}/v1/meta`, this.checkAuthMiddleware, (async (req, res) => {
try {
const metaConfig = await this.getCompilerApi(req).metaConfig();
const cubes = metaConfig.map(c => c.config);
res.json({ cubes });
} catch (e) {
this.handleError(e, req, res);
}
await this.meta({
context: this.contextByReq(req),
res: this.resToResultFn(res)
});
}));
}
getCompilerApi(req) {
initSubscriptionServer(sendMessage) {
return new SubscriptionServer(this, sendMessage, this.subscriptionStore);
}
async meta({ context, res }) {
try {
const metaConfig = await this.getCompilerApi(context).metaConfig();
const cubes = metaConfig.map(c => c.config);
res({ cubes });
} catch (e) {
this.handleError({
e, context, res
});
}
}
async sql({ query, context, res }) {
try {
query = this.parseQueryParam(query);
const normalizedQuery = await this.queryTransformer(normalizeQuery(query), context);
const sqlQuery = await this.getCompilerApi(context).getSql(coerceForSqlQuery(normalizedQuery, context));
res.json({
sql: sqlQuery
});
} catch (e) {
this.handleError({
e, context, query, res
});
}
}
async load({ query, context, res }) {
try {
query = this.parseQueryParam(query);
this.log(context, {
type: 'Load Request',
query
});
const normalizedQuery = await this.queryTransformer(normalizeQuery(query), context);
const [compilerSqlResult, metaConfigResult] = await Promise.all([
this.getCompilerApi(context).getSql(coerceForSqlQuery(normalizedQuery, context)),
this.getCompilerApi(context).metaConfig()
]);
const sqlQuery = compilerSqlResult;
const metaConfig = metaConfigResult;
const annotation = prepareAnnotation(metaConfig, normalizedQuery);
const aliasToMemberNameMap = prepareAliasToMemberNameMap(metaConfig, sqlQuery, normalizedQuery);
const toExecute = {
...sqlQuery,
query: sqlQuery.sql[0],
values: sqlQuery.sql[1],
continueWait: true,
renewQuery: normalizedQuery.renewQuery
};
const response = await this.getAdapterApi(context).executeQuery(toExecute);
this.log(context, {
type: 'Load Request Success',
query,
});
const flattenAnnotation = {
...annotation.measures,
...annotation.dimensions,
...annotation.timeDimensions
};
res({
query: normalizedQuery,
data: transformData(aliasToMemberNameMap, flattenAnnotation, response.data),
annotation
});
} catch (e) {
this.handleError({
e, context, query, res
});
}
}
async subscribe({
query, context, res, subscribe, subscriptionState
}) {
try {
this.log(context, {
type: 'Subscribe',
query
});
let result = null;
let error = null;
if (!subscribe) {
await this.load({ query, context, res });
return;
}
// TODO subscribe to refreshKeys instead of constantly firing load
await this.load({
query,
context,
res: (message) => {
if (message.error) {
error = message;
} else {
result = message;
}
}
});
const state = await subscriptionState();
if (result && (!state || JSON.stringify(state.result) !== JSON.stringify(result))) {
res(result);
} else if (error) {
res(error);
}
await subscribe({ error, result });
} catch (e) {
this.handleError({
e, context, query, res
});
}
}
resToResultFn(res) {
return (message, { status } = {}) => (status ? res.status(status).json(message) : res.json(message));
}
parseQueryParam(query) {
if (!query || query === 'undefined') {
throw new UserError(`query param is required`);
}
if (typeof query === 'string') {
query = JSON.parse(query);
}
return query;
}
getCompilerApi(context) {
if (typeof this.compilerApi === 'function') {
return this.compilerApi(this.contextByReq(req));
return this.compilerApi(context);
}

@@ -327,5 +422,5 @@ return this.compilerApi;

getAdapterApi(req) {
getAdapterApi(context) {
if (typeof this.adapterApi === 'function') {
return this.adapterApi(this.contextByReq(req));
return this.adapterApi(context);
}

@@ -339,37 +434,37 @@ return this.adapterApi;

handleError(e, req, res) {
handleError({
e, context, query, res
}) {
if (e instanceof UserError) {
this.log(req, {
this.log(context, {
type: 'User Error',
query: req.query && req.query.query,
query,
error: e.message
});
res.status(400).json({ error: e.message });
res({ error: e.message }, { status: 400 });
} else if (e.error === 'Continue wait') {
this.log(req, {
this.log(context, {
type: 'Continue wait',
query: req.query && req.query.query,
query,
error: e.message
});
res.status(200).json(e);
res(e, { status: 200 });
} else if (e.error) {
this.log(req, {
this.log(context, {
type: 'Orchestrator error',
query: req.query && req.query.query,
query,
error: e.error
});
res.status(400).json(e);
res(e, { status: 400 });
} else {
this.log(req, {
this.log(context, {
type: 'Internal Server Error',
query: req.query && req.query.query,
query,
error: e.stack || e.toString()
});
res.status(500).json({ error: e.toString() });
res({ error: e.toString() }, { status: 500 });
}
}
async checkAuth(req, res, next) {
const auth = req.headers.authorization;
async defaultCheckAuth(req, auth) {
if (auth) {

@@ -379,6 +474,5 @@ const secret = this.apiSecret;

req.authInfo = jwt.verify(auth, secret);
return next && next();
} catch (e) {
if (process.env.NODE_ENV === 'production') {
res.status(403).json({ error: 'Invalid token' });
throw new UserError('Invalid token');
} else {

@@ -390,16 +484,34 @@ this.log(req, {

});
return next && next();
}
}
} else if (process.env.NODE_ENV === 'production') {
res.status(403).send({ error: "Authorization header isn't set" });
} else {
return next && next();
throw new UserError("Authorization header isn't set");
}
return null;
}
log(req, event) {
async checkAuth(req, res, next) {
const auth = req.headers.authorization;
try {
this.checkAuthFn(req, auth);
} catch (e) {
if (e instanceof UserError) {
res.status(403).json({ error: e.message });
} else {
this.log(req, {
type: 'Auth Error',
token: auth,
error: e.stack || e.toString()
});
res.status(500).json({ error: e.toString() });
}
}
if (next) {
next();
}
}
log(context, event) {
const { type, ...restParams } = event;
this.logger(type, { ...restParams, authInfo: req.authInfo });
this.logger(type, { ...restParams, authInfo: context.authInfo });
}

@@ -406,0 +518,0 @@ }

@@ -5,3 +5,3 @@ {

"author": "Statsbot, Inc.",
"version": "0.10.62",
"version": "0.11.0",
"engines": {

@@ -25,3 +25,3 @@ "node": ">=8.11.1"

"license": "Apache-2.0",
"gitHead": "cc6d0a247b344a55d01265daf04f2732975c40bc"
"gitHead": "b62d0e18bc793a1182fb2e3d26baf114a9cd848c"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc