Skip to content

Commit b08da4b

Browse files
committed
feature(CORE): can pass request headers down to dataSource
1 parent d8f3a53 commit b08da4b

File tree

11 files changed

+64
-12
lines changed

11 files changed

+64
-12
lines changed

packages/core/src/lib/data-query/builder/dataQueryBuilder.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Pagination,
44
DataResult,
55
isOffsetPagination,
6+
IncomingHttpHeaders,
67
} from '@vulcan-sql/core/models';
78
import * as uuid from 'uuid';
89
import { find, isEmpty, isNull, isUndefined } from 'lodash';
@@ -411,6 +412,7 @@ export interface IDataQueryBuilder {
411412
take(size: number, move: number): IDataQueryBuilder;
412413
// paginate
413414
paginate(pagination: Pagination): void;
415+
setHeaders(headers: IncomingHttpHeaders): void;
414416
value(): Promise<DataResult>;
415417
clone(): IDataQueryBuilder;
416418
parameterizeOperations(): Promise<Partial<Parameterized<SQLClauseOperation>>>;
@@ -425,19 +427,22 @@ export class DataQueryBuilder implements IDataQueryBuilder {
425427
public readonly identifier: string;
426428
private profileName: string;
427429
private parameterizer: IParameterizer;
430+
private headers: IncomingHttpHeaders;
428431

429432
constructor({
430433
statement,
431434
operations,
432435
parameterizer,
433436
dataSource,
434437
profileName,
438+
headers,
435439
}: {
436440
statement: string;
437441
operations?: SQLClauseOperation;
438442
parameterizer: IParameterizer;
439443
dataSource: DataSource;
440444
profileName: string;
445+
headers: IncomingHttpHeaders;
441446
}) {
442447
this.identifier = uuid.v4();
443448
this.statement = statement;
@@ -453,6 +458,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
453458
limit: null,
454459
offset: null,
455460
};
461+
this.headers = headers;
456462
this.profileName = profileName;
457463
}
458464

@@ -647,6 +653,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
647653
dataSource: this.dataSource,
648654
parameterizer: this.parameterizer,
649655
profileName: this.profileName,
656+
headers: this.headers,
650657
});
651658
builderCallback(wrappedBuilder);
652659
this.recordWhere({
@@ -1096,6 +1103,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
10961103
operations: this.operations,
10971104
parameterizer: this.parameterizer.clone(),
10981105
profileName: this.profileName,
1106+
headers: this.headers,
10991107
});
11001108
}
11011109

@@ -1107,6 +1115,11 @@ export class DataQueryBuilder implements IDataQueryBuilder {
11071115
this.take(pagination.limit, pagination.offset);
11081116
}
11091117

1118+
public setHeaders(headers: IncomingHttpHeaders) {
1119+
if (!headers) return;
1120+
this.headers = headers;
1121+
}
1122+
11101123
public async parameterizeOperations(): Promise<
11111124
Partial<Parameterized<SQLClauseOperation>>
11121125
> {
@@ -1127,6 +1140,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
11271140
operations: await this.parameterizeOperations(),
11281141
bindParams: this.parameterizer.getBinding(),
11291142
profileName: this.profileName,
1143+
headers: this.headers,
11301144
});
11311145

11321146
return result;

packages/core/src/lib/data-query/executor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export class QueryExecutor implements IExecutor {
4646
parameterizer,
4747
dataSource: this.dataSourceFactory(profileName)!,
4848
profileName,
49+
headers: {},
4950
});
5051
}
5152
}

packages/core/src/lib/template-engine/built-in-extensions/cache/cacheTagRunner.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class CacheTagRunner extends TagRunner {
2525
this.executor = executor;
2626
}
2727

