Поделиться через


Краткое руководство. Настройка и использование данных каталога API платформы Microsoft Learn

Из этого краткого руководства вы узнаете, как настроить и запустить API платформы Microsoft Learn, который включает примеры для получения курсов, схем обучения, модулей и сертификаций.

Предпосылки

Прежде чем приступить к работе, убедитесь, что установлено следующее:

  • Node.js (версия 18.0.0 или более поздней версии)

    • Node.js — это среда выполнения JavaScript, которая позволяет запускать код JavaScript или TypeScript за пределами веб-браузера. Это необходимо для выполнения примеров скриптов и управления пакетами с помощью npm (диспетчер пакетов узлов).
    • Скачивание из: https://nodejs.org/
    • Проверьте установку: node --version
  • Azure CLI

    • Интерфейс azure Command-Line (CLI) — это средство для управления ресурсами Azure из командной строки. В этом руководстве используется аутентификация вашей личности, чтобы примеры могли получить доступ к API платформы Learn от вашего имени.
    • Скачивание из: https://docs.microsoft.com/cli/azure/install-azure-cli
    • Проверьте установку: az --version
  • Учетная запись Azure

    • Для проверки подлинности и доступа к API платформы Microsoft Learn требуется учетная запись Azure с активной подпиской. API использует идентификатор Microsoft Entra (ранее Azure Active Directory) для проверки подлинности, для которой требуются допустимые учетные данные Azure. Нет затрат на извлечение токена аутентификации из вашей подписки Azure.
    • Вам нужна активная подписка Azure
    • Зарегистрируйтесь по адресу: https://azure.microsoft.com/free/
  • Visual Studio Code (необязательно)

    • Visual Studio Code (VS Code) — это бесплатный, упрощенный редактор кода с интегрированным терминалом, поддержкой IntelliSense и TypeScript. Хотя вы можете использовать любой текстовый редактор и терминал, Visual Studio Code предоставляет упрощенный интерфейс для выполнения этих примеров.
    • Скачивание из: https://code.visualstudio.com/
    • Проверка установки: откройте Visual Studio Code и нажмите клавиши CTRL+', чтобы открыть интегрированный терминал.

Замечание

Все команды, написанные ниже, должны выполняться в терминале Git Bash. Вы можете использовать интегрированный терминал VS Code (клавиши CTRL+), Windows PowerShell или командную строку.

Настройка проекта

