Skip to content

Commit

Permalink
sunset of hosted (graphprotocol#1680)
Browse files Browse the repository at this point in the history
* sunset of hosted

* format

* update snapshot

* Fix missing refs

* Update `init` snapshot

* Remove hosted service from readme, add more relevant information

* Fix lint

---------

Co-authored-by: Etienne Donneger <[email protected]>
Co-authored-by: YaroShkvorets <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2024
1 parent bf43cbf commit 08914a8
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 606 deletions.
18 changes: 18 additions & 0 deletions .changeset/gold-deers-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@graphprotocol/graph-cli': minor
---

Breaking changes to the CLI to prepare for the sunset of the hosted service.

- `graph auth`
- Removed `--product` flag
- Removed `--studio` flag
- Removed `node` argument
- `graph deploy`
- Removed `--product` flag
- Removed `--studio` flag
- Removed `--from-hosted-service` flag
- `graph init`
- Removed `--product` flag
- Removed `--studio` flag
- Removed `--allow-simple-name` flag
20 changes: 14 additions & 6 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@ As of today, the command line interface supports the following commands:
The Graph CLI takes a subgraph manifest (defaults to `subgraph.yaml`) with references to:

- A GraphQL schema,
- Smart contract ABIs, and
- Mappings written in AssemblyScript.
- Smart contract ABIs,
- Mappings written in AssemblyScript for traditional subgraphs,
- Substreams package and triggers for substreams-based subgraphs

It compiles the mappings to WebAssembly, builds a ready-to-use version of the subgraph saved to IPFS
or a local directory for debugging, and deploys the subgraph to a
[Graph Node](https://github.com/graphprotocol/graph-node).
[Graph Node](https://github.com/graphprotocol/graph-node) instance or
[Subgraph Studio](https://thegraph.com/studio/). Additionally it allows you to publish your subgraph
to the decentralized network directly, making it available for indexing via
[Graph Explorer](https://thegraph.com/explorer)

## Installation

Expand Down Expand Up @@ -73,11 +77,15 @@ Use one of the following commands depending on your distribution:

The Graph CLI can be used with a local or self-hosted
[Graph Node](https://github.com/graphprotocol/graph-node) or with the
[Hosted Service](https://thegraph.com/explorer/). To help you get going, there are
[quick start guides](https://thegraph.com/docs/en/developer/quick-start/) available for both.
[Subgraph Studio](https://thegraph.com/studio/). To help you get going, there are
[quick start guides](https://thegraph.com/docs/en/quick-start/) available for both.

Additionally, you can use Graph CLI to
[publish](https://thegraph.com/docs/en/quick-start/#publishing-from-the-cli) your subgraph to the
decentralized network directly.

If you are ready to dive into the details of building a subgraph from scratch, there is a
[detailed walkthrough](https://thegraph.com/docs/en/developer/create-subgraph-hosted/) for that as
[detailed walkthrough](https://thegraph.com/docs/en/developing/creating-a-subgraph/) for that as
well, along with API documentation for the
[AssemblyScript API](https://thegraph.com/docs/en/developer/assemblyscript-api/).

Expand Down
76 changes: 3 additions & 73 deletions packages/cli/src/command-helpers/node.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,22 @@
import { URL } from 'url';
import { print } from 'gluegun';
import { GRAPH_CLI_SHARED_HEADERS } from '../constants';

export const SUBGRAPH_STUDIO_URL = 'https://api.studio.thegraph.com/deploy/';
const HOSTED_SERVICE_URL = 'https://api.thegraph.com/deploy/';
const HOSTED_SERVICE_INDEX_NODE_URL = 'https://api.thegraph.com/index-node/graphql';

export const validateNodeUrl = (node: string) => new URL(node);

export const normalizeNodeUrl = (node: string) => new URL(node).toString();

export function chooseNodeUrl({
product,
studio,
node,
allowSimpleName,
}: {
product: string | undefined;
studio: boolean | undefined;
node?: string;
allowSimpleName?: boolean;
}) {
export function chooseNodeUrl({ node }: { node?: string }) {
if (node) {
try {
validateNodeUrl(node);
return { node };
} catch (e) {
print.error(`Graph node "${node}" is invalid: ${e.message}`);
process.exit(1);
}
} else {
if (studio) {
product = 'subgraph-studio';
}
switch (product) {
case 'subgraph-studio':
node = SUBGRAPH_STUDIO_URL;
break;
case 'hosted-service':
node = HOSTED_SERVICE_URL;
break;
}
}
if (node?.match(/studio/) || product === 'subgraph-studio') {
allowSimpleName = true;
}
return { node, allowSimpleName };
}

export async function getHostedServiceSubgraphId({
subgraphName,
}: {
subgraphName: string;
}): Promise<{
subgraph: string;
synced: boolean;
health: 'healthy' | 'unhealthy' | 'failed';
}> {
const response = await fetch(HOSTED_SERVICE_INDEX_NODE_URL, {
method: 'POST',
body: JSON.stringify({
query: /* GraphQL */ `
query GraphCli_getSubgraphId($subgraphName: String!) {
indexingStatusForCurrentVersion(subgraphName: $subgraphName) {
subgraph
synced
health
}
}
`,
variables: {
subgraphName,
},
}),
headers: {
'content-type': 'application/json',
...GRAPH_CLI_SHARED_HEADERS,
},
});

const { data, errors } = await response.json();

if (errors) {
throw new Error(errors[0].message);
}

if (!data.indexingStatusForCurrentVersion) {
throw new Error(`Subgraph "${subgraphName}" not found on the hosted service`);
}

return data.indexingStatusForCurrentVersion;
return { node: SUBGRAPH_STUDIO_URL };
}
17 changes: 0 additions & 17 deletions packages/cli/src/command-helpers/subgraph.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
export const validateSubgraphName = (
name: string,
{ allowSimpleName }: { allowSimpleName?: boolean },
) => {
if (allowSimpleName) {
return name;
}
if (name.split('/').length !== 2) {
throw new Error(`Subgraph name "${name}" needs to have the format "<PREFIX>/${name}".
When using the Hosted Service at https://thegraph.com, <PREFIX> is the
name of your GitHub user or organization.
You can bypass this check with --allow-simple-name.`);
}
};

export const getSubgraphBasename = (name: string) => {
const segments = name.split('/', 2);
return segments[segments.length - 1];
Expand Down
44 changes: 3 additions & 41 deletions packages/cli/src/commands/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,21 @@ export default class AuthCommand extends Command {
static description = 'Sets the deploy key to use when deploying to a Graph node.';

static args = {
node: Args.string(),
'deploy-key': Args.string(),
};

static flags = {
help: Flags.help({
char: 'h',
}),

product: Flags.string({
summary: 'Select a product for which to authenticate.',
options: ['subgraph-studio', 'hosted-service'],
deprecated: {
message:
'In next major version, this flag will be removed. By default we will deploy to the Graph Studio. Learn more about Sunrise of Decentralized Data https://thegraph.com/blog/unveiling-updated-sunrise-decentralized-data/',
},
}),
studio: Flags.boolean({
summary: 'Shortcut for "--product subgraph-studio".',
exclusive: ['product'],
deprecated: {
message:
'In next major version, this flag will be removed. By default we will deploy to the Graph Studio. Learn more about Sunrise of Decentralized Data https://thegraph.com/blog/unveiling-updated-sunrise-decentralized-data/',
},
}),
};

async run() {
const {
args: { node: nodeOrDeployKey, 'deploy-key': deployKeyFlag },
flags: { product, studio },
let {
args: { 'deploy-key': deployKey },
} = await this.parse(AuthCommand);

// if user specifies --product or --studio then deployKey is the first parameter
let node: string | undefined;
let deployKey = deployKeyFlag;
if (product || studio) {
({ node } = chooseNodeUrl({ product, studio, node }));
deployKey = nodeOrDeployKey;
} else {
node = nodeOrDeployKey;
}

// eslint-disable-next-line -- prettier has problems with ||=
node =
node ||
(await ux.prompt('Which product to initialize?', {
required: true,
}));
const { node } = chooseNodeUrl({});

// eslint-disable-next-line -- prettier has problems with ||=
deployKey =
Expand All @@ -68,10 +34,6 @@ export default class AuthCommand extends Command {
this.error('✖ Deploy key must not exceed 200 characters', { exit: 1 });
}

if (product === 'hosted-service' || node?.match(/api.thegraph.com/)) {
this.error('✖ The hosted service is deprecated', { exit: 1 });
}

try {
await saveDeployKey(node!, deployKey);
print.success(`Deploy key set for ${node}`);
Expand Down
Loading

0 comments on commit 08914a8

Please sign in to comment.