mirror of
https://github.com/cerc-io/watcher-ts
synced 2026-02-01 07:44:09 +00:00
137 lines
4.9 KiB
TypeScript
137 lines
4.9 KiB
TypeScript
import path from 'path';
|
|
import assert from 'assert';
|
|
import fs from 'fs';
|
|
import yaml from 'js-yaml';
|
|
import shell from 'shelljs';
|
|
|
|
import PackageJson from '@npmcli/package-json';
|
|
import { loadFilesSync } from '@graphql-tools/load-files';
|
|
|
|
import { ASSET_DIR } from './constants';
|
|
|
|
const GRAPH_TS_VERSION = '0.27.0-watcher-ts-0.1.3';
|
|
const GRAPH_CLI_VERSION = '0.32.0-watcher-ts-0.1.4';
|
|
|
|
export function parseSubgraphSchema (subgraphPath: string, subgraphConfig: any): any {
|
|
const subgraphSchemaPath = path.join(path.resolve(subgraphPath), subgraphConfig.schema?.file ?? './schema.graphql');
|
|
|
|
assert(fs.existsSync(subgraphSchemaPath), `Schema file not found at ${subgraphSchemaPath}`);
|
|
const typesArray = loadFilesSync(subgraphSchemaPath);
|
|
|
|
// Get a subgraph-schema DocumentNode with existing types.
|
|
const subgraphSchemaDocument = typesArray[0];
|
|
const subgraphTypeDefs = subgraphSchemaDocument.definitions;
|
|
|
|
subgraphTypeDefs.forEach((def: any) => {
|
|
if (def.kind === 'ObjectTypeDefinition') {
|
|
def.fields.forEach((field: any) => {
|
|
// Parse the field type.
|
|
field.type = parseType(field.type);
|
|
});
|
|
}
|
|
});
|
|
|
|
subgraphSchemaDocument.definitions = subgraphTypeDefs;
|
|
|
|
// Return a modified subgraph-schema DocumentNode.
|
|
return subgraphSchemaDocument;
|
|
}
|
|
|
|
export function getFieldType (typeNode: any): { typeName: string, array: boolean, nullable: boolean } {
|
|
if (typeNode.kind === 'ListType') {
|
|
return { typeName: getFieldType(typeNode.type).typeName, array: true, nullable: true };
|
|
}
|
|
|
|
if (typeNode.kind === 'NonNullType') {
|
|
const fieldType = getFieldType(typeNode.type);
|
|
|
|
return { typeName: fieldType.typeName, array: fieldType.array, nullable: false };
|
|
}
|
|
|
|
// If 'NamedType'.
|
|
return { typeName: typeNode.name.value, array: false, nullable: true };
|
|
}
|
|
|
|
export function getSubgraphConfig (subgraphPath: string): any {
|
|
const subgraphConfigPath = path.join(path.resolve(subgraphPath), '/subgraph.yaml');
|
|
|
|
assert(fs.existsSync(subgraphConfigPath), `Subgraph config file not found at ${subgraphConfigPath}`);
|
|
return yaml.load(fs.readFileSync(subgraphConfigPath, 'utf8')) as any;
|
|
}
|
|
|
|
export async function buildSubgraph (
|
|
codegenConfigPath: string,
|
|
subgraphConfig: {
|
|
directory: string,
|
|
packageManager: string,
|
|
configFile: string,
|
|
networkFilePath?: string,
|
|
network?: string
|
|
}
|
|
): Promise<void> {
|
|
const codegenConfigDirName = path.dirname(codegenConfigPath);
|
|
const subgraphDirectory = path.resolve(codegenConfigDirName, subgraphConfig.directory);
|
|
const codegenWorkingDir = process.cwd();
|
|
// Change directory to subgraph repo
|
|
shell.cd(subgraphDirectory);
|
|
|
|
// Replace graph-cli & graph-ts in package.json with cerc-io forks
|
|
const pkgJson = await PackageJson.load(subgraphDirectory);
|
|
const { content } = pkgJson;
|
|
|
|
if (content.dependencies) {
|
|
// Remove graph tools from direct dependencies
|
|
delete content.dependencies['@graphprotocol/graph-ts'];
|
|
delete content.dependencies['@graphprotocol/graph-cli'];
|
|
}
|
|
|
|
if (!content.devDependencies) {
|
|
content.devDependencies = {};
|
|
}
|
|
|
|
content.devDependencies['@graphprotocol/graph-ts'] = `npm:@cerc-io/graph-ts@${GRAPH_TS_VERSION}`;
|
|
delete content.devDependencies['@graphprotocol/graph-cli'];
|
|
content.devDependencies['@cerc-io/graph-cli'] = GRAPH_CLI_VERSION;
|
|
pkgJson.update(content);
|
|
await pkgJson.save();
|
|
|
|
// Create .npmrc for cerc-io packages
|
|
fs.copyFileSync(path.join(ASSET_DIR, '.npmrc'), path.join(subgraphDirectory, '.npmrc'));
|
|
|
|
const packageManager = subgraphConfig.packageManager;
|
|
// Install dependencies
|
|
const { code: installCode } = shell.exec(`${packageManager} install --force`);
|
|
assert(installCode === 0, 'Installing dependencies exited with error');
|
|
|
|
const subgraphConfigPath = path.resolve(codegenConfigDirName, subgraphConfig.configFile);
|
|
|
|
// Run graph-cli codegen
|
|
const { code: codegenCode } = shell.exec(`${packageManager === 'npm' ? 'npx' : packageManager} graph codegen ${subgraphConfigPath}`);
|
|
assert(codegenCode === 0, 'Subgraph codegen command exited with error');
|
|
|
|
// Run graph-cli build
|
|
let buildCommand = `${packageManager === 'npm' ? 'npx' : packageManager} graph build ${subgraphConfigPath}`;
|
|
|
|
if (subgraphConfig.networkFilePath) {
|
|
const subgraphNetworkFilePath = path.resolve(codegenConfigDirName, subgraphConfig.networkFilePath);
|
|
assert(subgraphConfig.network, 'Config subgraph.network should be set if using networkFilePath');
|
|
const subgraphNetwork = subgraphConfig.network;
|
|
buildCommand = `${buildCommand} --network-file ${subgraphNetworkFilePath} --network ${subgraphNetwork}`;
|
|
}
|
|
|
|
const { code: buildCode } = shell.exec(buildCommand);
|
|
assert(buildCode === 0, 'Subgraph build command exited with error');
|
|
|
|
// Change directory back to codegen
|
|
shell.cd(codegenWorkingDir);
|
|
}
|
|
|
|
function parseType (typeNode: any): any {
|
|
// Check if 'NamedType' is reached.
|
|
if (typeNode.kind !== 'NamedType') {
|
|
typeNode.type = parseType(typeNode.type);
|
|
}
|
|
|
|
return typeNode;
|
|
}
|