Skip to content

Commit

Permalink
chore: start refactor to engines (#81)
Browse files Browse the repository at this point in the history
* chore: start refactor to engines

* chore: add newline
  • Loading branch information
roikoren755 authored Sep 13, 2021
1 parent be5f147 commit f76a497
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 110 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-seahorses-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'iql': minor
---

chore: start refactor to engines
27 changes: 19 additions & 8 deletions docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## Table of contents

### References

- [query](modules.md#query)

### Interfaces

- [IParamAggregator](interfaces/IParamAggregator.md)
Expand All @@ -21,13 +25,19 @@
- [extend](modules.md#extend)
- [intervalStringValue](modules.md#intervalstringvalue)
- [intervalToMilliseconds](modules.md#intervaltomilliseconds)
- [query](modules.md#query)
- [pg](modules.md#pg)

## References

### query

Renames and exports: [pg](modules.md#pg)

## Type aliases

### QueryCompiler

Ƭ **QueryCompiler**<`Result`, `Params`, `From`, `To`\>: `BaseQuery`<`Result`, `Params`, `From`, `To`\> & { `compile`: (`params`: `Params`) => `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\> }
Ƭ **QueryCompiler**<`Result`, `Params`, `From`, `To`, `Compiled`\>: `BaseQuery`<`Result`, `Params`, `From`, `To`\> & { `compile`: (`params`: `Params`) => `Compiled` }

Return type of the query/extend functions

Expand All @@ -39,6 +49,7 @@ Return type of the query/extend functions
| `Params` | `Params` |
| `From` | extends `Record`<`string`, `unknown`[]\>{} |
| `To` | extends `Record`<`string`, `unknown`\>{} |
| `Compiled` | `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\> |

___

Expand Down Expand Up @@ -80,7 +91,7 @@ Value types accepted by the pg library

### extend

`Const` **extend**<`T`, `U`, `K`, `L`, `M`, `N`\>(`input`, `change`): [`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M` & `T`, `N` & `U`\>
`Const` **extend**<`T`, `U`, `K`, `L`, `M`, `N`\>(`input`, `change`): [`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M` & `T`, `N` & `U`, `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\>\>

const findB = extend(findA, {
to: {
Expand Down Expand Up @@ -110,14 +121,14 @@ const publicUser = findB.toPublic(rows[0]); // publicUser.happy === true

| Name | Type |
| :------ | :------ |
| `input` | [`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M`, `N`\> |
| `input` | [`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M`, `N`, `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\>\> |
| `change` | `Object` |
| `change.from?` | { [R in string \| number \| symbol]: function} |
| `change.to?` | { [R in string \| number \| symbol]: function} |

#### Returns

[`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M` & `T`, `N` & `U`\>
[`QueryCompiler`](modules.md#querycompiler)<`K`, `L`, `M` & `T`, `N` & `U`, `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\>\>

___

Expand Down Expand Up @@ -157,9 +168,9 @@ Translates Postgres intervals to milliseconds

___

### query
### pg

`Const` **query**<`T`, `K`\>(`template`, ...`args`): [`QueryCompiler`](modules.md#querycompiler)<`T`, `K`, `Object`, `Object`\>
`Const` **pg**<`T`, `K`\>(`template`, ...`args`): [`QueryCompiler`](modules.md#querycompiler)<`T`, `K`, `Object`, `Object`, `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\>\>

```typescript
interface IRawUser {
Expand Down Expand Up @@ -202,4 +213,4 @@ OR id IN (${(agg) => agg.values('ids')}); -- Same as above

#### Returns

[`QueryCompiler`](modules.md#querycompiler)<`T`, `K`, `Object`, `Object`\>
[`QueryCompiler`](modules.md#querycompiler)<`T`, `K`, `Object`, `Object`, `QueryConfig`<[`ValueType`](modules.md#valuetype)[]\>\>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@changesets/cli": "2.17.0",
"@commitlint/cli": "13.1.0",
"@commitlint/config-conventional": "13.1.0",
"@google-cloud/bigquery": "5.9.0",
"@types/jest": "27.0.1",
"@types/pg": "8.6.1",
"@jest/types": "27.1.1",
Expand Down
51 changes: 51 additions & 0 deletions src/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { QueryCompiler } from './interfaces';

/**
* const findB = extend(findA, {
* to: {
* public: (raw) => ({ ...raw, happy: true }),
* },
* from: {
* register: (id: string) => ({ id }),
* },
* });
*
* const params = findB.fromRegister('iql'); // row is of type IUserParams
* const { rows } = await pg.query<QueryResylt<typeof findB>>(findB.compile(params));
* const publicUser = findB.toPublic(rows[0]); // publicUser.happy === true
*/
export const extend = <
T extends Record<string, unknown[]>,
U extends Record<string, unknown>,
K,
L,
M extends Record<string, unknown[]>,
N extends Record<string, unknown>,
>(
input: QueryCompiler<K, L, M, N>,
change: {
from?: { [R in keyof T]: (...args: T[R]) => L };
to?: { [R in keyof U]: (raw: K) => U[R] };
},
): QueryCompiler<K, L, M & T, N & U> =>
({
...input,
...(change.from
? Object.entries(change.from).reduce(
(acc, [from, value]) => ({
...acc,
[`from${from[0].toUpperCase()}${from.slice(1)}`]: value as (...args: T[keyof T]) => L,
}),
{},
)
: {}),
...(change.to
? Object.entries(change.to).reduce(
(acc, [from, value]) => ({
...acc,
[`to${from[0].toUpperCase()}${from.slice(1)}`]: value as (raw: K) => U[keyof U],
}),
{},
)
: {}),
} as QueryCompiler<K, L, M & T, N & U>);
14 changes: 4 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
export type {
IParamAggregator,
IPostgresInterval,
QueryCompiler,
QueryParameters,
QueryResult,
ValueType,
} from './interfaces';
export { extend, query } from './query';
export { intervalStringValue, intervalToMilliseconds } from './interval';
export { extend } from './extend';
export type { IParamAggregator, QueryCompiler, QueryParameters, QueryResult, ValueType } from './interfaces';
export { intervalStringValue, intervalToMilliseconds, query as pg, query } from './pg';
export type { IPostgresInterval } from './pg';
14 changes: 2 additions & 12 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
import type { QueryConfig } from 'pg';

/**
* Postgres internal representation of intervals
*/
export interface IPostgresInterval {
days?: number;
hours?: number;
minutes?: number;
seconds?: number;
milliseconds?: number;
}

/**
* Value types accepted by the pg library
*/
Expand Down Expand Up @@ -59,8 +48,9 @@ export type QueryCompiler<
Params,
From extends Record<string, unknown[]> = {},
To extends Record<string, unknown> = {},
Compiled = QueryConfig<ValueType[]>,
> = BaseQuery<Result, Params, From, To> & {
compile(params: Params): QueryConfig<ValueType[]>;
compile(params: Params): Compiled;
};

/**
Expand Down
File renamed without changes.
32 changes: 16 additions & 16 deletions src/__tests__/query.spec.ts → src/pg/__tests__/query.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { extend, query } from '..';
import { extend, pg } from '../..';

describe('query', () => {
describe('pg', () => {
it('should accept an array of parameters', () => {
const findMe = query<{ id: string }, [string]>`
const findMe = pg<{ id: string }, [string]>`
SELECT * FROM public.foo
WHERE id = $1::TEXT
`;
Expand All @@ -22,7 +22,7 @@ describe('query', () => {
});

it('should access key of parameters', () => {
const findMe = query<{ id: string }, { id: string }>`
const findMe = pg<{ id: string }, { id: string }>`
SELECT * FROM public.foo
WHERE id = ${'id'}::TEXT
`;
Expand All @@ -43,7 +43,7 @@ describe('query', () => {

it('should add .value to parameters', () => {
const id = 'asdasda';
const findMe = query<{ id: string }>`
const findMe = pg<{ id: string }>`
SELECT * FROM public.foo
WHERE id = ${(agg) => agg.value(id)}::TEXT
`;
Expand All @@ -61,7 +61,7 @@ describe('query', () => {
});

it('should use same parameter for multiple calls to same key', () => {
const findMe = query<{ id: string }, { id: string }>`
const findMe = pg<{ id: string }, { id: string }>`
SELECT * FROM public.foo
WHERE id = ${'id'}::TEXT
OR id = ${'id'}::TEXT
Expand All @@ -83,7 +83,7 @@ describe('query', () => {
});

it('should compile to same config with multiple calls', () => {
const findMe = query<{ id: string }, { id: string }>`
const findMe = pg<{ id: string }, { id: string }>`
SELECT * FROM public.foo
WHERE id = ${'id'}::TEXT
`;
Expand All @@ -105,7 +105,7 @@ describe('query', () => {
});

it('should access multiple keys', () => {
const findMe = query<{ id: string }, { bar: string; id: string }>`
const findMe = pg<{ id: string }, { bar: string; id: string }>`
SELECT id FROM public.foo
WHERE id = ${'id'}::TEXT
AND foo = ${'bar'}::TEXT
Expand All @@ -128,7 +128,7 @@ describe('query', () => {
});

it('should ignore order of params', () => {
const findMe = query<{ id: string }, { bar: string; id: string }>`
const findMe = pg<{ id: string }, { bar: string; id: string }>`
SELECT id FROM public.foo
WHERE id = ${'id'}::TEXT
AND foo = ${'bar'}::TEXT
Expand All @@ -151,7 +151,7 @@ describe('query', () => {
});

it('should parse array in .values', () => {
const findMe = query<{ id: string }, string[]>`
const findMe = pg<{ id: string }, string[]>`
SELECT id FROM public.foo
WHERE id in (${(agg, items) => agg.values(items)})
`;
Expand All @@ -171,7 +171,7 @@ describe('query', () => {
});

it('should access array by key in .values', () => {
const findMe = query<{ id: string }, { id: string; tags: string[] }>`
const findMe = pg<{ id: string }, { id: string; tags: string[] }>`
SELECT id FROM public.foo
WHERE id = ${'id'}
AND tags in (${(agg) => agg.values('tags')})
Expand All @@ -194,7 +194,7 @@ describe('query', () => {
});

it('should work with no helpers with extend', () => {
const findMe = query<{ id: string }, string[]>`
const findMe = pg<{ id: string }, string[]>`
SELECT id FROM public.foo
WHERE id in (${(agg, values) => agg.values(values)})
`;
Expand All @@ -205,7 +205,7 @@ describe('query', () => {
});

it('should add helpers with extend', () => {
const findMe = query<{ id: string }, string[]>`
const findMe = pg<{ id: string }, string[]>`
SELECT id FROM public.foo
WHERE id in (${(agg, values) => agg.values(values)})
`;
Expand All @@ -221,8 +221,8 @@ describe('query', () => {
expect(findMeExtended.fromId(result)).toStrictEqual([result.id]);
});

it('should create diiferent query names', () => {
const findMe = query<unknown, { a: number[]; b: number[] }>`
it('should create different query names', () => {
const findMe = pg<unknown, { a: number[]; b: number[] }>`
SELECT * FROM public.foo
WHERE a in (${(agg, { a }) => agg.values(a)})
AND b in (${(agg, { b }) => agg.values(b)});
Expand All @@ -235,7 +235,7 @@ describe('query', () => {
});

it('should not fail for empty query', () => {
const findMe = query``;
const findMe = pg``;

expect(findMe.compile()).toStrictEqual({
name: expect.stringContaining(''),
Expand Down
3 changes: 3 additions & 0 deletions src/pg/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type { IPostgresInterval } from './interfaces';
export { intervalStringValue, intervalToMilliseconds } from './interval';
export { query } from './query';
10 changes: 10 additions & 0 deletions src/pg/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Postgres internal representation of intervals
*/
export interface IPostgresInterval {
days?: number;
hours?: number;
minutes?: number;
seconds?: number;
milliseconds?: number;
}
File renamed without changes.
52 changes: 1 addition & 51 deletions src/query.ts → src/pg/query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createHash } from 'crypto';

import type { BuilderInput, IParamAggregator, QueryCompiler, QueryParameters, ValueType } from './interfaces';
import type { BuilderInput, IParamAggregator, QueryCompiler, QueryParameters, ValueType } from '../interfaces';

/**
* Utility function to generate a consistent query name
Expand Down Expand Up @@ -92,53 +92,3 @@ export const query = <T, K = void>(
return { name, text, values: agg.props };
},
});

/**
* const findB = extend(findA, {
* to: {
* public: (raw) => ({ ...raw, happy: true }),
* },
* from: {
* register: (id: string) => ({ id }),
* },
* });
*
* const params = findB.fromRegister('iql'); // row is of type IUserParams
* const { rows } = await pg.query<QueryResylt<typeof findB>>(findB.compile(params));
* const publicUser = findB.toPublic(rows[0]); // publicUser.happy === true
*/
export const extend = <
T extends Record<string, unknown[]>,
U extends Record<string, unknown>,
K,
L,
M extends Record<string, unknown[]>,
N extends Record<string, unknown>,
>(
input: QueryCompiler<K, L, M, N>,
change: {
from?: { [R in keyof T]: (...args: T[R]) => L };
to?: { [R in keyof U]: (raw: K) => U[R] };
},
): QueryCompiler<K, L, M & T, N & U> =>
({
...input,
...(change.from
? Object.entries(change.from).reduce(
(acc, [from, value]) => ({
...acc,
[`from${from[0].toUpperCase()}${from.slice(1)}`]: value as (...args: T[keyof T]) => L,
}),
{},
)
: {}),
...(change.to
? Object.entries(change.to).reduce(
(acc, [from, value]) => ({
...acc,
[`to${from[0].toUpperCase()}${from.slice(1)}`]: value as (raw: K) => U[keyof U],
}),
{},
)
: {}),
} as QueryCompiler<K, L, M & T, N & U>);
Loading

0 comments on commit f76a497

Please sign in to comment.