Skip to content

Commit

Permalink
rollback to js generated file approach
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrrt committed Dec 18, 2023
1 parent baebe71 commit 2e72f12
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 138 deletions.
6 changes: 6 additions & 0 deletions .changeset/mighty-candles-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@authdog/hydra-core": patch
"@authdog/hydra-cli": patch
---

cleanup, rollback to local js file generated
39 changes: 23 additions & 16 deletions packages/cli/src/utils/introspectSchemas.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import fetch from "node-fetch";
import { getIntrospectionQuery, buildClientSchema, printSchema } from "graphql";
import { initSpinner, stopSpinner } from "./spinners";
import { spawn } from "node:child_process";
// import { spawn } from "node:child_process";
import fs from "fs";


export async function introspectRemoteSchema(endpointUrl: string) {
try {
Expand Down Expand Up @@ -75,21 +77,26 @@ export const buildSchemaIntrospection = async (
introspected: s.introspected
}));

if (namespaceId && namespaceId !== "test") {
// write with wrangler child process
// wrangler kv:key put schema '{"foo": "bar"}' --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c
const wrangler = spawn("wrangler", [
"kv:key",
"put",
"schema",
JSON.stringify(fileContent),
`--namespace-id=${namespaceId}`,
]);

wrangler.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
}

// generate a schemaRaw file (.hydra/schemaRaw.js) module.exports = <fileContent>
fs.writeFileSync(outputPath, `module.exports = ${JSON.stringify(fileContent, null, 2)}`);


// if (namespaceId && namespaceId !== "test") {
// // write with wrangler child process
// // wrangler kv:key put schema '{"foo": "bar"}' --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c
// const wrangler = spawn("wrangler", [
// "kv:key",
// "put",
// "schema",
// JSON.stringify(fileContent),
// `--namespace-id=${namespaceId}`,
// ]);

// wrangler.stdout.on("data", (data) => {
// console.log(`stdout: ${data}`);
// });
// }


};
5 changes: 3 additions & 2 deletions packages/core/src/handlers/graphql.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { createYoga } from "graphql-yoga";
// TODO: add create schema method to build dynamically the schema and persist to KV
import { schema } from "../schema";
import { getSchema } from "../schema";