Выполните следующие действия, чтобы создать проект и установить необходимые зависимости.

  1. Создайте папку для проекта и перейдите к ней.

    mkdir learn-api-examples
    cd learn-api-examples
    
  2. Инициализировать новый проект Node.js с параметрами по умолчанию. Флаг -y автоматически принимает все значения по умолчанию.

    npm init -y
    
  3. Установите необходимые пакеты npm (@azure/identity для проверки подлинности, tsx запуска TypeScript напрямую, typescript компилятора и @types/node определения типов).

    npm install @azure/identity tsx typescript @types/node
    
  4. Создайте новый файл с именем examples.ts и вставьте приведенный ниже код. Это включает проверку подлинности, используя учетные данные Azure по умолчанию и несколько примеров возможностей каталога, доступных через API платформы Learn.

    /**
     * Microsoft Learn Platform API Examples
     * API Version: 2023-11-01-preview
     * Base URL: https://learn.microsoft.com/api/v1
     *
     * Authentication: OAuth2 with scope https://learn.microsoft.com/.default
     */
    
    import { DefaultAzureCredential } from "@azure/identity";
    
    const API_BASE_URL = "https://learn.microsoft.com/api/v1";
    const API_VERSION = "2023-11-01-preview";
    
    // ============================================================================
    // AUTHENTICATION HELPER
    // ============================================================================
    
    async function getAccessToken(): Promise<string> {
      const credential = new DefaultAzureCredential();
      const token = await credential.getToken("https://learn.microsoft.com/.default");
      return token.token;
    }
    
    /**
     * Helper to handle API response with error checking
     */
    async function handleResponse(response: Response, label: string): Promise<void> {
      if (!response.ok) {
        const text = await response.text();
        console.log(`${label} Error: ${response.status} ${response.statusText}`);
        console.log("Response:", text || "(empty)");
        return;
      }
    
      const text = await response.text();
      if (!text) {
        console.log(`${label}: (empty response)`);
        return;
      }
    
      try {
        const data = JSON.parse(text);
        console.log(`${label}:`, JSON.stringify(data, null, 2));
      } catch (e) {
        console.log(`${label} Parse Error: Invalid JSON`);
        console.log("Raw response:", text.substring(0, 500));
      }
    }
    
    // ============================================================================
    // TRAINING ENDPOINTS
    // ============================================================================
    
    /**
     * List all courses with optional filters
     * GET /courses
     */
    async function listCourses(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/courses?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Courses");
    }
    
    /**
     * Get a specific course by ID
     * GET /courses/{id}
     */
    async function getCourse(courseId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/courses/${courseId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Course");
    }
    
    /**
     * List all learning paths
     * GET /learning-paths
     */
    async function listLearningPaths(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/learning-paths?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Learning Paths");
    }
    
    /**
     * Get a specific learning path by ID
     * GET /learning-paths/{id}
     */
    async function getLearningPath(learningPathId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/learning-paths/${learningPathId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Learning Path");
    }
    
    /**
     * List all modules
     * GET /modules
     */
    async function listModules(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/modules?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Modules");
    }
    
    /**
     * Get a specific module by ID
     * GET /modules/{id}
     */
    async function getModule(moduleId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/modules/${moduleId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Module");
    }
    
    /**
     * Get a specific unit by ID
     * GET /units/{id}
     */
    async function getUnit(unitId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/units/${unitId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Unit");
    }
    
    // ============================================================================
    // CREDENTIALS ENDPOINTS
    // ============================================================================
    
    /**
     * List all certifications
     * GET /certifications
     */
    async function listCertifications(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/certifications?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Certifications");
    }
    
    /**
     * Get a specific certification by ID
     * GET /certifications/{id}
     */
    async function getCertification(certificationId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/certifications/${certificationId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Certification");
    }
    
    /**
     * List all exams
     * GET /exams
     */
    async function listExams(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/exams?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Exams");
    }
    
    /**
     * Get a specific exam by ID
     * GET /exams/{id}
     */
    async function getExam(examId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/exams/${examId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Exam");
    }
    
    /**
     * List all applied skills
     * GET /applied-skills
     */
    async function listAppliedSkills(options?: {
      levels?: string[];
      roles?: string[];
      products?: string[];
      subjects?: string[];
      locale?: string;
      maxpagesize?: number;
    }): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (options?.levels) params.append("levels", options.levels.join(","));
      if (options?.roles) params.append("roles", options.roles.join(","));
      if (options?.products) params.append("products", options.products.join(","));
      if (options?.subjects) params.append("subjects", options.subjects.join(","));
      if (options?.locale) params.append("locale", options.locale);
      if (options?.maxpagesize) params.append("maxpagesize", options.maxpagesize.toString());
    
      const response = await fetch(`${API_BASE_URL}/applied-skills?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Applied Skills");
    }
    
    /**
     * Get a specific applied skill by ID
     * GET /applied-skills/{id}
     */
    async function getAppliedSkill(appliedSkillId: string, locale?: string): Promise<void> {
      const token = await getAccessToken();
    
      const params = new URLSearchParams({ "api-version": API_VERSION });
      if (locale) params.append("locale", locale);
    
      const response = await fetch(`${API_BASE_URL}/applied-skills/${appliedSkillId}?${params}`, {
        method: "GET",
        headers: {
          "Accept": "application/json",
          "Authorization": `Bearer ${token}`
        }
      });
    
      await handleResponse(response, "Applied Skill");
    }
    
    // ============================================================================
    // PAGINATION HELPER
    // ============================================================================
    
    /**
     * Helper to handle paginated responses
     */
    async function fetchAllPages<T>(initialUrl: string, token: string): Promise<T[]> {
      const allItems: T[] = [];
      let nextLink: string | undefined = initialUrl;
    
      while (nextLink) {
        const response = await fetch(nextLink, {
          method: "GET",
          headers: {
            "Accept": "application/json",
            "Authorization": `Bearer ${token}`
          }
        });
    
        const data = await response.json();
        allItems.push(...data.value);
        nextLink = data.nextLink;
      }
    
      return allItems;
    }
    
    // ============================================================================
    // EXAMPLE USAGE
    // ============================================================================
    
    async function main() {
      try {
        // List beginner-level certifications for Azure
        console.log("=== Listing Azure certifications (beginner level) ===");
        await listCertifications({
          levels: ["beginner"],
          products: ["azure"],
          maxpagesize: 5
        });
    
        // List certifications
        console.log("\n=== Listing certifications ===");
        await listCertifications({ maxpagesize: 5 });
    
        // List all Spanish learning paths
        console.log("\n=== Listing Spanish learning paths ===");
        await listLearningPaths({ locale: "es-es", maxpagesize: 5 });
    
        // Get a specific learning path by ID
        console.log("\n=== Getting learning path: learn.introduction-ai-azure ===");
        await getLearningPath("learn.introduction-ai-azure");
    
        // Get a specific module by ID
        console.log("\n=== Getting module: learn.wwl.fundamentals-generative-ai ===");
        await getModule("learn.wwl.fundamentals-generative-ai");
    
        // Get a specific unit by ID
        console.log("\n=== Getting unit: learn.wwl.fundamentals-generative-ai.agents ===");
        await getUnit("learn.wwl.fundamentals-generative-ai.agents");
    
        // Get a specific applied skill by ID
        console.log("\n=== Getting applied skill: applied-skill.deploy-and-configure-azure-monitor ===");
        await getAppliedSkill("applied-skill.deploy-and-configure-azure-monitor");
    
        // Get a specific certification by ID
        console.log("\n=== Getting certification: certification.d365-functional-consultant-customer-service ===");
        await getCertification("certification.d365-functional-consultant-customer-service");
    
        // Get a specific exam by ID
        console.log("\n=== Getting exam: exam.77-881 ===");
        await getExam("exam.77-881");
    
        // Get a specific instructor-led course by ID
        console.log("\n=== Getting instructor-led course: course.ai-900t00 ===");
        await getCourse("course.ai-900t00");
    
      } catch (error) {
        console.error("Error:", error);
      }
    }
    
    main();
    
    

Проверка подлинности и запуск примеров

Выполните следующие действия, чтобы выполнить проверку подлинности в Azure и запустить пример кода.

  1. Войдите в Azure CLI. На этом шаге откроется окно браузера, в котором вы вводите учетные данные Azure.

    az login
    
  2. Если у вас несколько подписок, задайте активный. Замените <your-subscription-name> на имя подписки или идентификатор.

    az account set --subscription "<your-subscription-name>"
    
  3. Убедитесь, что ваши учетные данные могут получить доступ к API платформы Learn.

    az account get-access-token --resource https://learn.microsoft.com
    

    В случае успешного выполнения вы увидите ответ JSON с полем accessToken .

  4. Запустите файл примеров, используя npx для выполнения tsx пакета.

    npx tsx examples.ts
    
  5. (Необязательно) Сохраните выходные данные в файл с помощью перенаправления выходных данных.

    npx tsx examples.ts > output.txt 2>&1
    

Очистите ресурсы

Если ресурсы, созданные в этом кратком руководстве, больше не нужны, их можно удалить.

  1. Удалите папку проекта и все его содержимое.

    cd ..
    rm -rf learn-api-examples
    

    В Windows PowerShell используйте:

    cd ..
    Remove-Item -Recurse -Force learn-api-examples
    
  2. (Необязательно) Выйдите из Azure CLI, чтобы удалить кэшированные учетные данные.

    az logout
    

Замечание

В этом кратком руководстве не создаются ресурсы Azure, которые обычно влекут за собой затраты. Вызовы API используют существующее удостоверение Azure только для проверки подлинности.