feat(graphql): simplify graphql context and secrets

This commit is contained in:
Sam Tolmay 2020-11-12 14:17:20 +02:00
parent a08ea293ef
commit 5f2a43bb81
8 changed files with 32 additions and 145 deletions

View File

@ -21,29 +21,19 @@ import createGetController from './getController';
import createGetLoader from './getLoader';
function createContext(config) {
const { CONFIGURATION_BASE_PATH, logger, getSecrets } = config;
const bootstrapContext = {
DEPLOYMENT_ID: config.DEPLOYMENT_ID,
DEPLOYMENT_NAME: config.DEPLOYMENT_NAME,
DOMAIN_NAME: config.DOMAIN_NAME,
CONFIGURATION_BASE_PATH: config.CONFIGURATION_BASE_PATH,
logger: config.logger,
CONFIGURATION_BASE_PATH,
logger,
getSecrets,
};
bootstrapContext.getLoader = createGetLoader(bootstrapContext);
const getController = createGetController(bootstrapContext);
async function context(input) {
const headers = config.getHeadersFromInput(input);
const secrets = await config.getSecrets();
bootstrapContext.ORIGIN = get(headers, 'Origin') || get(headers, 'origin');
bootstrapContext.HOST = get(headers, 'Host') || get(headers, 'host');
bootstrapContext.getConnectionSecrets = () => secrets.CONNECTION_SECRETS;
bootstrapContext.getLoader = createGetLoader(bootstrapContext);
bootstrapContext.getController = createGetController(bootstrapContext);
async function context() {
return {
getController: bootstrapContext.getController,
logger: bootstrapContext.logger,
getController,
logger,
};
}
return context;

View File

@ -26,23 +26,15 @@ const logger = {
};
const mockGetHeadersFromInput = jest.fn((input) => input.headers);
const mockGetSecrets = jest.fn(() => ({
CONNECTION_SECRETS: {},
}));
const mockGetSecrets = jest.fn(() => ({}));
const config = {
DEPLOYMENT_ID: 'DEPLOYMENT_ID',
DEPLOYMENT_NAME: 'DEPLOYMENT_NAME',
DOMAIN_NAME: 'DOMAIN_NAME',
CONFIGURATION_BASE_PATH: 'CONFIGURATION_BASE_PATH',
logger,
getHeadersFromInput: mockGetHeadersFromInput,
getSecrets: mockGetSecrets,
};
/* TODO:
- headers are mapped to where used
- connection secrets are mapped to request controller
- secrets can only be accessed where they should be
- CONFIGURATION_BASE_PATH is mapped to loaders
*/
@ -53,14 +45,8 @@ test('create context function', () => {
});
test('context function returns context object with getController and logger', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
const context = await contextFn();
expect(context).toBeInstanceOf(Object);
expect(context.logger).toBe(logger);
expect(context.getController).toBeInstanceOf(Function);
@ -68,28 +54,16 @@ test('context function returns context object with getController and logger', as
});
test('context function returns context object with getController and logger', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
const context = await contextFn();
expect(context).toBeInstanceOf(Object);
expect(context.logger).toBe(logger);
expect(context.getController).toBeInstanceOf(Function);
});
test('getController returns the correct controllers', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
const context = await contextFn();
const pageController = context.getController('page');
expect(pageController).toBeInstanceOf(PageController);
const componentController = context.getController('component');
@ -97,67 +71,15 @@ test('getController returns the correct controllers', async () => {
});
test('logger is mapped through', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
const context = await contextFn();
context.logger.log('test');
expect(mockLog.mock.calls).toEqual([['test']]);
});
test('getHeaders is called', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
test('request controller has getSecrets', async () => {
const contextFn = createContext(config);
await contextFn(input);
expect(mockGetHeadersFromInput.mock.calls).toEqual([[input]]);
});
test('getSecrets is called', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
await contextFn(input);
expect(mockGetSecrets.mock.calls).toEqual([[]]);
});
test('deployment variables area available for component controller', async () => {
const input = {
headers: {
Origin: 'Origin',
Host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
const componentController = context.getController('component');
expect(componentController.DEPLOYMENT_ID).toEqual('DEPLOYMENT_ID');
expect(componentController.DEPLOYMENT_NAME).toEqual('DEPLOYMENT_NAME');
expect(componentController.DOMAIN_NAME).toEqual('DOMAIN_NAME');
});
test('Casing of headers', async () => {
const input = {
headers: {
origin: 'Origin',
host: 'Host',
},
};
const contextFn = createContext(config);
const context = await contextFn(input);
expect(context).toBeInstanceOf(Object);
expect(context.logger).toBe(logger);
expect(context.getController).toBeInstanceOf(Function);
const context = await contextFn();
const requestController = context.getController('request');
expect(requestController.getSecrets).toBe(mockGetSecrets);
});

View File

@ -17,19 +17,13 @@
import { get } from '@lowdefy/helpers';
class ComponentController {
constructor({ getLoader, DEPLOYMENT_ID, DEPLOYMENT_NAME, DOMAIN_NAME }) {
constructor({ getLoader }) {
this.componentLoader = getLoader('component');
this.DEPLOYMENT_ID = DEPLOYMENT_ID;
this.DEPLOYMENT_NAME = DEPLOYMENT_NAME;
this.DOMAIN_NAME = DOMAIN_NAME;
}
async getLowdefyGlobal() {
const loadedLowdefyGlobal = await this.componentLoader.load('global');
const lowdefyGlobal = loadedLowdefyGlobal || {};
lowdefyGlobal.deploymentId = this.DEPLOYMENT_ID;
lowdefyGlobal.deploymentName = this.DEPLOYMENT_NAME;
lowdefyGlobal.domainName = this.DOMAIN_NAME;
return lowdefyGlobal;
}

View File

@ -43,9 +43,6 @@ test('getLowdefyGlobal', async () => {
const res = await controller.getLowdefyGlobal();
expect(res).toEqual({
x: 'value',
deploymentId: 'test',
deploymentName: 'Test App',
domainName: 'test.com',
});
});
@ -55,11 +52,7 @@ test('getLowdefyGlobal, global not found', async () => {
});
const controller = createComponentController(context);
const res = await controller.getLowdefyGlobal();
expect(res).toEqual({
deploymentId: 'test',
deploymentName: 'Test App',
domainName: 'test.com',
});
expect(res).toEqual({});
});
test('getMenus, menus not found', async () => {

View File

@ -30,11 +30,10 @@ function validateConnection(connectionData, requestData) {
}
class RequestController {
constructor({ getController, getLoader, getConnectionSecrets }) {
this.getConnectionSecrets = getConnectionSecrets;
constructor({ getLoader, getSecrets }) {
this.getSecrets = getSecrets;
this.requestLoader = getLoader('request');
this.connectionLoader = getLoader('connection');
this.pageController = getController('page');
}
async callRequest({
@ -58,11 +57,13 @@ class RequestController {
const requestType = get(requestData, 'type');
const secrets = await this.getSecrets();
const operatorsParser = new NodeParser({
arrayIndices,
input,
lowdefyGlobal,
secrets: this.getConnectionSecrets(),
secrets,
state,
urlQuery,
});

View File

@ -34,7 +34,7 @@ const secrets = {
REQUEST: 'requestSecret',
};
const getConnectionSecrets = () => secrets;
const getSecrets = () => secrets;
const mockLoadConnection = jest.fn();
const mockLoadRequest = jest.fn();
@ -47,7 +47,7 @@ const loaders = {
},
};
const context = testBootstrapContext({ loaders, getConnectionSecrets });
const context = testBootstrapContext({ loaders, getSecrets });
const defaultInput = {
args: {},

View File

@ -57,7 +57,7 @@ test('global resolver', async () => {
});
});
test('menu graphql', async () => {
test('lowdefyGlobal graphql', async () => {
const res = await runTestQuery({
gqlQuery: GET_GLOBAL,
loaders,
@ -67,9 +67,6 @@ test('menu graphql', async () => {
expect(res.data).toEqual({
lowdefyGlobal: {
global: true,
deploymentId: 'test',
deploymentName: 'Test App',
domainName: 'test.com',
},
});
});

View File

@ -16,32 +16,22 @@
import createGetController from '../context/getController';
function testBootstrapContext({ loaders, getConnectionSecrets } = {}) {
function testBootstrapContext({ loaders, getSecrets } = {}) {
const bootstrapContext = {
DEPLOYMENT_ID: 'test',
DEPLOYMENT_NAME: 'Test App',
DOMAIN_NAME: 'test.com',
CONFIGURATION_BASE_PATH: 'CONFIGURATION_BASE_PATH',
ORIGIN: 'test.com',
HOST: 'test.com',
getLoader: loaders ? (name) => loaders[name] : () => {},
getController: () => {},
getConnectionSecrets: getConnectionSecrets || (() => {}),
getSecrets: getSecrets || (() => {}),
logger: { log: () => {} },
};
bootstrapContext.getController = createGetController(bootstrapContext);
return bootstrapContext;
}
function testContext({ loaders } = {}) {
function testContext({ loaders, getSecrets } = {}) {
const bootstrapContext = {
DEPLOYMENT_ID: 'test',
DEPLOYMENT_NAME: 'Test App',
DOMAIN_NAME: 'test.com',
ORIGIN: 'test.com',
HOST: 'test.com',
getLoader: (name) => loaders[name],
getConnectionSecrets: () => {},
getSecrets: getSecrets || (() => {}),
logger: { log: () => {} },
};
bootstrapContext.getController = createGetController(bootstrapContext);