Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/validate-file-source-manifests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphprotocol/graph-cli': patch
---

Validate regular manifest fields when file data sources are present.
48 changes: 36 additions & 12 deletions packages/cli/src/subgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,31 @@ const buildCombinedWarning = (filename: string, warnings: immutable.List<any>) =

type ResolveFile = (path: string) => string;

const isFileDataSourceKind = (kind: unknown) =>
typeof kind === 'string' && (kind === 'file' || kind.startsWith('file/'));

const hasFileDataSources = (data: any) => {
const hasFileKind = (entries: any) =>
Array.isArray(entries) && entries.some(entry => isFileDataSourceKind(entry?.kind));

return hasFileKind(data?.dataSources) || hasFileKind(data?.templates);
};

const omitFileDataSources = (data: any) => {
if (data == null || typeof data !== 'object' || Array.isArray(data)) {
return data;
}

const omitFileKind = (entries: any) =>
Array.isArray(entries) ? entries.filter(entry => !isFileDataSourceKind(entry?.kind)) : entries;

return {
...data,
dataSources: omitFileKind(data.dataSources),
templates: omitFileKind(data.templates),
};
};

export default class Subgraph {
static async validate(data: any, protocol: any, { resolveFile }: { resolveFile: ResolveFile }) {
subgraphDebug.extend('validate')('Validating Subgraph with protocol %M', protocol);
Expand Down Expand Up @@ -266,26 +291,25 @@ More than one template named '${name}', template names must be unique.`,
subgraphDebug('Loading manifest from %s', filename);
const raw_data = await fs.readFile(filename, 'utf-8');
subgraphDebug('Checking for file data sources in %s', filename);
has_file_data_sources = raw_data.includes('kind: file');
subgraphDebug('Parsing manifest from %s', filename);
data = yaml.parse(raw_data);
has_file_data_sources = hasFileDataSources(data);
}

// Helper to resolve files relative to the subgraph manifest
const resolveFile: ResolveFile = maybeRelativeFile =>
path.resolve(path.dirname(filename), maybeRelativeFile);

// TODO: Validation for file data sources
if (!has_file_data_sources) {
subgraphDebug('Validating manifest from %s', filename);
const manifestErrors = await Subgraph.validate(data, protocol, {
resolveFile,
});

if (manifestErrors.size > 0) {
subgraphDebug('Manifest validation failed for %s', filename);
throwCombinedError(filename, manifestErrors);
}
// TODO: Complete schema validation for file data sources themselves.
const dataForValidation = has_file_data_sources ? omitFileDataSources(data) : data;
subgraphDebug('Validating manifest from %s', filename);
const manifestErrors = await Subgraph.validate(dataForValidation, protocol, {
resolveFile,
});

if (manifestErrors.size > 0) {
subgraphDebug('Manifest validation failed for %s', filename);
throwCombinedError(filename, manifestErrors);
}

const manifest = immutable.fromJS(data) as immutable.Map<any, any>;
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/tests/cli/__snapshots__/validation.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,20 @@ Types generated successfully
"
`;

exports[`Validation > File data source does not skip regular manifest validation 1`] = `
"- Load subgraph from subgraph.yaml
✖ Failed to load subgraph from subgraph.yaml: Error in subgraph.yaml:

Path: dataSources > 0 > network
Expected string, found number:
11155111
"
`;

exports[`Validation > File data source does not skip regular manifest validation 2`] = `1`;

exports[`Validation > File data source does not skip regular manifest validation 3`] = `""`;

exports[`Validation > Invalid @fulltext directive 1`] = `
"- Load subgraph from subgraph.yaml
✖ Failed to load subgraph from subgraph.yaml: Error in schema.graphql:
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/tests/cli/validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ describe('Validation', { concurrent: true, timeout: 60_000 }, () => {
exitCode: 0,
},
);
cliTest(
'File data source does not skip regular manifest validation',
['codegen', '--skip-migrations'],
'validation/file-data-source-invalid-manifest',
{
exitCode: 1,
},
);
cliTest(
'Invalid data source template',
['codegen', '--skip-migrations'],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"type": "event",
"name": "ExampleEvent",
"inputs": [{ "type": "string" }]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type MyEntity @entity(immutable: true) {
id: ID!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
specVersion: 0.0.5
repository: https://github.com/graphprotocol/test-subgraph
description: Test subgraph
schema:
file: ./schema.graphql
dataSources:
- kind: ethereum/contract
name: ExampleSubgraph
network: 11155111
source:
abi: ExampleContract
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
file: ./mapping.ts
entities:
- ExampleEntity
abis:
- name: ExampleContract
file: ./Abi.json
eventHandlers:
- event: ExampleEvent(string)
handler: handleExampleEvent
templates:
- kind: file/ipfs
name: IpfsContent
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
file: ./mapping.ts
entities:
- ExampleEntity
abis:
- name: ExampleContract
file: ./Abi.json
handler: handleIpfsContent