Socket
Socket
Sign inDemoInstall

@subql/apollo-links

Package Overview
Dependencies
Maintainers
2
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@subql/apollo-links - npm Package Compare versions

Comparing version 0.5.0 to 0.5.1-0

7

dist/agreementManager.d.ts

@@ -1,3 +0,3 @@

import { Logger } from "./logger";
import { Agreement } from "./types";
import { Logger } from './logger';
import { Agreement } from './types';
declare type Options = {

@@ -15,5 +15,6 @@ logger: Logger;

private interval;
private healthy;
private _init;
constructor(options: Options);
private refreshAgreements;
start(): void;
getNextAgreement(): Promise<Agreement | undefined>;

@@ -20,0 +21,0 @@ updateTokenById(agreementId: string, token: string): void;

@@ -9,2 +9,3 @@ "use strict";

this.interval = 300000;
this.healthy = true;
const { authUrl, projectId, logger } = options;

@@ -15,15 +16,22 @@ this.authUrl = authUrl;

this.nextAgreementIndex = 0;
this._init = this.refreshAgreements();
setInterval(this.refreshAgreements, this.interval);
}
async refreshAgreements() {
this.agreements = await (0, query_1.fetchAgreements)(this.authUrl, this.projectId);
try {
this.agreements = await (0, query_1.fetchAgreements)(this.authUrl, this.projectId);
this.healthy = true;
}
catch (e) {
this.logger.error(`fetchAgreements failed: ${String(e)}`);
this.healthy = false;
}
}
start() {
void this.refreshAgreements();
setInterval(this.refreshAgreements, this.interval);
}
async getNextAgreement() {
if (this.agreements === undefined) {
this.agreements = await (0, query_1.fetchAgreements)(this.authUrl, this.projectId);
var _a;
await this._init;
if (!this.healthy) {
return;
}
if (this.agreements.length === 0)
if (!((_a = this.agreements) === null || _a === void 0 ? void 0 : _a.length))
return;

@@ -30,0 +38,0 @@ let agreement = this.agreements[this.nextAgreementIndex];

@@ -19,5 +19,6 @@ "use strict";

return null;
return new core_1.Observable(observer => {
return new core_1.Observable((observer) => {
let sub;
this.getUrlAndToken().then((data) => {
this.getUrlAndToken()
.then((data) => {
if (data) {

@@ -32,3 +33,3 @@ const { token, url } = data;

this.loggger.warn(`Failed to get token: ${error.message}`);
observer.error(error);
observer.error(new Error('failed to get indexer url and token'));
});

@@ -45,6 +46,12 @@ return () => sub === null || sub === void 0 ? void 0 : sub.unsubscribe();

return { token, url };
this.loggger.debug(`request new token for indexer ${indexer}`);
const { projectId, authUrl } = this.options;
const tokenUrl = new URL('/token', authUrl);
const res = await (0, query_1.POST)(tokenUrl.toString(), { projectId, indexer, agreementId: id });
const res = await (0, query_1.POST)(tokenUrl.toString(), {
projectId,
indexer,
agreementId: id,
});
this.agreementManager.updateTokenById(id, res.token);
this.loggger.debug(`request new token for indexer ${indexer} success`);
return { token: res.token, url };

@@ -51,0 +58,0 @@ }

@@ -26,7 +26,12 @@ "use strict";

const agreementManager = new agreementManager_1.default({ authUrl, projectId: deploymentId, logger });
agreementManager.start();
const errorLink = (0, errorLink_1.creatErrorLink)(logger);
const fallbackLink = new fallbackLink_1.FallbackLink(fallbackServiceUrl);
const httpLink = new dynamicHttpLink_1.DynamicHttpLink({ httpOptions });
const authLink = new auth_link_1.ClusterAuthLink({ authUrl, projectId: deploymentId, logger, agreementManager });
const retryLink = (0, retryLink_1.createRetryLink)(logger);
const fallbackLink = new fallbackLink_1.FallbackLink(fallbackServiceUrl, logger);
const httpLink = new dynamicHttpLink_1.DynamicHttpLink({ httpOptions, logger });
const errorLink = (0, errorLink_1.creatErrorLink)({ logger, fallbackLink, httpLink });
const authLink = new auth_link_1.ClusterAuthLink({
authUrl,
projectId: deploymentId,
logger,
agreementManager,
});
// 1. errorLink: This link helps in handling and logging any GraphQL or network errors that may occur down the chain.

@@ -37,5 +42,5 @@ // Placing it at the beginning ensures that it catches any errors that may occur in any of the other links.

// 4. httpLink: This should always be at the end of the link chain. This link is responsible for sending the request to the server.
return (0, core_1.from)([errorLink, retryLink_1.retryLink, authLink, fallbackLink, httpLink]);
return (0, core_1.from)([errorLink, retryLink, authLink, fallbackLink, httpLink]);
}
exports.deploymentHttpLink = deploymentHttpLink;
//# sourceMappingURL=authHttpLink.js.map
import { ApolloLink, FetchResult, HttpOptions, NextLink, Observable, Operation } from '@apollo/client/core';
import { Logger } from './logger';
export interface Options {
httpOptions: HttpOptions;
logger?: Logger;
}

@@ -8,4 +10,5 @@ export declare class DynamicHttpLink extends ApolloLink {

constructor(options: Options);
get logger(): Logger | undefined;
request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null;
private createHttpLink;
}

@@ -12,4 +12,14 @@ "use strict";

}
get logger() {
return this._options.logger;
}
request(operation, forward) {
var _a;
const { url } = operation.getContext();
if (!url) {
return new core_1.Observable((observer) => {
observer.error(new Error(`empty url`));
});
}
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`use url: ${url}`);
const httpLink = this.createHttpLink(url);

@@ -16,0 +26,0 @@ return httpLink.request(operation, forward);

@@ -1,2 +0,8 @@

import { Logger } from "./logger";
export declare const creatErrorLink: (logger: Logger) => import("@apollo/client/core").ApolloLink;
import { Logger } from './logger';
import { ApolloLink } from '@apollo/client/core';
export declare type ErrorLinkOption = {
logger?: Logger;
fallbackLink: ApolloLink;
httpLink: ApolloLink;
};
export declare const creatErrorLink: ({ logger, fallbackLink, httpLink }: ErrorLinkOption) => ApolloLink;

@@ -7,7 +7,11 @@ "use strict";

const error_1 = require("@apollo/client/link/error");
const creatErrorLink = (logger) => (0, error_1.onError)(({ graphQLErrors, networkError }) => {
const creatErrorLink = ({ logger, fallbackLink, httpLink }) => (0, error_1.onError)(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) => logger.warn(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`));
graphQLErrors.forEach(({ message, locations, path }) => logger === null || logger === void 0 ? void 0 : logger.warn(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`));
if (networkError) {
logger.warn(`[Network error]: ${networkError}`);
if (!operation.getContext().fallback) {
operation.setContext({ url: undefined });
return fallbackLink.request(operation, httpLink.request.bind(httpLink));
}
logger === null || logger === void 0 ? void 0 : logger.warn(`[Network error]: ${networkError}`);
}

@@ -14,0 +18,0 @@ });

import { ApolloLink, Operation, NextLink, Observable, FetchResult } from '@apollo/client/core';
import { Logger } from './logger';
export declare class FallbackLink extends ApolloLink {
private url?;
constructor(url?: string | undefined);
private logger?;
constructor(url?: string | undefined, logger?: Logger | undefined);
request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null;
}

@@ -8,5 +8,6 @@ "use strict";

class FallbackLink extends core_1.ApolloLink {
constructor(url) {
constructor(url, logger) {
super();
this.url = url;
this.logger = logger;
}

@@ -16,6 +17,10 @@ request(operation, forward) {

return null;
return new core_1.Observable(observer => {
return new core_1.Observable((observer) => {
var _a;
const url = (_a = operation.getContext().url) !== null && _a !== void 0 ? _a : this.url;
operation.setContext({ url });
if (!operation.getContext().url) {
if (this.url) {
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`use fallback url: ${this.url}`);
}
operation.setContext({ url: this.url, fallback: true });
}
const subscription = forward(operation).subscribe(observer);

@@ -22,0 +27,0 @@ return () => subscription.unsubscribe();

@@ -1,2 +0,3 @@

import { RetryLink } from "@apollo/client/link/retry";
export declare const retryLink: RetryLink;
import { RetryLink } from '@apollo/client/link/retry';
import { Logger } from './logger';
export declare const createRetryLink: (logger?: Logger, maxRetries?: number) => RetryLink;

@@ -5,10 +5,18 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.retryLink = void 0;
exports.createRetryLink = void 0;
const retry_1 = require("@apollo/client/link/retry");
exports.retryLink = new retry_1.RetryLink({
attempts: {
max: 5,
retryIf: (error) => !!error,
}
const createRetryLink = (logger, maxRetries = 3) => new retry_1.RetryLink({
attempts: function (count, operation, error) {
if (count <= maxRetries) {
if (['empty url'].includes(error === null || error === void 0 ? void 0 : error.message) || operation.getContext().fallback) {
return false;
}
logger === null || logger === void 0 ? void 0 : logger.debug(`retry: ${count}/${maxRetries}`);
return true;
}
logger === null || logger === void 0 ? void 0 : logger.debug(`reach max retries: ${maxRetries}`);
return false;
},
});
exports.createRetryLink = createRetryLink;
//# sourceMappingURL=retryLink.js.map
{
"name": "@subql/apollo-links",
"version": "0.5.0",
"version": "0.5.1-0",
"description": "SubQuery Network - graphql links",

@@ -27,3 +27,4 @@ "main": "dist/index.js",

"graphql": "*"
}
},
"stableVersion": "0.5.0"
}
// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Logger } from "./logger";
import { fetchAgreements } from "./query";
import { Agreement } from "./types";
import { Logger } from './logger';
import { fetchAgreements } from './query';
import { Agreement } from './types';

@@ -12,6 +12,5 @@ type Options = {

projectId: string;
}
};
class AgreementManager {
private nextAgreementIndex: number;

@@ -24,2 +23,4 @@ private agreements: Agreement[] | undefined;

private interval = 300_000;
private healthy = true;
private _init: Promise<void>;

@@ -32,19 +33,23 @@ constructor(options: Options) {

this.nextAgreementIndex = 0;
this._init = this.refreshAgreements();
setInterval(this.refreshAgreements, this.interval);
}
private async refreshAgreements() {
this.agreements = await fetchAgreements(this.authUrl, this.projectId);
try {
this.agreements = await fetchAgreements(this.authUrl, this.projectId);
this.healthy = true;
} catch (e) {
this.logger.error(`fetchAgreements failed: ${String(e)}`);
this.healthy = false;
}
}
public start() {
void this.refreshAgreements();
setInterval(this.refreshAgreements, this.interval);
}
public async getNextAgreement(): Promise<Agreement | undefined> {
if (this.agreements === undefined) {
this.agreements = await fetchAgreements(this.authUrl, this.projectId);
await this._init;
if (!this.healthy) {
return;
}
if (this.agreements.length === 0) return;
if (!this.agreements?.length) return;

@@ -51,0 +56,0 @@ let agreement = this.agreements[this.nextAgreementIndex];

@@ -13,6 +13,6 @@ // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors

interface AuthOptions {
authUrl: string; // the url for geting token
projectId: string; // chainId or deploymentId for the project
agreementManager: AgreementManager; // agreement manager for managing agreements
logger: Logger; // logger for logging
authUrl: string; // the url for geting token
projectId: string; // chainId or deploymentId for the project
agreementManager: AgreementManager; // agreement manager for managing agreements
logger: Logger; // logger for logging
}

@@ -35,17 +35,18 @@

return new Observable<FetchResult>(observer => {
return new Observable<FetchResult>((observer) => {
let sub: Subscription;
this.getUrlAndToken().then((data) => {
if (data) {
const { token, url } = data;
const headers = { authorization: `Bearer ${token}` };
operation.setContext({ url, headers });
}
this.getUrlAndToken()
.then((data) => {
if (data) {
const { token, url } = data;
const headers = { authorization: `Bearer ${token}` };
operation.setContext({ url, headers });
}
sub = forward(operation).subscribe(observer);
})
.catch((error) => {
this.loggger.warn(`Failed to get token: ${error.message}`);
observer.error(error);
});
sub = forward(operation).subscribe(observer);
})
.catch((error) => {
this.loggger.warn(`Failed to get token: ${error.message}`);
observer.error(new Error('failed to get indexer url and token'));
});

@@ -62,10 +63,15 @@ return () => sub?.unsubscribe();

if (!isTokenExpired(token)) return { token, url };
this.loggger.debug(`request new token for indexer ${indexer}`);
const { projectId, authUrl } = this.options;
const tokenUrl = new URL('/token', authUrl);
const res = await POST<{ token: string }>(tokenUrl.toString(), { projectId, indexer, agreementId: id });
const res = await POST<{ token: string }>(tokenUrl.toString(), {
projectId,
indexer,
agreementId: id,
});
this.agreementManager.updateTokenById(id, res.token);
this.loggger.debug(`request new token for indexer ${indexer} success`);
return { token: res.token, url };
}
}

@@ -10,18 +10,18 @@ // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors

import { creatErrorLink } from './errorLink';
import { retryLink } from './retryLink';
import { createRetryLink } from './retryLink';
import { Logger, silentLogger } from './logger';
import { FallbackLink } from './fallbackLink';
interface DictAuthOptions extends BaseAuthOptions{
chainId: string // chain id for the requested dictionary
interface DictAuthOptions extends BaseAuthOptions {
chainId: string; // chain id for the requested dictionary
}
interface DeploymentAuthOptions extends BaseAuthOptions {
deploymentId: string; // deployment id
deploymentId: string; // deployment id
}
interface BaseAuthOptions {
authUrl: string; // auth service url
httpOptions: HttpOptions; // http options for init `HttpLink`
logger?: Logger // logger for `AuthLink`
authUrl: string; // auth service url
httpOptions: HttpOptions; // http options for init `HttpLink`
logger?: Logger; // logger for `AuthLink`
fallbackServiceUrl?: string; // fall back service url for `AuthLink`

@@ -31,4 +31,4 @@ }

export function dictHttpLink(options: DictAuthOptions): ApolloLink {
const { chainId} = options;
return deploymentHttpLink({...options, deploymentId: chainId});
const { chainId } = options;
return deploymentHttpLink({ ...options, deploymentId: chainId });
}

@@ -41,8 +41,13 @@

const agreementManager = new AgreementManager({ authUrl, projectId: deploymentId, logger });
agreementManager.start();
const errorLink = creatErrorLink(logger);
const fallbackLink = new FallbackLink(fallbackServiceUrl)
const httpLink = new DynamicHttpLink({ httpOptions });
const authLink = new ClusterAuthLink({ authUrl, projectId: deploymentId, logger, agreementManager });
const retryLink = createRetryLink(logger);
const fallbackLink = new FallbackLink(fallbackServiceUrl, logger);
const httpLink = new DynamicHttpLink({ httpOptions, logger });
const errorLink = creatErrorLink({ logger, fallbackLink, httpLink });
const authLink = new ClusterAuthLink({
authUrl,
projectId: deploymentId,
logger,
agreementManager,
});

@@ -49,0 +54,0 @@ // 1. errorLink: This link helps in handling and logging any GraphQL or network errors that may occur down the chain.

// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ApolloLink, FetchResult, HttpLink, HttpOptions, NextLink, Observable, Operation } from '@apollo/client/core';
import {
ApolloLink,
FetchResult,
HttpLink,
HttpOptions,
NextLink,
Observable,
Operation,
} from '@apollo/client/core';
import { Logger } from './logger';
export interface Options {
httpOptions: HttpOptions; // http options for init `HttpLink`
httpOptions: HttpOptions; // http options for init `HttpLink`
logger?: Logger;
}

@@ -18,4 +28,14 @@

get logger(): Logger | undefined {
return this._options.logger;
}
override request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null {
const { url } = operation.getContext();
if (!url) {
return new Observable<FetchResult>((observer) => {
observer.error(new Error(`empty url`));
});
}
this.logger?.debug(`use url: ${url}`);
const httpLink = this.createHttpLink(url);

@@ -22,0 +42,0 @@

// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { onError } from "@apollo/client/link/error";
import { Logger } from "./logger";
import { onError } from '@apollo/client/link/error';
import { Logger } from './logger';
import { ApolloLink, FetchResult, NextLink, Observable } from '@apollo/client/core';
export const creatErrorLink = (logger: Logger) => onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
logger.warn(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
export type ErrorLinkOption = {
logger?: Logger;
fallbackLink: ApolloLink;
httpLink: ApolloLink;
};
if (networkError) {
logger.warn(`[Network error]: ${networkError}`);
}
});
export const creatErrorLink = ({ logger, fallbackLink, httpLink }: ErrorLinkOption) =>
onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
logger?.warn(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`)
);
if (networkError) {
if (!operation.getContext().fallback) {
operation.setContext({ url: undefined });
return fallbackLink.request(
operation,
httpLink.request.bind(httpLink) as NextLink
) as Observable<FetchResult>;
}
logger?.warn(`[Network error]: ${networkError}`);
}
});

@@ -5,5 +5,6 @@ // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors

import { ApolloLink, Operation, NextLink, Observable, FetchResult } from '@apollo/client/core';
import { Logger } from './logger';
export class FallbackLink extends ApolloLink {
constructor(private url?: string) {
constructor(private url?: string, private logger?: Logger) {
super();

@@ -15,5 +16,9 @@ }

return new Observable<FetchResult>(observer => {
const url = operation.getContext().url ?? this.url;
operation.setContext({ url });
return new Observable<FetchResult>((observer) => {
if (!operation.getContext().url) {
if (this.url) {
this.logger?.debug(`use fallback url: ${this.url}`);
}
operation.setContext({ url: this.url, fallback: true });
}
const subscription = forward(operation).subscribe(observer);

@@ -20,0 +25,0 @@ return () => subscription.unsubscribe();

// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { RetryLink } from "@apollo/client/link/retry";
import { RetryLink } from '@apollo/client/link/retry';
import { Logger } from './logger';
import type { Operation } from '@apollo/client/core';
export const retryLink = new RetryLink({
attempts: {
max: 5,
retryIf: (error) => !!error,
}
});
export const createRetryLink = (logger?: Logger, maxRetries = 3) =>
new RetryLink({
attempts: function (count: number, operation: Operation, error: any) {
if (count <= maxRetries) {
if (['empty url'].includes(error?.message) || operation.getContext().fallback) {
return false;
}
logger?.debug(`retry: ${count}/${maxRetries}`);
return true;
}
logger?.debug(`reach max retries: ${maxRetries}`);
return false;
},
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc