stellate
Version:
The CLI you need to work with Stellate from your CLI. See https://docs.stellate.co/docs/cli for the complete documentation.
190 lines (188 loc) • 5.83 kB
JavaScript
// src/server-plugins-shared.ts
function createBlake3Hash(str) {
let val = 0;
const strlen = str.length;
if (strlen === 0) {
return val;
}
for (let i = 0; i < strlen; ++i) {
const code = str.charCodeAt(i);
val = (val << 5) - val + code;
val &= val;
}
return val >>> 0;
}
function extractStellatePayload({
headers,
operation,
method,
start,
operationName,
errors,
response,
variables,
responseHeaders,
sendVariablesAsHash,
hasSetCookie,
graphqlClientName,
graphqlClientVersion
}) {
const forwardedFor = headers.get("x-forwarded-for");
const ips = forwardedFor ? forwardedFor.split(",") : [];
const vary = responseHeaders && responseHeaders.get("vary");
let varyHash = void 0;
if (vary && vary.length) {
const varyHeaders = vary.split(",").map((headerName) => headerName && headerName.trim()).sort();
const variedValues = varyHeaders.map((headerName) => {
const headerValue = headerName && headers.get(headerName);
return headerValue ? `${headerName}:${headerValue}` : void 0;
}).filter(Boolean).join("\n");
varyHash = createBlake3Hash(variedValues);
}
return {
graphqlClientName,
graphqlClientVersion,
operation,
operationName,
variables: sendVariablesAsHash ? void 0 : variables,
variableHash: sendVariablesAsHash ? createBlake3Hash(JSON.stringify(variables || {})) : void 0,
method,
elapsed: Date.now() - start,
ip: ips[0] || headers.get("true-client-ip") || headers.get("x-real-ip") || void 0,
hasSetCookie,
referer: headers.get("referer") || void 0,
userAgent: headers.get("user-agent") || void 0,
statusCode: 200,
errors,
responseSize: JSON.stringify(response).length,
responseHash: createBlake3Hash(JSON.stringify(response)),
varyHash
};
}
function warnFetch(fetch) {
if (typeof fetch !== "function") {
console.warn(
`Stellate logger plugin requires a fetch function to be provided as an option.`
);
return;
}
}
var hostname = process.env.STELLATE_ENDPOINT === "local" || process.env.STELLATE_ENDPOINT === "staging" ? "stellate.dev" : "stellate.sh";
async function logRequest({
fetch: fetchFn,
payload,
token,
serviceName
}) {
return fetchFn(`https://${serviceName}.${hostname}/log`, {
method: "POST",
body: JSON.stringify(payload),
headers: {
"Content-Type": "application/json",
"Stellate-Logging-Token": token
}
});
}
// src/apollo-server.ts
import { introspectionFromSchema } from "graphql";
var createStellateLoggerPlugin = (options) => {
var _a, _b;
const sendVariablesAsHash = (_a = options.sendVariablesAsHash) != null ? _a : true;
const shouldSyncSchema = (_b = options.schemaSyncing) != null ? _b : true;
let stopped = false, timeout;
const sendSchema = async (apiSchema) => {
if (shouldSyncSchema) {
const introspection = introspectionFromSchema(apiSchema);
const randomTimeout = Math.random() * 5e3;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(async () => {
timeout = null;
if (!stopped) {
try {
options.fetch(`https://${options.serviceName}.${hostname}/schema`, {
method: "POST",
body: JSON.stringify({
schema: introspection
}),
headers: {
"Content-Type": "application/json",
"Stellate-Schema-Token": options.token
}
}).then(() => {
});
} catch (e) {
}
}
}, randomTimeout);
}
};
return {
async serverWillStart() {
return {
schemaDidLoadOrUpdate({ apiSchema }) {
sendSchema(apiSchema);
},
async serverWillStop() {
stopped = true;
if (timeout) {
clearTimeout(timeout);
}
}
};
},
async requestDidStart(requestCtx) {
const start = Date.now();
const { request } = requestCtx;
const { operationName, variables, http, query } = request;
if (!http) return;
const { headers, method } = http;
if (headers.has("gcdn-request-id")) return;
return {
async willSendResponse(respContext) {
var _a2, _b2;
const { response, source } = respContext;
if (response.body.kind !== "single") {
console.warn(
`Stellate does not currently support logging incremental results.`
);
return;
}
const respBody = response.body.singleResult;
const queryString = query || source;
if (!queryString) return;
const graphqlClientName = ((_a2 = request.http) == null ? void 0 : _a2.headers.get("x-graphql-client-name")) || void 0;
const graphqlClientVersion = ((_b2 = request.http) == null ? void 0 : _b2.headers.get("x-graphql-client-version")) || void 0;
const stellatePayload = extractStellatePayload({
headers,
responseHeaders: response.http.headers,
operation: queryString,
method,
sendVariablesAsHash,
start,
operationName,
errors: respContext.errors,
response: respBody,
variables,
hasSetCookie: response.http.headers.has("set-cookie"),
graphqlClientName,
graphqlClientVersion
});
warnFetch(options.fetch);
try {
await logRequest({
fetch: options.fetch,
payload: stellatePayload,
token: options.token,
serviceName: options.serviceName
});
} catch (e) {
}
}
};
}
};
};
export {
createBlake3Hash,
createStellateLoggerPlugin
};