Skip to content

Новая версия внешнего API Airtable #1

@Tozarin

Description

@Tozarin

Новая версия API для Airtable-интеграции

Сервис Airtable изменил точку входа для получения метаданных баз и синхронизации данных. Старый эндпоинт будет выведен из эксплуатации. Необходимо адаптировать наш код.

  • Было (v1):
    • GET https://api.airtable.com/v0/{baseId}/{tableIdOrName}
    • Аутентификация: Authorization: Bearer {apiKey}
  • Стало (v2):
    • GET https://api.airtable.com/v0/meta/bases/{baseId}/tables
    • Аутентификация: Authorization: Bearer {personalAccessToken}
    • Query параметр: ?api_version=2

Обоснование

  1. Новая система аутентификации: переход с API Keys на Personal Access Tokens (PAT) для улучшенной безопасности
  2. Унифицированный метаданные endpoint: новый /meta/bases/ endpoint предоставляет структурированный доступ к схеме базы
  3. Версионирование через query-параметры: позволяет гибко управлять версией API без изменения базового URL
  4. Расширенные возможности: v2 API предоставляет дополнительные метаданные о полях, представлениях и связях

Детали изменения

1. Константы и конфигурация (tests/playwright/constants/index.ts)

Добавлены параметры:

const AIRTABLE_API_VERSION = process.env.AIRTABLE_API_VERSION || 'v1';
const AIRTABLE_BASE_URL = 'https://api.airtable.com/v0';
  • Тип: String
  • По умолчанию: 'v1'
  • Описание: Версия API Airtable для использования (v1 или v2)
  • Возможные значения:
    • 'v1' - использует legacy endpoint с API Key
    • 'v2' - использует новый meta endpoint с PAT и query параметром api_version=2

2. Компонент импорта (packages/nc-gui/components/dlg/AirtableImport.vue)

Изменения в структуре syncSource:

const syncSource = ref({
  id: '',
  type: 'Airtable',
  details: {
    syncInterval: '15mins',
    syncDirection: 'Airtable to NocoDB',
    syncRetryCount: 1,
    apiKey: '',              // Deprecated в v2, заменён на personalAccessToken
    personalAccessToken: '', // Новое поле для v2
    appId: '',
    shareId: '',
    syncSourceUrlOrId: '',
    apiVersion: 'v1',        // Новое поле для выбора версии
    options: {
      syncViews: true,
      syncData: true,
      syncRollup: false,
      syncLookup: true,
      syncFormula: false,
      syncAttachment: true,
      syncUsers: false,
    },
  },
})

Логика определения endpoint:

const getAirtableEndpoint = (baseId: string, apiVersion: string) => {
  if (apiVersion === 'v2') {
    return `${AIRTABLE_BASE_URL}/meta/bases/${baseId}/tables?api_version=2`;
  }
  // v1 fallback
  return `${AIRTABLE_BASE_URL}/${baseId}`;
};

Логика аутентификации:

const getAuthHeader = (apiVersion: string, credentials: any) => {
  if (apiVersion === 'v2') {
    return {
      'Authorization': `Bearer ${credentials.personalAccessToken}`
    };
  }
  // v1 fallback
  return {
    'Authorization': `Bearer ${credentials.apiKey}`
  };
};

3. Сервис синхронизации (packages/nocodb/src/services/sync.service.ts)

Обновлена логика подключения к Airtable:

  • Было: Прямое использование apiKey для всех запросов
  • Стало: Проверка версии API и использование соответствующих credentials и endpoints

Добавлена валидация:

// Валидация для v1
if (apiVersion === 'v1' && !details.apiKey) {
  throw new Error('API Key is required for Airtable API v1');
}

// Валидация для v2
if (apiVersion === 'v2' && !details.personalAccessToken) {
  throw new Error('Personal Access Token is required for Airtable API v2');
}

4. Контроллер синхронизации (packages/nocodb/src/controllers/sync.controller.ts)

Обновлены endpoints для поддержки версионирования:

  • Добавлена поддержка query параметра api_version в запросах к Airtable
  • Обратная совместимость с существующими интеграциями через fallback на v1

5. Тесты (tests/playwright/tests/db/features/import.spec.ts)

Обновлены тестовые данные:

// Добавлена поддержка обеих версий API
const airtableApiVersion = process.env.AIRTABLE_API_VERSION || 'v1';

