Skip to content

Commit

Permalink
refactor schema dump to leverage kv instead of local JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrrt committed Dec 18, 2023
1 parent 59c1a3a commit baebe71
Show file tree
Hide file tree
Showing 16 changed files with 77 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
node-version: [20.x]

steps:
- uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"scripts": {
"start": "node .",
"dev-gen-schema": "pnpm start generate-schema -c src/assets/hydra.config.ts -nid c63f48a0f29843e8ab8251ef533e1c9c",
"dev": "tsc -w -p tsconfig.json",
"build": "tsc -p tsconfig.json",
"test": "jest"
Expand Down
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion packages/cli/src/commands/generate-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const checkFileExists = (file: any) => {

describe("generate schema command", () => {
it("should validate a valid config object without throwing errors", async () => {
const configPath = "./src/__assets__/hydra.config.ts";
const configPath = "./src/assets/hydra.config.ts";

try {
// await fs.unlink("./.hydra/schemaRaw.ts");
Expand All @@ -22,6 +22,7 @@ describe("generate schema command", () => {
// Generate schema using the specified configuration
await generateSchemaAction({
config: configPath,
namespaceId: "test",
});

// Check if the schema file exists after generation
Expand Down
6 changes: 4 additions & 2 deletions packages/cli/src/commands/generate-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import ts from "typescript";
import {
hydraConfigPathDefault,
hydraSchemaRawPath,
} from "../__assets__/constants";
} from "../assets/constants";
import { logError, logSuccess } from "../utils/cliLogger";
import { buildSchemaIntrospection } from "../utils/introspectSchemas";
import { validateConfig } from "../utils/validateConfig";

interface IGenerateSchemaAction {
config?: string;
namespaceId: string;
}

export const generateSchemaAction = async ({
config = hydraConfigPathDefault,
namespaceId
}: IGenerateSchemaAction) => {
const rootPath = process.cwd(); // Get the root directory path
const configPath = path.resolve(rootPath, config); // Construct absolute path for config
Expand Down Expand Up @@ -44,7 +46,7 @@ export const generateSchemaAction = async ({
return logError(`Invalid config [${config}]`);
}
try {
await buildSchemaIntrospection(validatedConfig.schemas, outputPath);
await buildSchemaIntrospection(validatedConfig.schemas, outputPath, namespaceId);
} catch (error: any) {
return logError(error.message);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ program
"-c, --config <configPath>",
"Path to Hydra configuration path, default being <hydra.config.ts>",
)
.option(
"-nid, --namespace-id <namespaceId>",
"Cloudflare KV Namespace ID",
)
.action(actionRunner(generateSchemaAction));

// TODO
Expand Down
45 changes: 18 additions & 27 deletions packages/cli/src/utils/introspectSchemas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fetch from "node-fetch";
import { getIntrospectionQuery, buildClientSchema, printSchema } from "graphql";
import { initSpinner, stopSpinner } from "./spinners";
import { spawn } from "node:child_process";

export async function introspectRemoteSchema(endpointUrl: string) {
try {
Expand Down Expand Up @@ -48,6 +49,7 @@ interface GraphQLSchema {
export const buildSchemaIntrospection = async (
schemas: GraphQLSchema[],
outputPath: string,
namespaceId: string,
) => {
let schemaWithIntrospection = [];

Expand All @@ -67,38 +69,27 @@ export const buildSchemaIntrospection = async (

stopSpinner(interval);

// const outputPath = "src/handlers/federation/schemaRawGenerated.ts";
// const exportStatements = schemaWithIntrospection.map(
// (s) =>
// `export const ${s.name} = {
// name: "${s.name}",
// url: "${s.url}",
// introspected: ${JSON.stringify(s.introspected, null, 2)}
// };`,
// );

const exportObjects = schemaWithIntrospection.map(s => ({
const fileContent = schemaWithIntrospection.map(s => ({
name: s.name,
url: s.url,
introspected: s.introspected
}));

// const fileContent = `${exportStatements.join("\n")}\n`;

const fileContent = JSON.stringify(exportObjects, 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}`);
});
}

const fs = require("fs");

try {
// define .hydra folder if it doesn't exist
if (!fs.existsSync(".hydra")) {
fs.mkdirSync(".hydra");
}

fs.writeFileSync(outputPath, fileContent);
console.log(`${outputPath} written`);
} catch (err) {
console.error(err);
}
};
1 change: 1 addition & 0 deletions packages/core/src/handlers/graphql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createYoga } from "graphql-yoga";
// TODO: add create schema method to build dynamically the schema and persist to KV
import { schema } from "../schema";

export const GraphQLHandler = async (
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/schema.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { makeExecutableSchema } from "@graphql-tools/schema";
import { default as fetch } from "node-fetch";
import * as fs from "fs";

let schemas = [];


try {
// schemaRaw = require(".hydra/schemaRaw");
const filePath = "./.hydra/schemaRaw.json";
const fileContent = fs.readFileSync(filePath, { encoding: "utf8" });
schemas = JSON.parse(fileContent);
const fileContent = {} // TODO sync with kv
// schemas = JSON.parse(fileContent);

console.log("schemas", schemas);

} catch (error) {
// Handle error when import fails
console.error("Error loading schemaRaw:", error);
Expand All @@ -21,8 +23,6 @@ if (!schemas || schemas.length === 0) {
// Perform necessary actions or log messages for an empty schemaRaw
}



import {
addTypenameKeywordToSchema,
buildGraphQLSchemaSDL,
Expand Down
11 changes: 11 additions & 0 deletions services/itty-hydra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,14 @@ class_name = "RateLimiter"
tag = "v2"
new_classes = [ "RateLimiter" ]
```


## Setup schema

### Write

- `wrangler kv:key put schema '{ "foo": "bar" }' --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c`

### Read

- `wrangler kv:key get schema --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c`
3 changes: 1 addition & 2 deletions services/itty-hydra/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ try {
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
global: true,
// define: { 'process.env.var': '"hello"' }, // inject will override define, to keep env vars you must also pass define here https://github.com/evanw/esbuild/issues/660
global: true
}),
NodeModulesPolyfillPlugin({
util: true
Expand Down
4 changes: 4 additions & 0 deletions services/itty-hydra/get-schema.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Put schema into Key-Value store using wrangler
wrangler kv:key get schema --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c
22 changes: 17 additions & 5 deletions services/itty-hydra/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,34 @@ 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";

const { preflight, corsify } = createCors();


const router = Router();
router
// .all("*", withDurables())
.options("*", preflight)
.get("/", Health)
.get("/health", Health)
.get("/schema", async (req, env, ctx) => {

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

return new Response(
JSON.stringify(schema),
{ status: 200, headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*",
} },
);

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

const handleRequest = (req, env, ctx) => {
Expand All @@ -29,8 +43,6 @@ const handleRequest = (req, env, ctx) => {
// rateLimiter: null,
};



return router
.handle(req, env, enrichedContext)
.catch(
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 3546",
"dev": "npx wrangler dev -c wrangler.base.toml --live-reload --port 3565",
"deploy": "npx wrangler -c wrangler.base.toml deploy --minify"
},
"keywords": [],
Expand Down
7 changes: 7 additions & 0 deletions services/itty-hydra/sync-schema.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# Read schema from .hydra/schemaRaw.json
SCHEMA=$(<.hydra/schemaRaw.json)

# Put schema into Key-Value store using wrangler
wrangler kv:key put schema "$SCHEMA" --namespace-id=c63f48a0f29843e8ab8251ef533e1c9c

0 comments on commit baebe71

Please sign in to comment.