Skip to content

Commit

Permalink
Gil's repro
Browse files Browse the repository at this point in the history
  • Loading branch information
gilgardosh committed Feb 15, 2023
1 parent 6924fa1 commit 7e73207
Show file tree
Hide file tree
Showing 18 changed files with 4,041 additions and 105 deletions.
6 changes: 3 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"test-lib": true,
"lib": true,
"coverage": true,
"npm": true,
"**/dist": true
"npm": true
// "**/dist": true
},
"typescript.tsdk": "node_modules/typescript/lib"
}
}
1 change: 1 addition & 0 deletions examples/gils-repro/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/types.ts
21 changes: 21 additions & 0 deletions examples/gils-repro/codegen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
overwrite: true
schema: ./src/modules/*/typeDefs/*.graphql.ts
config:
scalars:
TimelessDate: 'TimelessDateString'
generates:
src/modules/:
preset: graphql-modules
presetConfig:
baseTypesPath: ../__generated__/types.ts
filename: __generated__/types.ts
encapsulateModuleTypes: namespace
config:
immutableTypes: true
contextType: 'GraphQLModules.Context'
optionalResolveType: true
mappers:
Charge: ../modules/charges/__generated__/charges.types.js#IGetChargesByIdsResult
plugins:
- 'typescript'
- 'typescript-resolvers'
45 changes: 45 additions & 0 deletions examples/gils-repro/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "gils-repro",
"version": "0.0.0",
"private": true,
"main": "dist/index.js",
"license": "MIT",
"type": "module",
"scripts": {
"build": "tsc && tsc-alias",
"prestart": "yarn generate && yarn build",
"start": "node dist/index.js",
"generate": "graphql-codegen --config codegen.yml"
},
"dependencies": {
"@accounter-toolkit/green-invoice-graphql": "0.1.1-alpha-20221128094016-ab48d5a",
"@accounter-toolkit/pcn874-generator": "0.0.2",
"@envelop/graphql-modules": "4.0.4",
"@graphql-tools/mock": "8.7.14",
"@graphql-tools/schema": "9.0.12",
"@graphql-yoga/node": "3.1.1",
"@pgtyped/cli": "1.0.2",
"@pgtyped/query": "1.0.1",
"cloudinary": "1.32.0",
"dataloader": "2.1.0",
"date-fns": "2.29.3",
"dotenv": "16.0.3",
"dotenv-cli": "6.0.0",
"fastify": "4.10.2",
"graphql": "16.6.0",
"graphql-modules": "2.1.0",
"graphql-yoga": "3.1.1",
"pg": "8.9.0",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
"@graphql-codegen/cli": "2.16.1",
"@graphql-codegen/graphql-modules-preset": "3.0.0",
"@graphql-codegen/typescript": "2.8.5",
"@graphql-codegen/typescript-resolvers": "2.7.10",
"@types/pg": "8.6.6",
"nodemon": "2.0.20",
"pino-pretty": "9.1.1",
"tsc-alias": "1.8.2"
}
}
25 changes: 25 additions & 0 deletions examples/gils-repro/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createServer } from 'node:http';
import { config } from 'dotenv';
import { createYoga } from 'graphql-yoga';
import 'reflect-metadata';
import { useGraphQLModules } from '@envelop/graphql-modules';
import { createGraphQLApp } from './modules-app.js';

config();

async function main() {
const application = await createGraphQLApp();
const yoga = createYoga({ plugins: [useGraphQLModules(application)] });
const server = createServer(yoga);

server.listen(
{
port: 4000,
},
() => {
console.log('GraphQL API located at http://localhost:4000/graphql');
}
);
}

main();
35 changes: 35 additions & 0 deletions examples/gils-repro/src/models/enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export enum MissingChargeInfo {
Counterparty = 'COUNTERPARTY',
TransactionDescription = 'TRANSACTION_DESCRIPTION',
Tags = 'TAGS',
Vat = 'VAT',
Documents = 'DOCUMENTS',
LedgerRecords = 'LEDGER_RECORDS',
Balance = 'BALANCE',
}

export enum ChargeSortByField {
Date = 'DATE',
Amount = 'AMOUNT',
AbsAmount = 'ABS_AMOUNT',
}

export enum TransactionDirection {
Debit = 'DEBIT',
Credit = 'CREDIT',
}

export enum Currency {
Usd = 'USD',
Ils = 'ILS',
Gbp = 'GBP',
Eur = 'EUR',
}

export enum DocumentType {
Invoice = 'INVOICE',
Receipt = 'RECEIPT',
InvoiceReceipt = 'INVOICE_RECEIPT',
Proforma = 'PROFORMA',
Unprocessed = 'UNPROCESSED',
}
34 changes: 34 additions & 0 deletions examples/gils-repro/src/models/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export type BeneficiaryCounterpartyProto = { name: string; percentage: number };
export type CounterpartyProto = string | null;

type CurrencySum = {
credit: number;
debit: number;
total: number;
};

export type RawBusinessTransactionsSum = {
ils: CurrencySum;
eur: CurrencySum;
gbp: CurrencySum;
usd: CurrencySum;
businessName: string;
};

type addZero<T> = T | 0;
type oneToFour = 1 | 2 | 3 | 4;
type oneToNine = oneToFour | 5 | 6 | 7 | 8 | 9;
type d = addZero<oneToNine>;
type YYYY = `20${addZero<oneToFour>}${d}`;
type MM = `0${oneToNine}` | `1${0 | 1 | 2}`;
type DD = `${0}${oneToNine}` | `${1 | 2}${d}` | `3${0 | 1}`;

export type TimelessDateString = `${YYYY}-${MM}-${DD}`;

export type OptionalToNullable<O> = {
[K in keyof O]: undefined extends O[K] ? O[K] | null : O[K];
};
export type Optional<T, Keys extends keyof T> = Omit<T, Keys> &
OptionalToNullable<Partial<Pick<T, Keys>>>;

export * as enums from './enums.js';
26 changes: 26 additions & 0 deletions examples/gils-repro/src/modules-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createApplication } from 'graphql-modules';
import { DBProvider } from './modules/app-providers/db.provider.js';
import postgres from 'pg';
import { chargesModule } from './modules/charges/index.js';
import { commonModule } from './modules/common/index.js';

const { Pool } = postgres;

export async function createGraphQLApp() {
return createApplication({
modules: [commonModule, chargesModule],
providers: () => [
{
provide: Pool,
useFactory: () =>
new Pool({
connectionString: process.env.PGURI,
ssl: {
rejectUnauthorized: false,
},
}),
},
DBProvider,
],
});
}
21 changes: 21 additions & 0 deletions examples/gils-repro/src/modules/app-providers/db.provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Injectable, Scope } from 'graphql-modules';
import postgres, { QueryResultBase, QueryResultRow } from 'pg';
import 'reflect-metadata';

type TypedQueryResult<Entity> = QueryResultBase & { rows: Entity[] };

@Injectable({
scope: Scope.Singleton,
global: true,
})
export class DBProvider {
constructor(private pool: postgres.Pool) {}

public async query<Entity extends QueryResultRow>(
queryStatement: string,
values?: any[] | undefined
): Promise<TypedQueryResult<Entity>> {
return this.pool.query(queryStatement, values);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions examples/gils-repro/src/modules/charges/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import charges from './typeDefs/charges.graphql.js';
import { createModule } from 'graphql-modules';
import { ChargesProvider } from './providers/charges.provider.js';
import { chargesResolvers } from './resolvers/charges.resolver.js';

const __dirname = new URL('.', import.meta.url).pathname;

export const chargesModule = createModule({
id: 'charges',
dirname: __dirname,
typeDefs: [charges],
resolvers: [chargesResolvers],
providers: () => [ChargesProvider],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import DataLoader from 'dataloader';
import { Injectable, Scope } from 'graphql-modules';
import { DBProvider } from '../../app-providers/db.provider.js';
import pgQuery from '@pgtyped/query';
import { IGetChargesByIdsQuery } from '../__generated__/charges.types.js';

const { sql } = pgQuery;

const getChargesByIds = sql<IGetChargesByIdsQuery>`
SELECT *
FROM accounter_schema.all_transactions
WHERE id IN $$cahrgeIds;`;

@Injectable({
scope: Scope.Singleton,
global: true,
})
export class ChargesProvider {
constructor(private dbProvider: DBProvider) {}

private async batchChargesByIds(ids: readonly string[]) {
const charges = await getChargesByIds.run(
{
cahrgeIds: ids,
},
this.dbProvider
);
return ids.map((id) => charges.find((charge) => charge.id === id));
}

public getChargeByIdLoader = new DataLoader(this.batchChargesByIds, {
cache: false,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ChargesModule } from '../__generated__/types.js';
import { ChargesProvider } from '../providers/charges.provider.js';

export const chargesResolvers: ChargesModule.Resolvers = {
Query: {
chargeById: async (_, { id }, { injector }) => {
const dbCharge = await injector
.get(ChargesProvider)
.getChargeByIdLoader.load(id);
if (!dbCharge) {
throw new Error(`Charge ID="${id}" not found`);
}
return dbCharge;
},
},
Charge: {
id: (DbCharge) => DbCharge.id,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { gql } from 'graphql-modules';

export default gql`
extend type Query {
chargeById(id: ID!): Charge!
}
" represrent a complex type for grouped charge with ledger info, bank/card transactions and documents "
type Charge {
id: ID!
}
`;
10 changes: 10 additions & 0 deletions examples/gils-repro/src/modules/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import common from './typeDefs/common.graphql.js';
import { createModule } from 'graphql-modules';

const __dirname = new URL('.', import.meta.url).pathname;

export const commonModule = createModule({
id: 'common',
dirname: __dirname,
typeDefs: [common],
});
13 changes: 13 additions & 0 deletions examples/gils-repro/src/modules/common/typeDefs/common.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { gql } from 'graphql-modules';

export default gql`
" query root "
type Query {
ping: Boolean
}
" mutation root "
type Mutation {
pong: Boolean
}
`;
Loading

0 comments on commit 7e73207

Please sign in to comment.