diff --git a/docs/src/data-types/types.md b/docs/src/data-types/types.md index 771dafb13..2dca9a3d3 100644 --- a/docs/src/data-types/types.md +++ b/docs/src/data-types/types.md @@ -37,7 +37,7 @@ struct Event { The corresponding GraphQL schema to mirror this `Event` struct would resemble: ```graphql -type Event { +type Event @entity { id: ID! account: Address! block_height: UInt8! diff --git a/docs/src/database/foreign-keys.md b/docs/src/database/foreign-keys.md index 7436d9e59..c92c69982 100644 --- a/docs/src/database/foreign-keys.md +++ b/docs/src/database/foreign-keys.md @@ -18,12 +18,12 @@ Let's learn how to use each foreign key type by looking at some GraphQL schema e ### Implicit foreign keys ```graphql -type Book { +type Book @entity { id: ID! name: Bytes8! } -type Library { +type Library @entity { id: ID! book: Book! } @@ -36,12 +36,12 @@ Given the above schema, two entities will be created: a `Book` entity, and a `Li ### Explicit foreign keys ```graphql -type Book { +type Book @entity { id: ID! name: Bytes8! @unique } -type Library { +type Library @entity { id: ID! book: Book! @join(on:name) } diff --git a/docs/src/graphql/directives.md b/docs/src/graphql/directives.md index a20bbb5dd..97fd353f4 100644 --- a/docs/src/graphql/directives.md +++ b/docs/src/graphql/directives.md @@ -14,12 +14,12 @@ As of this writing, the list of supported Fuel GraphQL schema directives include The `@indexed` directive adds a [database index](https://www.postgresql.org/docs/current/indexes-intro.html) to the underlying column for the indicated field of that type. Generally, a database index is a data structure that allows you to quickly locate data without having to search each row in a database table. ```graphql -type Book { +type Book @entity { id: ID! name: Bytes8! @indexed } -type Library { +type Library @entity { id: ID! book: Book! } @@ -34,12 +34,12 @@ In this example, a single `BTREE INDEX` constraint will be created on the `book` The `@unique` directive adds a `UNIQUE` database constraint to the underlying database column for the indicated field of that type. A constraint specifies a rule for the data in a table and can be used to limit the type of data that can be placed in the table. In the case of a column with a `UNIQUE` constraint, all values in the column must be different. ```graphql -type Book { +type Book @entity { id: ID! name: Bytes8! @unique } -type Library { +type Library @entity { id: ID! book: Book! } @@ -54,12 +54,12 @@ A `UNIQUE` constraint will be created on the `book` table's `name` column, ensur The `@join` directive is used to relate a field in one type to others by referencing fields in another type. You can think of it as a link between two tables in your database. The field in the referenced type is called a _foreign key_ and it is **required** to be unique. ```graphql -type Book { +type Book @entity { id: ID! name: Charfield! @unique } -type Library { +type Library @entity { id: ID! book: Book! @join(on:name) } @@ -72,11 +72,11 @@ A foreign key constraint will be created on `library.book` that references `book The `@virtual` directive instructs the indexer's SQL schema builder to _not_ build SQL tables from types that include this directive on any field. ```graphql -type Title { +type Title @entity { name: CharField! @virtual } -type Book { +type Book @entity { id: ID! title: Title! } diff --git a/docs/src/project-components/schema.md b/docs/src/project-components/schema.md index c6de701ae..ba3f1faa9 100644 --- a/docs/src/project-components/schema.md +++ b/docs/src/project-components/schema.md @@ -5,12 +5,12 @@ The GraphQL schema is a required component of the Fuel indexer. When data is ind In its most basic form, a Fuel indexer GraphQL schema should have a `schema` definition that contains a defined query root. The rest of the implementation is up to you. Here's an example of a well-formed schema: ```graphql -type FirstThing { +type FirstThing @entity { id: ID! value: UInt8! } -type SecondThing { +type SecondThing @entity { id: ID! optional_value: UInt8 timestamp: Timestamp! diff --git a/docs/src/queries/index.md b/docs/src/queries/index.md index c58270baa..e9828c703 100644 --- a/docs/src/queries/index.md +++ b/docs/src/queries/index.md @@ -88,24 +88,24 @@ Essentially, it's the same as the basic query example with an added sub-block to We'll start with the following example schema: ```graphql -type City { +type City @entity { id: ID! name: Charfield! } -type Library { +type Library @entity { id: ID! name: Charfield! city: City! } -type Book { +type Book @entity { id: ID! title: Charfield! library: Library! } -type Character { +type Character @entity { id: ID! name: Charfield! book: Book! diff --git a/examples/fuel-explorer/fuel-explorer/schema/fuel_explorer.schema.graphql b/examples/fuel-explorer/fuel-explorer/schema/fuel_explorer.schema.graphql index 7be5a2f75..ec65520be 100644 --- a/examples/fuel-explorer/fuel-explorer/schema/fuel_explorer.schema.graphql +++ b/examples/fuel-explorer/fuel-explorer/schema/fuel_explorer.schema.graphql @@ -100,53 +100,53 @@ enum OutputLabel { Unknown } -type Witness { - data: Blob! @virtual +type Witness @entity(virtual: true) { + data: Blob! } -type InstructionResult { - reason: PanicReason! @virtual +type InstructionResult @entity(virtual: true) { + reason: PanicReason! instruction: UInt4! } -type ProgramState { - return_type: ReturnType! @virtual +type ProgramState @entity(virtual: true) { + return_type: ReturnType! data: HexString! } -type DryRun { - tx: HexString! @virtual +type DryRun @entity(virtual: true) { + tx: HexString! utxo_validation: Boolean } -type TransactionIdFragment { +type TransactionIdFragment @entity { id: ID! hash: Bytes32! @indexed } -type UtxoId { +type UtxoId @entity { id: ID! tx_id: TxId! @indexed output_index: UInt4! } -type TxPointer { +type TxPointer @entity { id: ID! block_height: BlockHeight! tx_index: UInt8! } -type ContractIdFragment { +type ContractIdFragment @entity { id: ID! hash: Bytes32! @indexed } -type BlockIdFragment { +type BlockIdFragment @entity { id: ID! hash: Bytes32! @indexed } -type Genesis { +type Genesis @entity { id: ID! chain_config_hash: Bytes32! coins_root: Bytes32! @@ -156,7 +156,7 @@ type Genesis { label: ConsensusLabel! } -type PoA { +type PoA @entity { id: ID! # TODO: Is this important? The fact that signature is different # on almost every `PoA` implies that this type might be virtual? @@ -165,7 +165,7 @@ type PoA { label: ConsensusLabel! } -type Unknown { +type Unknown @entity { id: ID! is_unknown: Boolean! label: ConsensusLabel! @@ -173,7 +173,7 @@ type Unknown { union Consensus = Genesis | PoA | Unknown -type InputCoin { +type InputCoin @entity { id: ID! utxo_id: UtxoId! @indexed owner: Address! @indexed @@ -188,7 +188,7 @@ type InputCoin { is_coin: Boolean! } -type InputContract { +type InputContract @entity { id: ID! utxo_id: UtxoId! @indexed balance_root: Bytes32! @@ -199,7 +199,7 @@ type InputContract { is_contract: Boolean! } -type InputMessage { +type InputMessage @entity { id: ID! sender: Address! @indexed recipient: Address! @indexed @@ -215,14 +215,14 @@ type InputMessage { union Input = InputCoin | InputContract | InputMessage -type StorageSlot { +type StorageSlot @entity { id: ID! key: Bytes32! value: Bytes32! } -type CallReceipt { - contract_id: ContractId! @virtual +type CallReceipt @entity(virtual: true) { + contract_id: ContractId! # `recipient` has a different type of different `Reciept` members, so # we make it something more generic: `Identity`. recipient: Identity! @@ -238,8 +238,8 @@ type CallReceipt { is_call: Boolean! } -type ReturnDataReceipt { - contract_id: ContractId! @virtual +type ReturnDataReceipt @entity(virtual: true) { + contract_id: ContractId! ptr: UInt8! len: UInt8! digest: Bytes32! @@ -251,8 +251,8 @@ type ReturnDataReceipt { is_return_data: Boolean! } -type PanicReceipt { - contract_id: ContractId @virtual +type PanicReceipt @entity(virtual: true) { + contract_id: ContractId reason: InstructionResult pc: UInt8! # `is` is a reserved keyword in PostgreSQL. @@ -261,8 +261,8 @@ type PanicReceipt { is_panic: Boolean! } -type RevertReceipt { - contract_id: ContractId! @virtual +type RevertReceipt @entity(virtual: true) { + contract_id: ContractId! ra: UInt8! pc: UInt8! # `is` is a reserved keyword in PostgreSQL. @@ -271,8 +271,8 @@ type RevertReceipt { is_revert: Boolean! } -type LogReceipt { - contract_id: ContractId! @virtual +type LogReceipt @entity(virtual: true) { + contract_id: ContractId! ra: UInt8! rb: UInt8! rc: UInt8! @@ -284,8 +284,8 @@ type LogReceipt { is_log: Boolean! } -type LogDataReceipt { - contract_id: ContractId! @virtual +type LogDataReceipt @entity(virtual: true) { + contract_id: ContractId! ra: UInt8! rb: UInt8! ptr: UInt8! @@ -299,8 +299,8 @@ type LogDataReceipt { is_log_data: Boolean! } -type ReturnReceipt { - contract_id: ContractId! @virtual +type ReturnReceipt @entity(virtual: true) { + contract_id: ContractId! val: UInt8! pc: UInt8! # `is` is a reserved keyword in PostgreSQL. @@ -309,8 +309,8 @@ type ReturnReceipt { is_return: Boolean! } -type TransferReceipt { - contract_id: ContractId! @virtual +type TransferReceipt @entity(virtual: true) { + contract_id: ContractId! # `recipient` has a different type of different `Reciept` members, so # we make it something more generic: `Identity`. recipient: Identity! @@ -323,8 +323,8 @@ type TransferReceipt { is_transfer: Boolean! } -type TransferOutReceipt { - contract_id: ContractId! @virtual +type TransferOutReceipt @entity(virtual: true) { + contract_id: ContractId! # `recipient` has a different type of different `Reciept` members, so # we make it something more generic: `Identity`. recipient: Identity! @@ -337,15 +337,15 @@ type TransferOutReceipt { is_transfer_out: Boolean! } -type ScriptResultReceipt { - result: ScriptExecutionResult! @virtual +type ScriptResultReceipt @entity(virtual: true) { + result: ScriptExecutionResult! gas_used: UInt8! label: ReceiptLabel! is_script_result: Boolean! } -type MessageOutReceipt { - sender: Address! @virtual +type MessageOutReceipt @entity(virtual: true) { + sender: Address! # `recipient` has a different type of different `Reciept` members, so # we make it something more generic: `Identity`. recipient: Identity! @@ -371,7 +371,7 @@ union Receipt = | ScriptResultReceipt | MessageOutReceipt -type VariableOutput { +type VariableOutput @entity { id: ID! # `to` is a reserved keyword in PostgreSQL. recipient: Address! @indexed @@ -381,7 +381,7 @@ type VariableOutput { label: OutputLabel! } -type ChangeOutput { +type ChangeOutput @entity { id: ID! # `to` is a reserved keyword in PostgreSQL. recipient: Address! @indexed @@ -391,7 +391,7 @@ type ChangeOutput { label: OutputLabel! } -type ContractOutput { +type ContractOutput @entity { id: ID! input_index: Int8! balance_root: Bytes32! @@ -400,7 +400,7 @@ type ContractOutput { label: OutputLabel! } -type CoinOutput { +type CoinOutput @entity { id: ID! # `to` is a reserved keyword in PostgreSQL. recipient: Address! @indexed @@ -410,13 +410,13 @@ type CoinOutput { label: OutputLabel! } -type UnknownOutput { +type UnknownOutput @entity { id: ID! is_unknown: Boolean! label: OutputLabel! } -type ContractCreated { +type ContractCreated @entity { id: ID! contract: ContractIdFragment! @indexed state_root: Bytes32! @@ -424,7 +424,7 @@ type ContractCreated { label: OutputLabel! } -type MessageOutput { +type MessageOutput @entity { id: ID! amount: UInt8! recipient: Address! @indexed @@ -441,7 +441,7 @@ union Output = # `Create` is a reserved word in SQL so we append the suffix `Transaction` to these # transaction type names. -type CreateTransaction { +type CreateTransaction @entity { id: ID! gas_price: UInt8! gas_limit: UInt8! @@ -460,7 +460,7 @@ type CreateTransaction { label: TransactionLabel! } -type ScriptTransaction { +type ScriptTransaction @entity { id: ID! gas_price: UInt8! gas_limit: UInt8! @@ -478,7 +478,7 @@ type ScriptTransaction { label: TransactionLabel! } -type MintTransaction { +type MintTransaction @entity { id: ID! tx_pointer: TxPointer! outputs: [Output!] @@ -489,26 +489,23 @@ type MintTransaction { label: TransactionLabel! } -union Transaction = - CreateTransaction - | ScriptTransaction - | MintTransaction +union Transaction = CreateTransaction | ScriptTransaction | MintTransaction -type SubmittedStatus { +type SubmittedStatus @entity { id: ID! time: UInt8! label: TransactionStatusLabel! is_submitted: Boolean! } -type SqueezedOutStatus { +type SqueezedOutStatus @entity { id: ID! reason: Charfield! label: TransactionStatusLabel! is_squeezed_out: Boolean! } -type FailureStatus { +type FailureStatus @entity { id: ID! block: BlockIdFragment! time: UInt8! @@ -518,7 +515,7 @@ type FailureStatus { is_failure: Boolean! } -type SuccessStatus { +type SuccessStatus @entity { id: ID! time: UInt8! block: BlockIdFragment! @@ -527,7 +524,7 @@ type SuccessStatus { is_success: Boolean! } -type UnknownStatus { +type UnknownStatus @entity { id: ID! label: TransactionStatusLabel! is_unknown: Boolean! @@ -540,7 +537,7 @@ union TransactionStatus = | SuccessStatus | UnknownStatus -type Header { +type Header @entity { id: ID! block_id: BlockId! da_height: UInt8! @@ -554,7 +551,7 @@ type Header { application_hash: Bytes32! } -type Block { +type Block @entity { id: ID! block_id: BlockId! @indexed header: Header! @indexed @@ -562,7 +559,7 @@ type Block { transactions: [TransactionIdFragment!] } -type NodeInfo { +type NodeInfo @entity { id: ID! utxo_validation: Boolean! vm_backtrace: Boolean! @@ -572,7 +569,7 @@ type NodeInfo { node_version: Charfield! } -type ConsensusParameters { +type ConsensusParameters @entity { id: ID! contract_max_size: UInt8! max_inputs: UInt8! @@ -589,7 +586,7 @@ type ConsensusParameters { chain_id: UInt8! } -type ChainInfo { +type ChainInfo @entity { id: ID! base_chain_height: UInt4! name: Charfield! @@ -598,7 +595,7 @@ type ChainInfo { consensus_parameters: ConsensusParameters! } -type Coin { +type Coin @entity { id: ID! amount: UInt8! block_created: UInt4! @@ -608,7 +605,7 @@ type Coin { owner: Address! @indexed } -type MessageCoin { +type MessageCoin @entity { id: ID! amount: UInt8! sender: Address! @indexed @@ -617,7 +614,7 @@ type MessageCoin { da_height: UInt8! } -type Contract { +type Contract @entity { id: ID! contract_id: ContractId! @indexed bytecode: HexString! diff --git a/examples/hello-world-native/hello-indexer-native/schema/hello_indexer_native.schema.graphql b/examples/hello-world-native/hello-indexer-native/schema/hello_indexer_native.schema.graphql index 3a7e4990f..40d63135d 100644 --- a/examples/hello-world-native/hello-indexer-native/schema/hello_indexer_native.schema.graphql +++ b/examples/hello-world-native/hello-indexer-native/schema/hello_indexer_native.schema.graphql @@ -1,18 +1,18 @@ # Calling this `Greeter` so as to not clash with `Person` in the contract -type Greeter { - id: ID! - name: Charfield! - first_seen: UInt8! - last_seen: UInt8! - visits: Blob! +type Greeter @entity { + id: ID! + name: Charfield! + first_seen: UInt8! + last_seen: UInt8! + visits: Blob! } # Calling this `Salutation` so as to not clash with `Greeting` in the contract -type Salutation { - id: ID! - message_hash: Bytes32! - message: Charfield! - greeter: Greeter! - first_seen: UInt8! - last_seen: UInt8! +type Salutation @entity { + id: ID! + message_hash: Bytes32! + message: Charfield! + greeter: Greeter! + first_seen: UInt8! + last_seen: UInt8! } diff --git a/examples/hello-world/hello-indexer/schema/hello_indexer.schema.graphql b/examples/hello-world/hello-indexer/schema/hello_indexer.schema.graphql index 3a7e4990f..40d63135d 100644 --- a/examples/hello-world/hello-indexer/schema/hello_indexer.schema.graphql +++ b/examples/hello-world/hello-indexer/schema/hello_indexer.schema.graphql @@ -1,18 +1,18 @@ # Calling this `Greeter` so as to not clash with `Person` in the contract -type Greeter { - id: ID! - name: Charfield! - first_seen: UInt8! - last_seen: UInt8! - visits: Blob! +type Greeter @entity { + id: ID! + name: Charfield! + first_seen: UInt8! + last_seen: UInt8! + visits: Blob! } # Calling this `Salutation` so as to not clash with `Greeting` in the contract -type Salutation { - id: ID! - message_hash: Bytes32! - message: Charfield! - greeter: Greeter! - first_seen: UInt8! - last_seen: UInt8! +type Salutation @entity { + id: ID! + message_hash: Bytes32! + message: Charfield! + greeter: Greeter! + first_seen: UInt8! + last_seen: UInt8! } diff --git a/packages/fuel-indexer-database/database-types/src/lib.rs b/packages/fuel-indexer-database/database-types/src/lib.rs index 83c3614f9..4d92221d2 100644 --- a/packages/fuel-indexer-database/database-types/src/lib.rs +++ b/packages/fuel-indexer-database/database-types/src/lib.rs @@ -1267,7 +1267,7 @@ mod tests { #[test] fn test_can_create_well_formed_table_and_table_components_when_passed_typedef() { let schema = r#" -type Person { +type Person @entity { id: ID! name: Charfield! @unique age: UInt1! @@ -1345,7 +1345,7 @@ type Person { #[test] fn test_can_create_well_formed_column_from_field_defintion() { let schema = r#" -type Person { +type Person @entity { id: ID! name: Charfield! @unique age: UInt1! @@ -1397,12 +1397,12 @@ type Person { #[test] fn test_can_create_well_formed_join_table_from_m2m_relationship() { let schema = r#" -type Account { +type Account @entity { id: ID! index: UInt8! } -type Wallet { +type Wallet @entity { id: ID! account: [Account!]! } diff --git a/packages/fuel-indexer-graphql/src/graphql.rs b/packages/fuel-indexer-graphql/src/graphql.rs index df12007b2..cf1942ebf 100644 --- a/packages/fuel-indexer-graphql/src/graphql.rs +++ b/packages/fuel-indexer-graphql/src/graphql.rs @@ -754,13 +754,13 @@ mod tests { }; let schema = r#" -type Block { +type Block @entity { id: ID! height: UInt8! timestamp: Int8! } -type Tx { +type Tx @entity { id: ID! timestamp: Int8! block: Block diff --git a/packages/fuel-indexer-lib/src/graphql/mod.rs b/packages/fuel-indexer-lib/src/graphql/mod.rs index dac247bac..23344cfda 100644 --- a/packages/fuel-indexer-lib/src/graphql/mod.rs +++ b/packages/fuel-indexer-lib/src/graphql/mod.rs @@ -44,7 +44,7 @@ impl IndexMetadata { pub fn schema_fragment() -> &'static str { r#" -type IndexMetadataEntity { +type IndexMetadataEntity @entity { id: ID! time: UInt8! block_height: UInt8! diff --git a/packages/fuel-indexer-lib/src/graphql/parser.rs b/packages/fuel-indexer-lib/src/graphql/parser.rs index 8cfee5748..72a3d728d 100644 --- a/packages/fuel-indexer-lib/src/graphql/parser.rs +++ b/packages/fuel-indexer-lib/src/graphql/parser.rs @@ -344,6 +344,17 @@ impl ParsedGraphQLSchema { TypeKind::Object(o) => { let obj_name = t.node.name.to_string(); + // Only parse `TypeDefinition`s with the `@entity` directive. + let is_entity = t + .node + .directives + .iter() + .any(|d| d.node.name.to_string() == "entity"); + + if !is_entity { + continue; + } + type_defs.insert(obj_name.clone(), t.node.clone()); objects.insert(obj_name.clone(), o.clone()); parsed_typedef_names.insert(t.node.name.to_string()); @@ -367,13 +378,14 @@ impl ParsedGraphQLSchema { .insert(obj_name.clone(), t.node.clone()); } - let is_virtual = field + let is_virtual = &t .node .directives .iter() - .any(|d| d.node.name.to_string() == "virtual"); + .flat_map(|d| d.node.arguments.clone()) + .any(|t| t.0.node == "virtual"); - if is_virtual { + if *is_virtual { virtual_type_names.insert(obj_name.clone()); } @@ -829,42 +841,42 @@ enum AccountLabel { SECONDARY } -type Account { +type Account @entity { id: ID! address: Address! label: AccountLabel } -type User { +type User @entity { id: ID! account: Account! username: Charfield! } -type Loser { +type Loser @entity { id: ID! account: Account! age: UInt8! } -type Metadata { - count: UInt8! @virtual +type Metadata @entity(virtual: true) { + count: UInt8! } union Person = User | Loser -type Wallet { +type Wallet @entity { id: ID! accounts: [Account!]! } -type Safe { +type Safe @entity { id: ID! account: [Account!]! } -type Vault { +type Vault @entity { id: ID! label: Charfield! user: [User!]! diff --git a/packages/fuel-indexer-macros/src/decoder.rs b/packages/fuel-indexer-macros/src/decoder.rs index 80146f67b..047ed9000 100644 --- a/packages/fuel-indexer-macros/src/decoder.rs +++ b/packages/fuel-indexer-macros/src/decoder.rs @@ -85,7 +85,7 @@ impl Decoder for ImplementationDecoder { let obj_field_names = parsed .object_field_mappings() .get(&obj_name) - .expect("TypeDefinition not found in parsed GraphQL schema.") + .unwrap_or_else(|| panic!("TypeDefinition '{obj_name}' not found in parsed GraphQL schema.")) .iter() .map(|(k, _v)| k.to_owned()) .collect::>(); @@ -960,13 +960,13 @@ impl From for TokenStream { mod tests { use super::*; - use async_graphql_parser::types::{BaseType, ObjectType, Type}; + use async_graphql_parser::types::{BaseType, ConstDirective, ObjectType, Type}; use fuel_indexer_lib::graphql::GraphQLSchema; #[test] fn test_can_create_object_decoder_containing_expected_tokens_from_object_typedef() { let schema = r#" -type Person { +type Person @entity { id: ID! name: Charfield! age: UInt1! @@ -1005,7 +1005,16 @@ type Person { implements: vec![], fields, }), - directives: vec![], + directives: vec![Positioned { + pos: Pos::default(), + node: ConstDirective { + name: Positioned { + pos: Pos::default(), + node: Name::new("entity"), + }, + arguments: vec![], + }, + }], }; let schema = ParsedGraphQLSchema::new( @@ -1036,12 +1045,12 @@ type Person { fn test_can_create_object_decoder_containing_expected_tokens_from_object_typedef_containing_m2m_relationship( ) { let schema = r#" -type Account { +type Account @entity { id: ID! index: UInt8! } -type Wallet { +type Wallet @entity { id: ID! account: [Account!]! } @@ -1102,7 +1111,16 @@ type Wallet { implements: vec![], fields, }), - directives: vec![], + directives: vec![Positioned { + pos: Pos::default(), + node: ConstDirective { + name: Positioned { + pos: Pos::default(), + node: Name::new("entity"), + }, + arguments: vec![], + }, + }], }; let schema = ParsedGraphQLSchema::new( diff --git a/packages/fuel-indexer-tests/components/indices/fuel-indexer-test/schema/fuel_indexer_test.graphql b/packages/fuel-indexer-tests/components/indices/fuel-indexer-test/schema/fuel_indexer_test.graphql index 48dcf0b15..fd031fb0e 100644 --- a/packages/fuel-indexer-tests/components/indices/fuel-indexer-test/schema/fuel_indexer_test.graphql +++ b/packages/fuel-indexer-tests/components/indices/fuel-indexer-test/schema/fuel_indexer_test.graphql @@ -1,325 +1,321 @@ -type PingEntity { - id: ID! - value: UInt8! - message: Charfield! +type PingEntity @entity { + id: ID! + value: UInt8! + message: Charfield! } -type PungEntity { - id: ID! - value: UInt8! - is_pung: Boolean! - pung_from: Identity! +type PungEntity @entity { + id: ID! + value: UInt8! + is_pung: Boolean! + pung_from: Identity! } -type U16Entity { - id: ID! - value1: UInt16! - value2: Int16! +type U16Entity @entity { + id: ID! + value1: UInt16! + value2: Int16! } -type PongEntity { - id: ID! - value: UInt8! +type PongEntity @entity { + id: ID! + value: UInt8! } -type BlockEntity { - id: ID! - height: UInt8! - timestamp: Int8! +type BlockEntity @entity { + id: ID! + height: UInt8! + timestamp: Int8! } - -type TxEntity { - id: ID! - block: BlockEntity! - input_data: Json! - timestamp: Int8! +type TxEntity @entity { + id: ID! + block: BlockEntity! + input_data: Json! + timestamp: Int8! } -type TransferEntity { - id: ID! - contract_id: ContractId! - # 'to' is a reserved SQL word, so using 'recipient' - recipient: ContractId! - amount: UInt8! - asset_id: AssetId! +type TransferEntity @entity { + id: ID! + contract_id: ContractId! + # 'to' is a reserved SQL word, so using 'recipient' + recipient: ContractId! + amount: UInt8! + asset_id: AssetId! } -type TransferOutEntity { - id: ID! - contract_id: ContractId! - recipient: Address! - amount: UInt8! - asset_id: AssetId! +type TransferOutEntity @entity { + id: ID! + contract_id: ContractId! + recipient: Address! + amount: UInt8! + asset_id: AssetId! } -type LogEntity { - id: ID! - contract_id: ContractId! - ra: UInt8! - rb: UInt8! +type LogEntity @entity { + id: ID! + contract_id: ContractId! + ra: UInt8! + rb: UInt8! } -type ScriptResultEntity { - id: ID! - result: UInt8! - gas_used: UInt8! - blob: Blob! +type ScriptResultEntity @entity { + id: ID! + result: UInt8! + gas_used: UInt8! + blob: Blob! } -type MessageOutEntity { - id: ID! - message_id: MessageId! - sender: Address! - recipient: Address! - amount: UInt8! - nonce: Nonce! - len: UInt8! - digest: Bytes32! +type MessageOutEntity @entity { + id: ID! + message_id: MessageId! + sender: Address! + recipient: Address! + amount: UInt8! + nonce: Nonce! + len: UInt8! + digest: Bytes32! } -type OptionEntity { - id: ID! - int_required: UInt8! - int_optional_some: UInt8 - addr_optional_none: Address +type OptionEntity @entity { + id: ID! + int_required: UInt8! + int_optional_some: UInt8 + addr_optional_none: Address } -type TupleEntity { - id: ID! - complex_a: Charfield! - complex_b: UInt8! - simple_a: Charfield! +type TupleEntity @entity { + id: ID! + complex_a: Charfield! + complex_b: UInt8! + simple_a: Charfield! } -type MessageEntity { - id: ID! - message: Charfield! +type MessageEntity @entity { + id: ID! + message: Charfield! } -type CallEntity { - id: ID! - contract_id: ContractId! - callee: ContractId! - asset_id: AssetId! - gas: UInt8! - fn_name: Charfield! - amount: UInt8! +type CallEntity @entity { + id: ID! + contract_id: ContractId! + callee: ContractId! + asset_id: AssetId! + gas: UInt8! + fn_name: Charfield! + amount: UInt8! } -type PanicEntity { - id: ID! - contract_id: ContractId! - reason: UInt4! +type PanicEntity @entity { + id: ID! + contract_id: ContractId! + reason: UInt4! } -type RevertEntity { - id: ID! - contract_id: ContractId! - error_val: UInt8! +type RevertEntity @entity { + id: ID! + contract_id: ContractId! + error_val: UInt8! } -type Genre { - id: ID! - name: Charfield! +type Genre @entity { + id: ID! + name: Charfield! } -type Person { - id: ID! - name: Charfield! +type Person @entity { + id: ID! + name: Charfield! } -type Planet { - id: ID! - name: Charfield! +type Planet @entity { + id: ID! + name: Charfield! } -type Continent { - id: ID! - name: Charfield! - planet: Planet! +type Continent @entity { + id: ID! + name: Charfield! + planet: Planet! } -type Country { - id: ID! - name: Charfield! - continent: Continent! +type Country @entity { + id: ID! + name: Charfield! + continent: Continent! } -type Region { - id: ID! - name: Charfield! - country: Country! +type Region @entity { + id: ID! + name: Charfield! + country: Country! } -type City { - id: ID! - name: Charfield! - region: Region! +type City @entity { + id: ID! + name: Charfield! + region: Region! } -type Author { - id: ID! - name: Charfield! - genre: Genre! +type Author @entity { + id: ID! + name: Charfield! + genre: Genre! } -type Library { - id: ID! - name: Charfield! - city: City! +type Library @entity { + id: ID! + name: Charfield! + city: City! } -type Book { - id: ID! - name: Charfield! - author: Author! @indexed - library: Library! - genre: Genre! +type Book @entity { + id: ID! + name: Charfield! + author: Author! @indexed + library: Library! + genre: Genre! } -type Sponsor { - id: ID! - name: Charfield! @unique - amount: UInt8! - representative: Person! +type Sponsor @entity { + id: ID! + name: Charfield! @unique + amount: UInt8! + representative: Person! } # TODO: Fix nullable foreign keys; there seems to be issues during codegen -type BookClub { - id: ID! - book: Book! - member: Person! - corporate_sponsor: Sponsor! @join(on:name) +type BookClub @entity { + id: ID! + book: Book! + member: Person! + corporate_sponsor: Sponsor! @join(on: name) } -type Municipality { - id: ID! - name: Charfield! @unique +type Municipality @entity { + id: ID! + name: Charfield! @unique } -type SportsTeam { - id: ID! - name: Charfield! - municipality: Municipality! @join(on:name) +type SportsTeam @entity { + id: ID! + name: Charfield! + municipality: Municipality! @join(on: name) } -type InnerFilterEntity { - id: ID! - inner_foo: Charfield! - inner_bar: UInt8! - inner_baz: UInt8! +type InnerFilterEntity @entity { + id: ID! + inner_foo: Charfield! + inner_bar: UInt8! + inner_baz: UInt8! } -type FilterEntity { - id: ID! - foola: Charfield! - maybe_null_bar: UInt8 - bazoo: UInt8! - inner_entity: InnerFilterEntity! +type FilterEntity @entity { + id: ID! + foola: Charfield! + maybe_null_bar: UInt8 + bazoo: UInt8! + inner_entity: InnerFilterEntity! } -type EnumError { - id: ID! - contract_id: ContractId! - error_val: UInt8! +type EnumError @entity { + id: ID! + contract_id: ContractId! + error_val: UInt8! } -type ExplorerEntity { - id: ID! - nonce: Nonce! - time: Tai64Timestamp - hex: HexString - sig: Signature! - bytes: Bytes64! +type ExplorerEntity @entity { + id: ID! + nonce: Nonce! + time: Tai64Timestamp + hex: HexString + sig: Signature! + bytes: Bytes64! } -enum EnumEntity { - One - Two - Three +enum EnumEntity @entity { + One + Two + Three } -type ComplexEnumEntity { - id: ID! - one: EnumEntity +type ComplexEnumEntity @entity { + id: ID! + one: EnumEntity } -type VirtualEntity { - name: Charfield @virtual - size: UInt1! +type VirtualEntity @entity(virtual: true) { + name: Charfield + size: UInt1! } - -type UsesVirtualEntity { - id: ID! - name: Charfield! - no_table: VirtualEntity! +type UsesVirtualEntity @entity { + id: ID! + name: Charfield! + no_table: VirtualEntity! } enum UnionType { - A - B - C + A + B + C } -type IndexableUnionA { - id: ID! - a: UInt8! - union_type: UnionType! +type IndexableUnionA @entity { + id: ID! + a: UInt8! + union_type: UnionType! } -type IndexableUnionB { - id: ID! - b: UInt8! - union_type: UnionType! +type IndexableUnionB @entity { + id: ID! + b: UInt8! + union_type: UnionType! } -type IndexableUnionC { - id: ID! - c: UInt8! - union_type: UnionType! +type IndexableUnionC @entity { + id: ID! + c: UInt8! + union_type: UnionType! } -type VirtualUnionA { - a: UInt8! @virtual - union_type: UnionType! +type VirtualUnionA @entity(virtual: true) { + a: UInt8! + union_type: UnionType! } -type VirtualUnionB { - b: UInt8! @virtual - union_type: UnionType! +type VirtualUnionB @entity(virtual: true) { + b: UInt8! + union_type: UnionType! } -type VirtualUnionC { - c: UInt8! @virtual - union_type: UnionType! +type VirtualUnionC @entity(virtual: true) { + c: UInt8! + union_type: UnionType! } union IndexableUnionEntity = IndexableUnionA | IndexableUnionB | IndexableUnionC union VirtualUnionEntity = VirtualUnionA | VirtualUnionB | VirtualUnionC -type VirtualUnionContainerEntity { - id: ID! - union_entity: VirtualUnionEntity - union_type: UnionType! +type VirtualUnionContainerEntity @entity { + id: ID! + union_entity: VirtualUnionEntity + union_type: UnionType! } - -type ListFKType { - id: ID! - value: UInt8! +type ListFKType @entity { + id: ID! + value: UInt8! } -type ListTypeEntity { - id: ID! - foo: Charfield! - required_all: [ListFKType!]! - optional_inner: [Charfield]! - optional_outer: [UInt8!] - optional_all: [UInt8] - virtual_optional_inner: [VirtualEntity]! - enum_required_all: [EnumEntity!]! +type ListTypeEntity @entity { + id: ID! + foo: Charfield! + required_all: [ListFKType!]! + optional_inner: [Charfield]! + optional_outer: [UInt8!] + optional_all: [UInt8] + virtual_optional_inner: [VirtualEntity]! + enum_required_all: [EnumEntity!]! } - diff --git a/packages/fuel-indexer-tests/components/indices/simple-wasm/bad_simple_wasm.graphql b/packages/fuel-indexer-tests/components/indices/simple-wasm/bad_simple_wasm.graphql index dcf102053..24363e035 100644 --- a/packages/fuel-indexer-tests/components/indices/simple-wasm/bad_simple_wasm.graphql +++ b/packages/fuel-indexer-tests/components/indices/simple-wasm/bad_simple_wasm.graphql @@ -1,10 +1,10 @@ -type Thing1 { - id: ID! - account: Address! +type Thing1 @entity { + id: ID! + account: Address! } -type Thing2 { - id: ID! - account: Address! @indexed - hash: Bytes32! @indexed +type Thing2 @entity { + id: ID! + account: Address! @indexed + hash: Bytes32! @indexed } diff --git a/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/schema.graphql b/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/schema.graphql index dcf102053..24363e035 100644 --- a/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/schema.graphql +++ b/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/schema.graphql @@ -1,10 +1,10 @@ -type Thing1 { - id: ID! - account: Address! +type Thing1 @entity { + id: ID! + account: Address! } -type Thing2 { - id: ID! - account: Address! @indexed - hash: Bytes32! @indexed +type Thing2 @entity { + id: ID! + account: Address! @indexed + hash: Bytes32! @indexed } diff --git a/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/simple_wasm.graphql b/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/simple_wasm.graphql index dcf102053..24363e035 100644 --- a/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/simple_wasm.graphql +++ b/packages/fuel-indexer-tests/components/indices/simple-wasm/schema/simple_wasm.graphql @@ -1,10 +1,10 @@ -type Thing1 { - id: ID! - account: Address! +type Thing1 @entity { + id: ID! + account: Address! } -type Thing2 { - id: ID! - account: Address! @indexed - hash: Bytes32! @indexed +type Thing2 @entity { + id: ID! + account: Address! @indexed + hash: Bytes32! @indexed } diff --git a/packages/fuel-indexer-tests/components/indices/simple-wasm/simple_wasm.wasm b/packages/fuel-indexer-tests/components/indices/simple-wasm/simple_wasm.wasm index b5cebab24..8251a7037 100644 Binary files a/packages/fuel-indexer-tests/components/indices/simple-wasm/simple_wasm.wasm and b/packages/fuel-indexer-tests/components/indices/simple-wasm/simple_wasm.wasm differ diff --git a/packages/fuel-indexer-tests/tests/integration/graphql_schema.rs b/packages/fuel-indexer-tests/tests/integration/graphql_schema.rs index 6036a7310..caad17eb2 100644 --- a/packages/fuel-indexer-tests/tests/integration/graphql_schema.rs +++ b/packages/fuel-indexer-tests/tests/integration/graphql_schema.rs @@ -10,13 +10,13 @@ use std::collections::HashMap; fn generate_schema() -> IndexerSchema { let schema = r#" -type Thing1 { +type Thing1 @entity { id: ID! account: Address! huge_number: UInt16! } -type Thing2 { +type Thing2 @entity { id: ID! account: Address! hash: Bytes32! diff --git a/plugins/forc-index/src/defaults.rs b/plugins/forc-index/src/defaults.rs index 5398ce473..df4d62742 100644 --- a/plugins/forc-index/src/defaults.rs +++ b/plugins/forc-index/src/defaults.rs @@ -201,13 +201,13 @@ pub mod {indexer_name}_index_mod {{ } pub fn default_indexer_schema() -> String { - r#"type Block { + r#"type Block @entity { id: ID! height: UInt8! hash: Bytes32! @unique } -type Transaction { +type Transaction @entity { id: ID! block: Block! @join(on:hash) hash: Bytes32! @unique