28-
public async run({ context, args, contentArgs }: TagRunnerOptions) {
28+
public async run({ context, args, contentArgs, metadata }: TagRunnerOptions) {
2929
// Get the variable name, if the cache tag has variable name, then we use the variable and keep the builder in the variable, and make user could use by xxx.value() like the req feature.
3030
// However if the cache tag not has variable name, means you would like to get the result directly after query, then we will replace the original query main builder to the cache builder.
3131
const name = String(args[0]);
@@ -56,6 +56,9 @@ export class CacheTagRunner extends TagRunner {
5656
parameterizer
5757
);
5858
context.setVariable(name, builder);
59+
// pass header to builder
60+
const headers = metadata.getHeaders();
61+
if (headers) builder.setHeaders(headers);
5962

6063
// Set parameter back for upstream usage
6164
context.setVariable(PARAMETERIZER_VAR_NAME, parentParameterizer);

packages/core/src/lib/template-engine/built-in-extensions/query-builder/reqTagRunner.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ export class ReqTagRunner extends TagRunner {
4747
.join('\n')
4848
.replace(/--.*(?:\n|$)|\/\*[\s\S]*?\*\//g, ''); // remove single-line comments and multi-line comments
4949

50+
const headers = metadata.getHeaders();
5051
let builder: IDataQueryBuilder | undefined;
5152
// Replace to put the directly query cache builder to original query main builder of "__wrapper__builder",
5253
// it means we can use the cache builder to execute the query directly and get result to be final result
5354
builder = context.lookup(CACHE_MAIN_BUILDER_VAR_NAME);
54-
if (builder) context.setVariable(name, builder);
55-
else {
55+
if (builder) {
56+
if (headers) builder.setHeaders(headers);
57+
context.setVariable(name, builder);
58+
} else {
5659
builder = await this.executor.createBuilder(
5760
profileName,
5861
query,
5962
parameterizer
6063
);
64+
if (headers) builder.setHeaders(headers);
6165
context.setVariable(name, builder);
6266
}
6367

packages/core/src/lib/template-engine/compiler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { DataResult, KoaRequest } from '@vulcan-sql/core/models';
1+
import {
2+
DataResult,
3+
IncomingHttpHeaders,
4+
KoaRequest,
5+
} from '@vulcan-sql/core/models';
26
import { Pagination } from '../../models/pagination';
37

48
export interface TemplateLocation {
@@ -32,6 +36,7 @@ export interface ExecuteContext {
3236
user?: UserInfo;
3337
profileName: string;
3438
req?: KoaRequest;
39+
headers?: IncomingHttpHeaders;
3540
}
3641

3742
export interface Compiler {

packages/core/src/lib/template-engine/nunjucksExecutionMetadata.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as nunjucks from 'nunjucks';
22
import { ExecuteContext, UserInfo } from './compiler';
3-
import { KoaRequest } from '@vulcan-sql/core/models';
3+
import { IncomingHttpHeaders, KoaRequest } from '@vulcan-sql/core/models';
44

55
export const ReservedContextKeys = {
66
CurrentProfileName: 'RESERVED_CURRENT_PROFILE_NAME',
@@ -12,12 +12,20 @@ export class NunjucksExecutionMetadata {
1212
private parameters: Record<string, any>;
1313
private userInfo?: UserInfo;
1414
private req?: KoaRequest;
15+
private headers?: IncomingHttpHeaders;
1516

16-
constructor({ parameters = {}, profileName, user, req }: ExecuteContext) {
17+
constructor({
18+
parameters = {},
19+
profileName,
20+
user,
21+
req,
22+
headers,
23+
}: ExecuteContext) {
1724
this.parameters = parameters;
1825
this.profileName = profileName;
1926
this.userInfo = user;
2027
this.req = req;
28+
this.headers = headers;
2129
}
2230

2331
/** Load from nunjucks context */
@@ -26,6 +34,7 @@ export class NunjucksExecutionMetadata {
2634
parameters: context.lookup('context')?.params || {},
2735
user: context.lookup('context')?.user || {},
2836
req: context.lookup('context')?.req || {},
37+
headers: context.lookup('context')?.headers || {},
2938
profileName: context.lookup(ReservedContextKeys.CurrentProfileName)!,
3039
});
3140
}
@@ -38,6 +47,7 @@ export class NunjucksExecutionMetadata {
3847
user: this.userInfo,
3948
req: this.req,
4049
profile: this.profileName,
50+
headers: this.headers,
4151
},
4252
[ReservedContextKeys.CurrentProfileName]: this.profileName,
4353
};
@@ -54,4 +64,8 @@ export class NunjucksExecutionMetadata {
5464
public getRequest() {
5565
return this.req;
5666
}
67+
68+
public getHeaders() {
69+
return this.headers;
70+
}
5771
}

packages/core/src/models/artifact.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ import {
3030
import { Type } from 'class-transformer';
3131
import 'reflect-metadata';
3232
import { Request as KoaRequest } from 'koa';
33+
import { IncomingHttpHeaders } from 'http';
3334

3435
export type { KoaRequest };
36+
export type { IncomingHttpHeaders };
3537

3638
// Pagination mode should always be UPPERCASE because schema parser will transform the user inputs.
3739
export enum PaginationMode {

packages/core/src/models/extensions/dataSource.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
/* eslint-disable @typescript-eslint/no-unused-vars */
22
import { Parameterized, SQLClauseOperation } from '@vulcan-sql/core/data-query';
3-
import { CacheLayerStoreFormatType, Profile } from '@vulcan-sql/core/models';
3+
import {
4+
CacheLayerStoreFormatType,
5+
IncomingHttpHeaders,
6+
Profile,
7+
} from '@vulcan-sql/core/models';
48
import { TYPES } from '@vulcan-sql/core/types';
59
import { inject, multiInject, optional } from 'inversify';
610
import { Readable } from 'stream';
@@ -58,6 +62,7 @@ export interface ExecuteOptions {
5862
/** The parameter bindings, we guarantee the order of the keys in the map is the same as the order when they were used in queries. */
5963
bindParams: BindParameters;
6064
profileName: string;
65+
headers?: IncomingHttpHeaders;
6166
}
6267

6368
export type PrepareParameterFunc = {

packages/serve/src/lib/route/route-component/baseRoute.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { IRequestValidator } from './requestValidator';
99
import { IRequestTransformer, RequestParameters } from './requestTransformer';
1010
import { IPaginationTransformer } from './paginationTransformer';
1111
import { Evaluator } from '@vulcan-sql/serve/evaluator';
12-
import { KoaRequest } from '@vulcan-sql/core';
12+
import { KoaRequest, IncomingHttpHeaders } from '@vulcan-sql/core';
1313

1414
export interface TransformedRequest {
1515
reqParams: RequestParameters;
@@ -61,7 +61,8 @@ export abstract class BaseRoute implements IRoute {
6161
protected async handle(
6262
user: AuthUserInfo,
6363
transformed: TransformedRequest,
64-
req: KoaRequest
64+
req: KoaRequest,
65+
headers: IncomingHttpHeaders
6566
) {
6667
const { reqParams, pagination } = transformed;
6768
// could template name or template path, use for template engine
@@ -81,6 +82,7 @@ export abstract class BaseRoute implements IRoute {
8182
user,
8283
req,
8384
profileName: profile,
85+
headers: headers,
8486
},
8587
pagination
8688
);

packages/serve/src/lib/route/route-component/graphQLRoute.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export class GraphQLRoute extends BaseRoute {
2020
const transformed = await this.prepare(ctx);
2121
const authUser = ctx.state.user;
2222
const req = ctx.request as KoaRequest;
23-
await this.handle(authUser, transformed, req);
23+
const headers = ctx.headers;
24+
await this.handle(authUser, transformed, req, headers);
2425
// TODO: get template engine handled result and return response by checking API schema
2526
return transformed;
2627
}

0 commit comments

Comments
 (0)