```javascript
import Groq from "groq-sdk";
const groq = new Groq();

// Define the JSON schema for recipe objects
// This is the schema that the model will use to generate the JSON object, 
// which will be parsed into the Recipe class.
const schema = {
  $defs: {
    Ingredient: {
      properties: {
        name: { title: "Name", type: "string" },
        quantity: { title: "Quantity", type: "string" },
        quantity_unit: {
          anyOf: [{ type: "string" }, { type: "null" }],
          title: "Quantity Unit",
        },
      },
      required: ["name", "quantity", "quantity_unit"],
      title: "Ingredient",
      type: "object",
    },
  },
  properties: {
    recipe_name: { title: "Recipe Name", type: "string" },
    ingredients: {
      items: { $ref: "#/$defs/Ingredient" },
      title: "Ingredients",
      type: "array",
    },
    directions: {
      items: { type: "string" },
      title: "Directions",
      type: "array",
    },
  },
  required: ["recipe_name", "ingredients", "directions"],
  title: "Recipe",
  type: "object",
};

// Ingredient class representing a single recipe ingredient
class Ingredient {
  constructor(name, quantity, quantity_unit) {
    this.name = name;
    this.quantity = quantity;
    this.quantity_unit = quantity_unit || null;
  }
}

// Recipe class representing a complete recipe
class Recipe {
  constructor(recipe_name, ingredients, directions) {
    this.recipe_name = recipe_name;
    this.ingredients = ingredients;
    this.directions = directions;
  }
}

// Generates a recipe based on the recipe name
export async function getRecipe(recipe_name) {
  // Pretty printing improves completion results
  const jsonSchema = JSON.stringify(schema, null, 4);
  const chat_completion = await groq.chat.completions.create({
    messages: [
      {
        role: "system",
        content: `You are a recipe database that outputs recipes in JSON.\n'The JSON object must use the schema: ${jsonSchema}`,
      },
      {
        role: "user",
        content: `Fetch a recipe for ${recipe_name}`,
      },
    ],
    model: "openai/gpt-oss-20b",
    temperature: 0,
    stream: false,
    response_format: { type: "json_object" },
  });

  const recipeJson = JSON.parse(chat_completion.choices[0].message.content);

  // Map the JSON ingredients to the Ingredient class
  const ingredients = recipeJson.ingredients.map((ingredient) => {
    return new Ingredient(ingredient.name, ingredient.quantity, ingredient.quantity_unit);
  });

  // Return the recipe object
  return new Recipe(recipeJson.recipe_name, ingredients, recipeJson.directions);
}

// Prints a recipe to the console with nice formatting
function printRecipe(recipe) {
  console.log("Recipe:", recipe.recipe_name);
  console.log();

  console.log("Ingredients:");
  recipe.ingredients.forEach((ingredient) => {
    console.log(
      `- ${ingredient.name}: ${ingredient.quantity} ${
        ingredient.quantity_unit || ""
      }`,
    );
  });
  console.log();

  console.log("Directions:");
  recipe.directions.forEach((direction, step) => {
    console.log(`${step + 1}. ${direction}`);
  });
}

// Main function that generates and prints a recipe
export async function main() {
  const recipe = await getRecipe("apple pie");
  printRecipe(recipe);
}

main();
```

---

## Required parameters