1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6 | desc = { enumerable: true, get: function() { return m[k]; } };
|
7 | }
|
8 | Object.defineProperty(o, k2, desc);
|
9 | }) : (function(o, m, k, k2) {
|
10 | if (k2 === undefined) k2 = k;
|
11 | o[k2] = m[k];
|
12 | }));
|
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15 | }) : function(o, v) {
|
16 | o["default"] = v;
|
17 | });
|
18 | var __importStar = (this && this.__importStar) || function (mod) {
|
19 | if (mod && mod.__esModule) return mod;
|
20 | var result = {};
|
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22 | __setModuleDefault(result, mod);
|
23 | return result;
|
24 | };
|
25 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
26 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
27 | };
|
28 | Object.defineProperty(exports, "__esModule", { value: true });
|
29 | const path_1 = __importDefault(require("path"));
|
30 |
|
31 | const Index_bs_js_1 = __importDefault(require("@float-capital/float-subgraph-uncrashable/src/Index.bs.js"));
|
32 | const fs_extra_1 = __importDefault(require("fs-extra"));
|
33 | const toolbox = __importStar(require("gluegun"));
|
34 | const graphql = __importStar(require("graphql/language"));
|
35 | const immutable_1 = __importDefault(require("immutable"));
|
36 | const prettier_1 = __importDefault(require("prettier"));
|
37 | const template_1 = __importDefault(require("./codegen/template"));
|
38 | const typescript_1 = require("./codegen/typescript");
|
39 | const fs_1 = require("./command-helpers/fs");
|
40 | const spinner_1 = require("./command-helpers/spinner");
|
41 | const migrations_1 = require("./migrations");
|
42 | const schema_1 = __importDefault(require("./schema"));
|
43 | const subgraph_1 = __importDefault(require("./subgraph"));
|
44 | const watcher_1 = __importDefault(require("./watcher"));
|
45 | class TypeGenerator {
|
46 | constructor(options) {
|
47 | this.options = options;
|
48 | this.sourceDir =
|
49 | this.options.sourceDir ||
|
50 | (this.options.subgraphManifest && path_1.default.dirname(this.options.subgraphManifest));
|
51 | this.protocol = this.options.protocol;
|
52 | this.protocolTypeGenerator = this.protocol?.getTypeGenerator?.({
|
53 | sourceDir: this.sourceDir,
|
54 | outputDir: this.options.outputDir,
|
55 | });
|
56 | process.on('uncaughtException', e => {
|
57 | toolbox.print.error(`UNCAUGHT EXCEPTION: ${e}`);
|
58 | });
|
59 | }
|
60 | async generateTypes() {
|
61 | if (this.protocol.name === 'substreams') {
|
62 | toolbox.print.success('Subgraph uses a substream datasource. Codegeneration is not required.');
|
63 | process.exit(0);
|
64 | return;
|
65 | }
|
66 | try {
|
67 | if (!this.options.skipMigrations && this.options.subgraphManifest) {
|
68 | await (0, migrations_1.applyMigrations)({
|
69 | sourceDir: this.sourceDir,
|
70 | manifestFile: this.options.subgraphManifest,
|
71 | });
|
72 | }
|
73 | const subgraph = await this.loadSubgraph();
|
74 |
|
75 | if (this.protocol.hasABIs()) {
|
76 | const abis = await this.protocolTypeGenerator.loadABIs(subgraph);
|
77 | await this.protocolTypeGenerator.generateTypesForABIs(abis);
|
78 | }
|
79 | await this.generateTypesForDataSourceTemplates(subgraph);
|
80 |
|
81 | if (this.protocol.hasABIs()) {
|
82 | const templateAbis = await this.protocolTypeGenerator.loadDataSourceTemplateABIs(subgraph);
|
83 | await this.protocolTypeGenerator.generateTypesForDataSourceTemplateABIs(templateAbis);
|
84 | }
|
85 | const schema = await this.loadSchema(subgraph);
|
86 | await this.generateTypesForSchema(schema);
|
87 | toolbox.print.success('\nTypes generated successfully\n');
|
88 | if (this.options.uncrashable && this.options.uncrashableConfig) {
|
89 | await this.generateUncrashableEntities(schema);
|
90 | toolbox.print.success('\nUncrashable Helpers generated successfully\n');
|
91 | }
|
92 | return true;
|
93 | }
|
94 | catch (e) {
|
95 | return false;
|
96 | }
|
97 | }
|
98 | async generateUncrashableEntities(graphSchema) {
|
99 | const ast = graphql.parse(graphSchema.document);
|
100 | const entityDefinitions = ast['definitions'];
|
101 | return await (0, spinner_1.withSpinner)(`Generate Uncrashable Entity Helpers`, `Failed to generate Uncrashable Entity Helpers`, `Warnings while generating Uncrashable Entity Helpers`, async (spinner) => {
|
102 | Index_bs_js_1.default.run(entityDefinitions, this.options.uncrashableConfig, this.options.outputDir);
|
103 | const outputFile = path_1.default.join(this.options.outputDir, 'UncrashableEntityHelpers.ts');
|
104 | (0, spinner_1.step)(spinner, 'Save uncrashable entities to', (0, fs_1.displayPath)(outputFile));
|
105 | });
|
106 | }
|
107 | async loadSubgraph({ quiet } = { quiet: false }) {
|
108 | const subgraphLoadOptions = { protocol: this.protocol, skipValidation: false };
|
109 | if (quiet) {
|
110 | return (this.options.subgraph ||
|
111 | (await subgraph_1.default.load(this.options.subgraphManifest, subgraphLoadOptions)).result);
|
112 | }
|
113 | const manifestPath = (0, fs_1.displayPath)(this.options.subgraphManifest);
|
114 | return await (0, spinner_1.withSpinner)(`Load subgraph from ${manifestPath}`, `Failed to load subgraph from ${manifestPath}`, `Warnings while loading subgraph from ${manifestPath}`, async (_spinner) => {
|
115 | return (this.options.subgraph || subgraph_1.default.load(this.options.subgraphManifest, subgraphLoadOptions));
|
116 | });
|
117 | }
|
118 | async loadSchema(subgraph) {
|
119 | const maybeRelativePath = subgraph.getIn(['schema', 'file']);
|
120 | const absolutePath = path_1.default.resolve(this.sourceDir, maybeRelativePath);
|
121 | return await (0, spinner_1.withSpinner)(`Load GraphQL schema from ${(0, fs_1.displayPath)(absolutePath)}`, `Failed to load GraphQL schema from ${(0, fs_1.displayPath)(absolutePath)}`, `Warnings while loading GraphQL schema from ${(0, fs_1.displayPath)(absolutePath)}`, async (_spinner) => {
|
122 | const absolutePath = path_1.default.resolve(this.sourceDir, maybeRelativePath);
|
123 | return schema_1.default.load(absolutePath);
|
124 | });
|
125 | }
|
126 | async generateTypesForSchema(schema) {
|
127 | return await (0, spinner_1.withSpinner)(`Generate types for GraphQL schema`, `Failed to generate types for GraphQL schema`, `Warnings while generating types for GraphQL schema`, async (spinner) => {
|
128 |
|
129 | const codeGenerator = schema.codeGenerator();
|
130 | const code = prettier_1.default.format([
|
131 | typescript_1.GENERATED_FILE_NOTE,
|
132 | ...codeGenerator.generateModuleImports(),
|
133 | ...codeGenerator.generateTypes(),
|
134 | ...codeGenerator.generateDerivedLoaders(),
|
135 | ].join('\n'), {
|
136 | parser: 'typescript',
|
137 | });
|
138 | const outputFile = path_1.default.join(this.options.outputDir, 'schema.ts');
|
139 | (0, spinner_1.step)(spinner, 'Write types to', (0, fs_1.displayPath)(outputFile));
|
140 | await fs_extra_1.default.mkdirs(path_1.default.dirname(outputFile));
|
141 | await fs_extra_1.default.writeFile(outputFile, code);
|
142 | });
|
143 | }
|
144 | async generateTypesForDataSourceTemplates(subgraph) {
|
145 | return await (0, spinner_1.withSpinner)(`Generate types for data source templates`, `Failed to generate types for data source templates`, `Warnings while generating types for data source templates`, async (spinner) => {
|
146 |
|
147 | const codeSegments = subgraph
|
148 | .get('templates', immutable_1.default.List())
|
149 | .reduce((codeSegments, template) => {
|
150 | (0, spinner_1.step)(spinner, 'Generate types for data source template', String(template.get('name')));
|
151 | const codeGenerator = new template_1.default(template, this.protocol);
|
152 |
|
153 |
|
154 | if (codeSegments.isEmpty()) {
|
155 | codeSegments = codeSegments.concat(codeGenerator.generateModuleImports());
|
156 | }
|
157 | return codeSegments.concat(codeGenerator.generateTypes());
|
158 | }, immutable_1.default.List());
|
159 | if (!codeSegments.isEmpty()) {
|
160 | const code = prettier_1.default.format([typescript_1.GENERATED_FILE_NOTE, ...codeSegments].join('\n'), {
|
161 | parser: 'typescript',
|
162 | });
|
163 | const outputFile = path_1.default.join(this.options.outputDir, 'templates.ts');
|
164 | (0, spinner_1.step)(spinner, `Write types for templates to`, (0, fs_1.displayPath)(outputFile));
|
165 | await fs_extra_1.default.mkdirs(path_1.default.dirname(outputFile));
|
166 | await fs_extra_1.default.writeFile(outputFile, code);
|
167 | }
|
168 | });
|
169 | }
|
170 | async getFilesToWatch() {
|
171 | try {
|
172 | const files = [];
|
173 | const subgraph = await this.loadSubgraph({ quiet: true });
|
174 |
|
175 | files.push(this.options.subgraphManifest);
|
176 |
|
177 | files.push(subgraph.getIn(['schema', 'file']));
|
178 |
|
179 | subgraph.get('dataSources').map((dataSource) => {
|
180 | dataSource.getIn(['mapping', 'abis']).map((abi) => {
|
181 | files.push(abi.get('file'));
|
182 | });
|
183 | });
|
184 |
|
185 | return files.map(file => path_1.default.resolve(file));
|
186 | }
|
187 | catch (e) {
|
188 | throw Error(`Failed to load subgraph: ${e.message}`);
|
189 | }
|
190 | }
|
191 | async watchAndGenerateTypes() {
|
192 | const generator = this;
|
193 | let spinner;
|
194 |
|
195 | const watcher = new watcher_1.default({
|
196 | onReady: () => (spinner = toolbox.print.spin('Watching subgraph files')),
|
197 | onTrigger: async (changedFile) => {
|
198 | if (changedFile !== undefined) {
|
199 | spinner.info(`File change detected: ${(0, fs_1.displayPath)(changedFile)}\n`);
|
200 | }
|
201 | await generator.generateTypes();
|
202 | spinner.start();
|
203 | },
|
204 | onCollectFiles: async () => await generator.getFilesToWatch(),
|
205 | onError: error => {
|
206 | spinner.stop();
|
207 | toolbox.print.error(`${error}\n`);
|
208 | spinner.start();
|
209 | },
|
210 | });
|
211 |
|
212 | process.on('SIGINT', () => {
|
213 | watcher.close();
|
214 | process.exit();
|
215 | });
|
216 | try {
|
217 | await watcher.watch();
|
218 | }
|
219 | catch (e) {
|
220 | toolbox.print.error(String(e.message));
|
221 | }
|
222 | }
|
223 | }
|
224 | exports.default = TypeGenerator;
|