Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@
"zod": "^3.21.4"
},
"devDependencies": {
"@snapshot-labs/eslint-config": "^0.1.0-beta.7",
"@snapshot-labs/prettier-config": "^0.1.0-beta.7",
"@snapshot-labs/eslint-config": "^0.1.0-beta.21",
"@snapshot-labs/prettier-config": "^0.1.0-beta.19",
"@types/bn.js": "^5.1.0",
"@types/jest": "^29.5.0",
"@types/node": "^18.11.6",
"@types/node": "^22.18.0",
"@types/pg": "^8.6.6",
"dotenv": "^16.0.1",
"eslint": "^8.28.0",
"eslint": "^8.57.0",
"jest": "^29.5.0",
"jest-mock-extended": "^3.0.4",
"prettier": "^2.7.1",
"prettier": "^3.6.2",
"sqlite3": "^5.1.6",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"typescript": "^4.9.3"
"typescript": "^5.9.2"
},
"files": [
"dist/**/*",
Expand Down
27 changes: 19 additions & 8 deletions src/bin/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
#!/usr/bin/env node

import path from 'path';
import fs from 'fs/promises';
import path from 'path';
import process from 'process';
import yargs from 'yargs/yargs';
import { printSchema } from 'graphql';
import { hideBin } from 'yargs/helpers';
import yargs from 'yargs/yargs';
import { codegen } from '../codegen';
import { GqlEntityController } from '../graphql/controller';
import { OverridesConfig } from '../types';
import { extendSchema } from '../utils/graphql';
import { GqlEntityController } from '../graphql/controller';
import { printSchema } from 'graphql';

const DEFAULT_CONFIG_PATH = 'src/overrides.json';
const DEFAULT_SCHEMA_PATH = 'src/schema.gql';
const OUTPUT_DIRECTORY = '.checkpoint';

async function generate(schemaFile: string, overridesConfigFile: string, format: string) {
async function generate(
schemaFile: string,
overridesConfigFile: string,
format: string
) {
if (format !== 'typescript' && format !== 'javascript') {
throw new Error('Invalid output format');
}
Expand All @@ -29,7 +33,7 @@ async function generate(schemaFile: string, overridesConfigFile: string, format:
let config: OverridesConfig = {};
try {
config = await import(overridesConfigFilePath);
} catch (err) {}
} catch {}

let schema = await fs.readFile(schemaFilePath, 'utf8');
schema = extendSchema(schema);
Expand All @@ -49,7 +53,10 @@ async function generate(schemaFile: string, overridesConfigFile: string, format:
console.log('Generating query schema');
const querySchema = controller.generateSchema();
const schemaOutputPath = path.join(OUTPUT_DIRECTORY, 'schema.gql');
await fs.writeFile(path.join(cwd, schemaOutputPath), printSchema(querySchema));
await fs.writeFile(
path.join(cwd, schemaOutputPath),
printSchema(querySchema)
);

console.log('Schema generated to', schemaOutputPath);
}
Expand Down Expand Up @@ -81,7 +88,11 @@ yargs(hideBin(process.argv))
},
async argv => {
try {
await generate(argv['schema-file'], argv['overrides-config-file'], argv['output-format']);
await generate(
argv['schema-file'],
argv['overrides-config-file'],
argv['output-format']
);
} catch (err) {
console.error('Error generating models:', err);
process.exit(1);
Expand Down
37 changes: 26 additions & 11 deletions src/checkpoint.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Knex } from 'knex';
import { Pool as PgPool } from 'pg';
import { Container } from './container';
import getGraphQL from './graphql';
import { GqlEntityController } from './graphql/controller';
import { CheckpointsStore } from './stores/checkpoints';
import { BaseIndexer } from './providers';
import { createLogger, Logger, LogLevel } from './utils/logger';
import { extendSchema } from './utils/graphql';
import { createKnex } from './knex';
import { createPgPool } from './pg';
import { checkpointConfigSchema } from './schemas';
import { BaseIndexer } from './providers';
import { register } from './register';
import { checkpointConfigSchema } from './schemas';
import { CheckpointsStore } from './stores/checkpoints';
import { CheckpointConfig, CheckpointOptions } from './types';
import { Container } from './container';
import { extendSchema } from './utils/graphql';
import { createLogger, Logger, LogLevel } from './utils/logger';

export default class Checkpoint {
private readonly entityController: GqlEntityController;
Expand All @@ -28,7 +28,10 @@ export default class Checkpoint {

constructor(schema: string, opts?: CheckpointOptions) {
this.schema = extendSchema(schema);
this.entityController = new GqlEntityController(this.schema, opts?.overridesConfig);
this.entityController = new GqlEntityController(
this.schema,
opts?.overridesConfig
);

this.opts = opts;
this.log = createLogger({
Expand Down Expand Up @@ -57,10 +60,16 @@ export default class Checkpoint {
register.setKnex(this.knex);
}

public addIndexer(name: string, config: CheckpointConfig, indexer: BaseIndexer) {
public addIndexer(
name: string,
config: CheckpointConfig,
indexer: BaseIndexer
) {
const validationResult = checkpointConfigSchema.safeParse(config);
if (validationResult.success === false) {
throw new Error(`Checkpoint config is invalid: ${validationResult.error.message}`);
throw new Error(
`Checkpoint config is invalid: ${validationResult.error.message}`
);
}

const container = new Container(
Expand Down Expand Up @@ -100,7 +109,11 @@ export default class Checkpoint {
public get graphql() {
const schema = this.getSchema();

return getGraphQL(schema, this.getBaseContext(), this.entityController.generateSampleQuery());
return getGraphQL(
schema,
this.getBaseContext(),
this.entityController.generateSampleQuery()
);
}

/**
Expand All @@ -113,7 +126,9 @@ export default class Checkpoint {
public async start() {
this.log.debug('starting');

await Promise.all([...this.containers.values()].map(container => container.start()));
await Promise.all(
[...this.containers.values()].map(container => container.start())
);
}

/**
Expand Down
27 changes: 19 additions & 8 deletions src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
} from 'graphql';
import pluralize from 'pluralize';
import { GqlEntityController } from './graphql/controller';
import { getDerivedFromDirective } from './utils/graphql';
import { OverridesConfig } from './types';
import { getDerivedFromDirective } from './utils/graphql';

type TypeInfo = {
type: string;
Expand Down Expand Up @@ -74,7 +74,10 @@ export const getTypeInfo = (
const nonNullNestedType =
type.ofType instanceof GraphQLNonNull ? type.ofType.ofType : type.ofType;

return { type: `${getTypeInfo(nonNullNestedType, decimalTypes).type}[]`, initialValue: '[]' };
return {
type: `${getTypeInfo(nonNullNestedType, decimalTypes).type}[]`,
initialValue: '[]'
};
}

throw new Error('Unknown type');
Expand Down Expand Up @@ -104,7 +107,8 @@ export const getJSType = (
field: GraphQLField<any, any>,
decimalTypes: DecimalTypes = DEFAULT_DECIMAL_TYPES
) => {
const nonNullType = field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
const nonNullType =
field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
const isNullable = !(field.type instanceof GraphQLNonNull);
const isList = nonNullType instanceof GraphQLList;
const baseType = getBaseType(nonNullType, decimalTypes);
Expand Down Expand Up @@ -139,7 +143,9 @@ export const codegen = (
idType.isNullable ||
idType.isList
) {
throw new Error(`Model ${modelName} must have an id field of type string or number`);
throw new Error(
`Model ${modelName} must have an id field of type string or number`
);
}

contents +=
Expand All @@ -148,7 +154,8 @@ export const codegen = (
: ` constructor(id: ${idType.baseType}, indexerName: string) {\n`;
contents += ` super(${modelName}.tableName, indexerName);\n\n`;
typeFields.forEach(field => {
const fieldType = field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
const fieldType =
field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
if (
isListType(fieldType) &&
fieldType.ofType instanceof GraphQLObjectType &&
Expand All @@ -158,7 +165,8 @@ export const codegen = (
}

const rawInitialValue = getInitialValue(field.type, decimalTypes);
const initialValue = field.name === 'id' ? 'id' : JSON.stringify(rawInitialValue);
const initialValue =
field.name === 'id' ? 'id' : JSON.stringify(rawInitialValue);
contents += ` this.initialSet('${field.name}', ${initialValue});\n`;
});
contents += ` }\n\n`;
Expand All @@ -181,7 +189,8 @@ export const codegen = (
contents += ` }\n\n`;

typeFields.forEach(field => {
const fieldType = field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
const fieldType =
field.type instanceof GraphQLNonNull ? field.type.ofType : field.type;
if (
isListType(fieldType) &&
fieldType.ofType instanceof GraphQLObjectType &&
Expand All @@ -198,7 +207,9 @@ export const codegen = (
? ` get ${field.name}() {\n`
: ` get ${field.name}(): ${typeAnnotation} {\n`;
contents += ` return ${
isList ? `JSON.parse(this.get('${field.name}'))` : `this.get('${field.name}')`
isList
? `JSON.parse(this.get('${field.name}'))`
: `this.get('${field.name}')`
};\n`;
contents += ` }\n\n`;

Expand Down
Loading