export const GraphQLHandler = async (
req: Request,
env: any,
ctx: any,
): Promise<any> => {
const {rawSchema} = ctx;
const yoga = createYoga({
schema,
schema: await getSchema(rawSchema),
context: async (event) => {
const { request } = event;
const authorization =
Expand Down
226 changes: 111 additions & 115 deletions packages/core/src/schema.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,124 @@
import { makeExecutableSchema } from "@graphql-tools/schema";
import { default as fetch } from "node-fetch";
import {
addTypenameKeywordToSchema,
buildGraphQLSchemaSDL,
unifyGraphQLSchemasObjects,
} from "./schemaUtils";

let schemas = [];

// extract everything between type Query {}
const queryRegex = /type Query {([\s\S]*?)}/;
const mutationRegex = /type Mutation {([\s\S]*?)}/;

try {
// schemaRaw = require(".hydra/schemaRaw");
const filePath = "./.hydra/schemaRaw.json";
const fileContent = {} // TODO sync with kv
// schemas = JSON.parse(fileContent);
const extractPrimitiveWithRegExp = (rawSchema: string, regex: RegExp) => {
const primitiveMatch = rawSchema.match(regex);
const primitiveBody = primitiveMatch?.[1];
const primitiveBodyTrimmed = primitiveBody?.trim();
const primitiveBodyTrimmedLines = primitiveBodyTrimmed?.split("\n");
const operations = primitiveBodyTrimmedLines?.map((line) => {
const lineTrimmed = line.trim();
const lineTrimmedWords = lineTrimmed.split(" ");
let operationName = lineTrimmedWords?.[0];
// remove everything after : or ( (inclusive) in mutationName
// health: -> health
// health(meta: SomeInput) -> health
operationName = operationName?.replace(/[:\(].*$/, "");
return {
operationName,
};
});
return operations;
};

console.log("schemas", schemas);

} catch (error) {
// Handle error when import fails
console.error("Error loading schemaRaw:", error);
}
export const getSchema = (schemas: any) => {

// If the schemaRaw is empty, handle it here
if (!schemas || schemas.length === 0) {
console.warn("SchemaRaw is empty or invalid.");
// Perform necessary actions or log messages for an empty schemaRaw
}


const queries = [
...schemas
.map(({ introspected, url }) => {
return extractPrimitiveWithRegExp(introspected, queryRegex).map(
({ operationName }) => {
return {
id: operationName,
resolver: async (_, __, ctx) => {
const queryBody = ctx?.params?.query;
const variables = ctx?.params?.variables;
const authorization = getAuthorizationFromContext(ctx);
return await fetchGraphQLEndpoint(
url,
addTypenameKeywordToSchema(queryBody),
variables,
operationName,
{ Authorization: authorization },
);
},
};
},
);
})
.flat(),
];

const mutations = [
...schemas
.map(({ introspected, url }) => {
return extractPrimitiveWithRegExp(introspected, mutationRegex).map(
({ operationName }) => {
return {
id: operationName,
resolver: async (_, bindings, ctx) => {
const queryBody = ctx?.params?.query;
const variables = ctx?.params?.variables;
const authorization = getAuthorizationFromContext(ctx);
return await fetchGraphQLEndpoint(
url,
addTypenameKeywordToSchema(queryBody),
variables,
operationName,
{ Authorization: authorization },
);
},
};
},
);
})
.flat(),
];

const resolvers = {
Query: {},
Mutation: {},
};

queries?.forEach(({ id, resolver }) => {
resolvers.Query[id] = resolver;
});

mutations?.forEach(({ id, resolver }) => {
resolvers.Mutation[id] = resolver;
});

let schema = makeExecutableSchema({
typeDefs: buildGraphQLSchemaSDL(
unifyGraphQLSchemasObjects([
...schemas.map(({ introspected }) => introspected),
]),
),
resolvers,
});

// If the schemaRaw is empty, handle it here
if (!schemas || schemas.length === 0) {
console.warn("SchemaRaw is empty or invalid.");
// Perform necessary actions or log messages for an empty schemaRaw
return schema;
}

import {
addTypenameKeywordToSchema,
buildGraphQLSchemaSDL,
unifyGraphQLSchemasObjects,
} from "./schemaUtils";

const fetchGraphQLEndpoint = async (
endpoint: string,
query: string,
Expand Down Expand Up @@ -67,107 +157,13 @@ const fetchGraphQLEndpoint = async (
}
};

// extract everything between type Query {}
const queryRegex = /type Query {([\s\S]*?)}/;
const mutationRegex = /type Mutation {([\s\S]*?)}/;

const extractPrimitiveWithRegExp = (rawSchema: string, regex: RegExp) => {
const primitiveMatch = rawSchema.match(regex);
const primitiveBody = primitiveMatch?.[1];
const primitiveBodyTrimmed = primitiveBody?.trim();
const primitiveBodyTrimmedLines = primitiveBodyTrimmed?.split("\n");
const operations = primitiveBodyTrimmedLines?.map((line) => {
const lineTrimmed = line.trim();
const lineTrimmedWords = lineTrimmed.split(" ");
let operationName = lineTrimmedWords?.[0];
// remove everything after : or ( (inclusive) in mutationName
// health: -> health
// health(meta: SomeInput) -> health
operationName = operationName?.replace(/[:\(].*$/, "");
return {
operationName,
};
});
return operations;
};

const getAuthorizationFromContext = (ctx) => {
const authorization = ctx?.request?.headers?.get("authorization");
return authorization;
};

const queries = [
...schemas
.map(({ introspected, url }) => {
return extractPrimitiveWithRegExp(introspected, queryRegex).map(
({ operationName }) => {
return {
id: operationName,
resolver: async (_, __, ctx) => {
const queryBody = ctx?.params?.query;
const variables = ctx?.params?.variables;
const authorization = getAuthorizationFromContext(ctx);
return await fetchGraphQLEndpoint(
url,
addTypenameKeywordToSchema(queryBody),
variables,
operationName,
{ Authorization: authorization },
);
},
};
},
);
})
.flat(),
];

const mutations = [
...schemas
.map(({ introspected, url }) => {
return extractPrimitiveWithRegExp(introspected, mutationRegex).map(
({ operationName }) => {
return {
id: operationName,
resolver: async (_, bindings, ctx) => {
const queryBody = ctx?.params?.query;
const variables = ctx?.params?.variables;
const authorization = getAuthorizationFromContext(ctx);
return await fetchGraphQLEndpoint(
url,
addTypenameKeywordToSchema(queryBody),
variables,
operationName,
{ Authorization: authorization },
);
},
};
},
);
})
.flat(),
];

const resolvers = {
Query: {},
Mutation: {},
};

queries?.forEach(({ id, resolver }) => {
resolvers.Query[id] = resolver;
});

mutations?.forEach(({ id, resolver }) => {
resolvers.Mutation[id] = resolver;
});

let schema = makeExecutableSchema({
typeDefs: buildGraphQLSchemaSDL(
unifyGraphQLSchemasObjects([
...schemas.map(({ introspected }) => introspected),
]),
),
resolvers,
});

export { schema };
// export { schema };
15 changes: 11 additions & 4 deletions services/itty-hydra/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { createCors } from "itty-cors";
// import { withDurables } from "itty-durable";
import { NotFound } from "./handlers/notFound";
import { Health } from "./handlers/health";
// import { GraphQLHandler, HydraHandler } from "@authdog/hydra-core";
import { GraphQLHandler, HydraHandler } from "@authdog/hydra-core";
import { HydraConfigAcme } from "./hydra.config";

import {default as rawSchema} from "./.hydra/schemaRaw"

const { preflight, corsify } = createCors();


Expand All @@ -17,7 +19,9 @@ router
.get("/health", Health)
.get("/schema", async (req, env, ctx) => {

const schema = await ctx.kv.get("schema")
const schema = await ctx.rawSchema

// const schema = await ctx.kv.get("schema")

return new Response(
JSON.stringify(schema),
Expand All @@ -29,17 +33,20 @@ router

})
// serves playground
// .get("/graphql", GraphQLHandler)
// .post("/graphql", HydraHandler)
.get("/graphql", GraphQLHandler)
.post("/graphql", HydraHandler)
.get("*", NotFound);

const handleRequest = (req, env, ctx) => {
const { HYDRA_ACME } = env;

console.log("rawSchema", rawSchema);

const enrichedContext = {
...ctx,
kv: HYDRA_ACME,
hydraConfig: HydraConfigAcme,
rawSchema
// rateLimiter: null,
};

Expand Down
2 changes: 1 addition & 1 deletion services/itty-hydra/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"private": true,
"scripts": {
"build": "node build.mjs",
"dev": "npx wrangler dev -c wrangler.base.toml --live-reload --port 3565",
"dev": "npx wrangler dev -c wrangler.base.toml --live-reload --port 3566",
"deploy": "npx wrangler -c wrangler.base.toml deploy --minify"
},
"keywords": [],
Expand Down

0 comments on commit 2e72f12

Please sign in to comment.