@graphql-tools/prisma-loader
Version:
A set of utils for faster development of GraphQL tools
226 lines (225 loc) • 8.02 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cluster = void 0;
const tslib_1 = require("tslib");
require("isomorphic-fetch");
const jsonwebtoken_1 = tslib_1.__importDefault(require("jsonwebtoken"));
const constants_js_1 = require("./constants.js");
const graphql_request_1 = require("graphql-request");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const getProxyAgent_js_1 = require("./utils/getProxyAgent.js");
const debug_1 = tslib_1.__importDefault(require("debug"));
const debug = (0, debug_1.default)('Environment');
class Cluster {
constructor(out, name, baseUrl, clusterSecret, local = true, shared = false, isPrivate = false, workspaceSlug) {
this.out = out;
this.name = name;
// All `baseUrl` extension points in this class
// adds a trailing slash. Here we remove it from
// the passed `baseUrl` in order to avoid double
// slashes.
this.baseUrl = baseUrl.replace(/\/$/, '');
this.clusterSecret = clusterSecret;
this.local = local;
this.shared = shared;
this.isPrivate = isPrivate;
this.workspaceSlug = workspaceSlug;
this.hasOldDeployEndpoint = false;
}
async getToken(serviceName, workspaceSlug, stageName) {
// public clusters just take the token
const needsAuth = await this.needsAuth();
debug({ needsAuth });
if (!needsAuth) {
return null;
}
if (this.name === 'shared-public-demo') {
return '';
}
if (this.isPrivate && process.env['PRISMA_MANAGEMENT_API_SECRET']) {
return this.getLocalToken();
}
if (this.shared || (this.isPrivate && !process.env['PRISMA_MANAGEMENT_API_SECRET'])) {
return this.generateClusterToken(serviceName, workspaceSlug, stageName);
}
else {
return this.getLocalToken();
}
}
getLocalToken() {
if (!this.clusterSecret && !process.env['PRISMA_MANAGEMENT_API_SECRET']) {
return null;
}
if (!this.cachedToken) {
const grants = [{ target: `*/*`, action: '*' }];
const secret = process.env['PRISMA_MANAGEMENT_API_SECRET'] || this.clusterSecret;
if (!secret) {
throw new Error(`Could not generate token for cluster ${chalk_1.default.bold(this.getDeployEndpoint())}. Did you provide the env var PRISMA_MANAGEMENT_API_SECRET?`);
}
try {
const algorithm = process.env['PRISMA_MANAGEMENT_API_SECRET'] ? 'HS256' : 'RS256';
this.cachedToken = jsonwebtoken_1.default.sign({ grants }, secret, {
expiresIn: '5y',
algorithm,
});
}
catch (e) {
throw new Error(`Could not generate token for cluster ${chalk_1.default.bold(this.getDeployEndpoint())}.
Original error: ${e.message}`);
}
}
return this.cachedToken;
}
get cloudClient() {
return new graphql_request_1.GraphQLClient(constants_js_1.cloudApiEndpoint, {
headers: {
Authorization: `Bearer ${this.clusterSecret}`,
},
agent: (0, getProxyAgent_js_1.getProxyAgent)(constants_js_1.cloudApiEndpoint),
});
}
async generateClusterToken(serviceName, workspaceSlug = this.workspaceSlug || '*', stageName) {
const query = /* GraphQL */ `
mutation ($input: GenerateClusterTokenRequest!) {
generateClusterToken(input: $input) {
clusterToken
}
}
`;
const { generateClusterToken: { clusterToken }, } = await this.cloudClient.request(query, {
input: {
workspaceSlug,
clusterName: this.name,
serviceName,
stageName,
},
});
return clusterToken;
}
async addServiceToCloudDBIfMissing(serviceName, workspaceSlug = this.workspaceSlug, stageName) {
const query = /* GraphQL */ `
mutation ($input: GenerateClusterTokenRequest!) {
addServiceToCloudDBIfMissing(input: $input)
}
`;
const serviceCreated = await this.cloudClient.request(query, {
input: {
workspaceSlug,
clusterName: this.name,
serviceName,
stageName,
},
});
return serviceCreated.addServiceToCloudDBIfMissing;
}
getApiEndpoint(service, stage, workspaceSlug) {
if (!this.shared && service === 'default' && stage === 'default') {
return this.baseUrl;
}
if (!this.shared && stage === 'default') {
return `${this.baseUrl}/${service}`;
}
if (this.isPrivate || this.local) {
return `${this.baseUrl}/${service}/${stage}`;
}
const workspaceString = workspaceSlug ? `${workspaceSlug}/` : '';
return `${this.baseUrl}/${workspaceString}${service}/${stage}`;
}
getWSEndpoint(service, stage, workspaceSlug) {
return this.getApiEndpoint(service, stage, workspaceSlug).replace(/^http/, 'ws');
}
getImportEndpoint(service, stage, workspaceSlug) {
return this.getApiEndpoint(service, stage, workspaceSlug) + `/import`;
}
getExportEndpoint(service, stage, workspaceSlug) {
return this.getApiEndpoint(service, stage, workspaceSlug) + `/export`;
}
getDeployEndpoint() {
return `${this.baseUrl}/${this.hasOldDeployEndpoint ? 'cluster' : 'management'}`;
}
async isOnline() {
const version = await this.getVersion();
return typeof version === 'string';
}
async getVersion() {
// first try new api
try {
const result = await this.request(`{
serverInfo {
version
}
}`);
const res = await result.json();
const { data, errors } = res;
if (errors && errors[0].code === 3016 && errors[0].message.includes('management@default')) {
this.hasOldDeployEndpoint = true;
return await this.getVersion();
}
if (data && data.serverInfo) {
return data.serverInfo.version;
}
}
catch (e) {
debug(e);
}
// if that doesn't work, try the old one
try {
const result = await this.request(`{
serverInfo {
version
}
}`);
const res = await result.json();
const { data } = res;
return data.serverInfo.version;
}
catch (e) {
debug(e);
}
return null;
}
request(query, variables) {
return fetch(this.getDeployEndpoint(), {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables,
}),
agent: (0, getProxyAgent_js_1.getProxyAgent)(this.getDeployEndpoint()),
});
}
async needsAuth() {
try {
const result = await this.request(`{
listProjects {
name
}
}`);
const data = await result.json();
if (data.errors && data.errors.length > 0) {
return true;
}
return false;
}
catch (e) {
debug('Assuming that the server needs authentication');
debug(e.toString());
return true;
}
}
toJSON() {
return {
name: this.name,
baseUrl: this.baseUrl,
local: this.local,
clusterSecret: this.clusterSecret,
shared: this.shared,
isPrivate: this.isPrivate,
workspaceSlug: this.workspaceSlug,
};
}
}
exports.Cluster = Cluster;
;