test('Airtable v2 Import', async () => {
  await dashboard.treeView.quickImport({ 
    title: 'Airtable', 
    baseTitle: context.base.title, 
    context 
  });
  await dashboard.importAirtable.import({
    personalAccessToken: airtablePersonalAccessToken,
    sourceId: airtableApiBase,
    apiVersion: 'v2',
  });
  await quickVerify({ dashboard, airtableImport: true, context });
});

Стратегия обратной совместимости

Реализован механизм конфигурируемого переключения версий:

  1. По умолчанию используется v1 - обеспечивает обратную совместимость с существующими интеграциями
  2. Переключение на v2 через:
    • Переменную окружения: AIRTABLE_API_VERSION=v2
    • UI-переключатель в компоненте импорта
    • Параметр в syncSource: apiVersion: 'v2'
  3. Автоматическая миграция credentials:
    • При обнаружении personalAccessToken автоматически используется v2
    • При наличии только apiKey используется v1
  4. Плавный переход - пользователи могут переключиться на v2 в удобное время

Риски и влияние

  • Breaking change для существующих интеграций: при принудительном переключении на v2 потребуется обновление credentials
  • Изменение формата ответа: v2 API возвращает структурированные метаданные, может потребоваться адаптация парсинга
  • Deprecation timeline: необходимо отслеживать сроки отключения v1 API со стороны Airtable
  • Rate limiting: v2 API может иметь другие лимиты запросов
  • Миграция существующих синхронизаций: потребуется механизм обновления сохранённых конфигураций

План тестирования

  • Unit тесты:
    • Корректное формирование URL для v1 и v2
    • Правильная генерация заголовков аутентификации
    • Валидация credentials в зависимости от версии
  • Интеграционные тесты:
    • Успешный импорт данных через v1 API
    • Успешный импорт данных через v2 API
    • Корректная обработка ошибок аутентификации
  • E2E тесты:
    • Полный цикл импорта базы Airtable через UI (v1 и v2)
    • Синхронизация данных с использованием обеих версий
    • Переключение между версиями в существующей интеграции
  • Регрессионные тесты:
    • Проверка работоспособности существующих интеграций (v1 по умолчанию)
    • Обратная совместимость с сохранёнными конфигурациями

Критерии приемки

  • Система корректно работает с v1 API по умолчанию (обратная совместимость)
  • При установке apiVersion: 'v2' используется новый endpoint и PAT
  • UI компонент импорта поддерживает выбор версии API
  • Существующие синхронизации продолжают работать без изменений
  • Новые интеграции могут использовать v2 API
  • Корректная обработка ошибок для обеих версий
  • Документация обновлена и описывает процесс миграции
  • Все тесты проходят успешно

Чеклист задач

  • Добавить параметр AIRTABLE_API_VERSION в конфигурацию
  • Обновить tests/playwright/constants/index.ts с поддержкой версионирования
  • Добавить поле personalAccessToken в интерфейс syncSource
  • Добавить поле apiVersion в интерфейс syncSource
  • Реализовать функцию getAirtableEndpoint() в компоненте импорта
  • Реализовать функцию getAuthHeader() в компоненте импорта
  • Обновить валидацию в AirtableImport.vue
  • Обновить логику в sync.service.ts для поддержки обеих версий
  • Написать unit тесты для новой логики
  • Обновить интеграционные тесты
  • Добавить E2E тесты для v2 API
  • Создать документацию по миграции для пользователей
  • Обновить production после успешного тестирования

Справочная информация

API Endpoints

Airtable API v1 (Legacy)

  • Base URL: https://api.airtable.com/v0
  • Endpoint: /{baseId}/{tableIdOrName}
  • Метод: GET
  • Аутентификация: Authorization: Bearer {apiKey}
  • Формат ответа: JSON с записями таблицы

Airtable API v2 (Current)

  • Base URL: https://api.airtable.com/v0
  • Metadata Endpoint: /meta/bases/{baseId}/tables
  • Data Endpoint: /{baseId}/{tableIdOrName}?api_version=2
  • Метод: GET
  • Аутентификация: Authorization: Bearer {personalAccessToken}
  • Формат ответа: JSON с расширенными метаданными и записями

Миграция credentials

Получение Personal Access Token:

  1. Перейти в Airtable Account Settings
  2. Создать новый Personal Access Token
  3. Выбрать необходимые scopes:
    • data.records:read - для чтения данных
    • schema.bases:read - для чтения структуры базы
  4. Скопировать сгенерированный токен
  5. Использовать токен вместо API Key в конфигурации NocoDB

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions