diff --git a/.gitignore b/.gitignore index 48323c844..bb92e5370 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ **/.eslintcache **/.nyc_output **/.DS_Store -**/lib \ No newline at end of file +**/lib +**/.idea/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..b58b603fe --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/README.md b/README.md index a522f0b4b..7a0c42bdb 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,12 @@ The monorepo contains the following sub-packages: * [Sample Project](https://github.com/dzhelezov/hydra/tree/d8c7f79fd26db49de753e0247ef561f5fcb7878f/packages/sample/README.md): A quickstart Hydra project set up against a publicly available Kusama indexer. Good starting point. * [Docs](docs/): In-depth documentation covering the Hydra pipeline and API features, such as full-text search, pagination, extensive filtering and a rich GraphQL dialect defining your schema! +## Contributing + +Thank you for you interest in contributing to Hydra and the Joy Stream ecosystem. Please don't hesitate to reach out to us on our [telegram channel](https://t.me/HydraDevs) if you have any questions about contributing. + +Each package has it's own README file which you should read before contributing. + +The first step is to fork this repository and then clone your fork. All changes should be done on a seperate branch and then submitted for review on a pull request. + + diff --git a/docs/install-hydra.md b/docs/install-hydra.md index b71422279..5484b0d0e 100644 --- a/docs/install-hydra.md +++ b/docs/install-hydra.md @@ -49,5 +49,11 @@ It may be convenient to create an alias for quick access to `hydra-cli` e.g. ```text alias hydra-cli='npx @dzlzv/hydra-cli' ``` + +Or on Windows you can use: + +```text +doskey hydra-cli=npx @dzlzv/hydra-cli +``` {% endhint %} diff --git a/docs/mappings/README.md b/docs/mappings/README.md index d8b63879c..6e7ae1f92 100644 --- a/docs/mappings/README.md +++ b/docs/mappings/README.md @@ -47,7 +47,7 @@ and this is where all the auto-generated classes live by default. Next, the body of the handler transforms the event parameters and extrinsic arguments into the properties of the entity. There is currently no way to enforce type safety here and one should instead inspect the event parameters and extrinsics for the event in question. In the example above, we can consult the Kusama [explorer](https://kusama.subscan.io/extrinsic/0x1bba67ddb62117fc64710e35b6ccbef64d4df528d78310ccca725137e75823d4?event=2022835-5) and check that * `ProposalIndex` is a single named param of `treasury.Proposed` event -* The extrinsic has to arguments: `value` and `beneficiary`, propagated to the entity in a straightforward fashion. +* The extrinsic has two arguments: `value` and `beneficiary`, propagated to the entity in a straightforward fashion. Type-safe mappings and runtime upgrades will be supported in future releases of Hydra. diff --git a/docs/schema-spec/README.md b/docs/schema-spec/README.md index 088a633f1..547fce261 100644 --- a/docs/schema-spec/README.md +++ b/docs/schema-spec/README.md @@ -14,3 +14,10 @@ Hydra input schema is a dialect of the GraphQL schema definition language enrich $ hydra-cli preview && cat apipreview.graphql ``` +In windows, you should run: + +```text +$ hydra-cli preview && type apipreview.graphql +``` + + diff --git a/docs/schema-spec/entities.md b/docs/schema-spec/entities.md index 46ce36b20..deba79cca 100644 --- a/docs/schema-spec/entities.md +++ b/docs/schema-spec/entities.md @@ -42,7 +42,7 @@ type Person @entity { name: String! married: Boolean age: Int - "one person, one account, one live" + "one person, one account, one life" account: Bytes! @unique salary: BigInt interests: [String] diff --git a/docs/schema-spec/enums.md b/docs/schema-spec/enums.md index 1f1daf88b..1b6f3f895 100644 --- a/docs/schema-spec/enums.md +++ b/docs/schema-spec/enums.md @@ -3,7 +3,7 @@ Enums are natively supported as described the GraphQL schema [spec](https://spec.graphql.org/June2018/#sec-Enums). Here is an illustrative example: ```text -enum { +enum ProposalStatus { NONE REJECTED APPROVED diff --git a/docs/schema-spec/full-text-queries.md b/docs/schema-spec/full-text-queries.md index e8a427586..11356eacd 100644 --- a/docs/schema-spec/full-text-queries.md +++ b/docs/schema-spec/full-text-queries.md @@ -25,7 +25,7 @@ The generated output schema will define the required output type and the query: type SearchResult { item: Post | Comment, rank: number, - highligt: String + highlight: String } type Query { diff --git a/docs/schema-spec/the-query-goodies.md b/docs/schema-spec/the-query-goodies.md index 70a6fd80b..33cfed405 100644 --- a/docs/schema-spec/the-query-goodies.md +++ b/docs/schema-spec/the-query-goodies.md @@ -8,7 +8,7 @@ description: >- ## Filtering -All the scalar entity types enjoy first-class support in the output schema when it comes to filtering. The standard is known as [OpenCRUD](https://www.opencrud.org/) and dictates who filtering should look like depending on the field type. For example, if the input schema defines the following type: +All the scalar entity types enjoy first-class support in the output schema when it comes to filtering. The standard is known as [OpenCRUD](https://www.opencrud.org/) and dictates what the filtering should look like depending on the field type. For example, if the input schema defines the following type: ```graphql type Person @entity { @@ -45,7 +45,7 @@ query { ## Ordering -The results can also be ordered by any property with natural ordering. `_DESC`an `_ASC` suffixes indicate the direction: +The results can also be ordered by any property with natural ordering. The `_DESC` and `_ASC` suffixes indicate the direction: ```graphql query { diff --git a/packages/hydra-cli/CHANGELOG.md b/packages/hydra-cli/CHANGELOG.md index c2cf37c6d..066d2d595 100644 --- a/packages/hydra-cli/CHANGELOG.md +++ b/packages/hydra-cli/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 0.1.7 + +- `codegen --schema` now supports passing folders instead of single schema file + ## 0.1.6 - Fixed preview feature diff --git a/packages/hydra-cli/README.md b/packages/hydra-cli/README.md index 6606ba39c..9d4c81273 100644 --- a/packages/hydra-cli/README.md +++ b/packages/hydra-cli/README.md @@ -175,3 +175,18 @@ To run it locally, inspect the settings in `.env` and run $ yarn configure:dev $ yarn server:start:dev ``` + +## Contributing +Thank you for you interest in contributing to Hydra CLI and the Joy Stream ecosystem. Please don't hesitate to reach out to us on our [telegram channel](https://t.me/HydraDevs) if you have any questions about contributing. + +All changes should be submited on a pull request. Before submitting a pull request you should run the linting and test commands: +``` +yarn lint +yarn test +``` + +Other development scripts include: +`yarn build` +`yarn postpack` +`yarn prepack` +`yarn version` diff --git a/packages/hydra-cli/package.json b/packages/hydra-cli/package.json index 03e355da2..90eb5a650 100644 --- a/packages/hydra-cli/package.json +++ b/packages/hydra-cli/package.json @@ -1,7 +1,7 @@ { "name": "@dzlzv/hydra-cli", "description": "CLI tool for building a Hydra query node", - "version": "0.1.6", + "version": "0.1.7", "author": "metmirr @metmirr dzlzv @dzhelezov", "license": "MIT", "bin": { diff --git a/packages/hydra-cli/src/codegen/WarthogWrapper.ts b/packages/hydra-cli/src/codegen/WarthogWrapper.ts index 8133d4356..43e1114e8 100644 --- a/packages/hydra-cli/src/codegen/WarthogWrapper.ts +++ b/packages/hydra-cli/src/codegen/WarthogWrapper.ts @@ -33,7 +33,7 @@ export default class WarthogWrapper { ) if (!fs.existsSync(this.schemaResolvedPath)) { throw new Error( - `Cannot open the schema file ${this.schemaResolvedPath}. Check if it exists.` + `Cannot open the schema file or folder: ${this.schemaResolvedPath}. Check if it exists.` ) } } diff --git a/packages/hydra-cli/src/commands/codegen.ts b/packages/hydra-cli/src/commands/codegen.ts index 6f0a21a90..d4b36beb6 100644 --- a/packages/hydra-cli/src/commands/codegen.ts +++ b/packages/hydra-cli/src/commands/codegen.ts @@ -18,7 +18,7 @@ export default class Codegen extends Command { static flags = { schema: flags.string({ char: 's', - description: 'Schema path', + description: 'Schema path, can be file or directory', default: '../../schema.graphql', }), // pass --no-indexer to skip indexer generation diff --git a/packages/hydra-cli/src/commands/scaffold.ts b/packages/hydra-cli/src/commands/scaffold.ts index 8469ba59b..819a7ffa6 100644 --- a/packages/hydra-cli/src/commands/scaffold.ts +++ b/packages/hydra-cli/src/commands/scaffold.ts @@ -216,7 +216,7 @@ export default class Scaffold extends Command { return ctx } const typesJSON = (await cli.prompt( - 'Please provide the localtion of the type definitions JSON, relative to ./generated/indexer', + 'Please provide the location of the type definitions JSON, relative to ./generated/indexer', { default: '../../typedefs.json' } )) as string return { ...ctx, typesJSON } diff --git a/packages/hydra-cli/src/parse/SchemaParser.ts b/packages/hydra-cli/src/parse/SchemaParser.ts index a46ab9325..9e6057775 100644 --- a/packages/hydra-cli/src/parse/SchemaParser.ts +++ b/packages/hydra-cli/src/parse/SchemaParser.ts @@ -19,6 +19,7 @@ import { cloneDeep } from 'lodash' import { SCHEMA_DEFINITIONS_PREAMBLE } from './constant' import { SchemaDirective } from './SchemaDirective' import { FTSDirective } from './FTSDirective' +import path from 'path' const debug = Debug('qnode-cli:schema-parser') @@ -67,7 +68,7 @@ export class GraphQLSchemaParser { if (!fs.existsSync(schemaPath)) { throw new Error('Schema not found') } - const contents = fs.readFileSync(schemaPath, 'utf8') + const contents = this.getUnifiedSchema(schemaPath) this.schema = GraphQLSchemaParser.buildSchema(contents) this.namedTypes = [ ...Object.values(this.schema.getTypeMap()).filter( @@ -79,6 +80,28 @@ export class GraphQLSchemaParser { ) } + private getUnifiedSchema(schemaPath: string): string { + let schemaString = '' + if (fs.lstatSync(schemaPath).isDirectory()) { + fs.readdirSync(schemaPath).forEach((file) => { + if ( + fs.lstatSync(path.resolve(schemaPath, file)).isFile() && + path.extname(file) === '.graphql' + ) { + schemaString = schemaString.concat( + fs.readFileSync(path.resolve(schemaPath, file), 'utf8'), + '\n\n' + ) + } + }) + } else if (fs.lstatSync(schemaPath).isFile()) { + schemaString = fs.readFileSync(schemaPath, 'utf8') + } else { + throw new Error('Error reading schema file(s)') + } + return schemaString + } + private static buildPreamble(): string { let preamble = SCHEMA_DEFINITIONS_PREAMBLE DIRECTIVES.map((d) => (preamble += d.preamble + '\n')) diff --git a/packages/hydra-cli/test/fixtures/schema-folder/proposal.graphql b/packages/hydra-cli/test/fixtures/schema-folder/proposal.graphql new file mode 100644 index 000000000..09b1c5f89 --- /dev/null +++ b/packages/hydra-cli/test/fixtures/schema-folder/proposal.graphql @@ -0,0 +1,24 @@ +enum ProposalStatus { + NONE + REJECTED + APPROVED +} + +"A spending proposal" +type Proposal @entity { + "The account proposing it" + proposer: Bytes! + + "The (total) amount that should be paid if the proposal is accepted" + value: BigInt! + + "The account to whom the payment should be made if the proposal is accepted" + beneficiary: Bytes! + + "The amount held on deposit (reserved) for making this proposal" + bond: BigInt! + + proposalIndex: BigInt! @unique + + status: ProposalStatus +} \ No newline at end of file diff --git a/packages/hydra-cli/test/fixtures/schema-folder/tip.graphql b/packages/hydra-cli/test/fixtures/schema-folder/tip.graphql new file mode 100644 index 000000000..004962eee --- /dev/null +++ b/packages/hydra-cli/test/fixtures/schema-folder/tip.graphql @@ -0,0 +1,32 @@ +"The members who have voted for the tip." +type Tipper @entity { + tip: Tip! + tipper: Bytes! + tipValue: BigInt! +} + +type Tip @entity { + "The hash of the reason for the tip." + reason: Bytes! @unique + + "The account to be tipped." + who: Bytes! + + "The account who began this tip." + finder: Bytes! + + "The amount held on deposit for this tip." + deposit: BigInt + + "The block number at which this tip will close if Some." + closes: BigInt + + "The members who have voted for this tip." + tippers: [Tipper!] @derivedFrom(field: "tip") + + "Whether this tip should result in the finder taking a fee." + findersFee: Boolean! + + "Cancel the process of tipping" + retracted: Boolean! +} \ No newline at end of file diff --git a/packages/hydra-cli/test/fixtures/schema-folder/transfer.graphql b/packages/hydra-cli/test/fixtures/schema-folder/transfer.graphql new file mode 100644 index 000000000..bc143d917 --- /dev/null +++ b/packages/hydra-cli/test/fixtures/schema-folder/transfer.graphql @@ -0,0 +1,8 @@ +" All transfers " +type Transfer @entity { + from: Bytes! + to: Bytes! + value: BigInt! + comment: String @fulltext(query: "commentSearch") + block: Int! +} diff --git a/packages/hydra-cli/test/helpers/SchemaParser.test.ts b/packages/hydra-cli/test/helpers/SchemaParser.test.ts index f81664632..007fcc701 100644 --- a/packages/hydra-cli/test/helpers/SchemaParser.test.ts +++ b/packages/hydra-cli/test/helpers/SchemaParser.test.ts @@ -101,6 +101,11 @@ describe('SchemaParser', () => { ) }) + it('should load multiple files', () => { + const parser = new GraphQLSchemaParser('test/fixtures/schema-folder/') + expect(parser.getObjectDefinations()).length(4, 'Should detect 4 types') + }) + it('should visit directives', () => { const parser = new GraphQLSchemaParser('test/fixtures/single-type.graphql') const names: string[] = [] diff --git a/packages/sample/package.json b/packages/sample/package.json index 85a20912b..f2146d2ab 100644 --- a/packages/sample/package.json +++ b/packages/sample/package.json @@ -42,7 +42,7 @@ }, "devDependencies": { "envsub": "^4.0.7", - "@dzlzv/hydra-cli": "0.1.6", + "@dzlzv/hydra-cli": "0.1.7", "@dzlzv/hydra-common": "~0.0.3", "@dzlzv/hydra-db-utils": "^0.0.2", "@dzlzv/hydra-processor": "~0.1.1", diff --git a/yarn.lock b/yarn.lock index 3e9cc75ce..a3b00befb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10982,7 +10982,7 @@ ts-mockito@^2.6.1: dependencies: lodash "^4.17.5" -ts-node-dev@^1.0.0-pre.40, ts-node-dev@^1.0.0-pre.60, ts-node-dev@^1.0.0-pre.63: +ts-node-dev@^1.0.0-pre.40, ts-node-dev@^1.0.0-pre.63: version "1.1.1" resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.1.tgz#b7602929395b1616b4aa99a3be0a4e121742283d" integrity sha512-kAO8LUZgXZSY0+PucMPsQ0Bbdv0x+lgbN7j8gcD4PuTI4uKC6YchekaspmYTBNilkiu+rQYkWJA7cK+Q8/B0tQ== @@ -11013,7 +11013,7 @@ ts-node@^7.0.1: source-map-support "^0.5.6" yn "^2.0.0" -ts-node@^8, ts-node@^8.10: +ts-node@^8: version "8.10.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==