Skip to content

Upgrading

This page documents breaking changes, new features, and migration steps for releases that require your attention when upgrading. New versions are listed from newest to oldest.

v2 is a major release that streamlines the module’s configuration and storage layers. Module declarations are now consistently array-based, custom database tables are powered by Drizzle ORM, and the package’s public import paths have been tidied up. A few legacy options - MySQL storage and the AI Tools modules - have been removed. The sections below cover each breaking change and the steps to migrate.

All module declarations now require array syntax. Single-object declarations are no longer supported for module properties except projectIntegration and api.

Before:

const configuration = {
customMT: {
translate
}
};

After:

const configuration = {
customMT: [
{
translate
}
]
};

Affected module properties:

  • customFileFormat, customMT, profileResourcesMenu, profileSettingsMenu, organizationMenu, organizationSettingsMenu
  • editorRightPanel, projectMenu, projectMenuCrowdsource, projectTools, projectReports, contextMenu, modal
  • filePreImport, filePostImport, filePreExport, filePostExport, fileTranslationsAlignmentExport
  • customSpellchecker, aiProvider, aiPromptProvider, aiRequestPreCompile, aiRequestPostCompile, aiRequestPreParse, aiRequestPostParse
  • externalQaCheck, webhooks, workflowStepType, automationAction, authGuard

Migration:

  1. Wrap each affected module configuration object in [...].
  2. Keep projectIntegration and api as single objects.
  3. If you configure multiple instances, keep using the same array with multiple items.

Custom Database Tables Now Use Drizzle ORM

Section titled “Custom Database Tables Now Use Drizzle ORM”

The module now uses Drizzle ORM for custom tables. The previous raw-SQL API - storage.registerCustomTable() and the related custom query helpers - has been removed.

Before:

await crowdinApp.storage.registerCustomTable('translations', {
id: 'INTEGER PRIMARY KEY AUTOINCREMENT',
content: 'TEXT',
});

After:

import * as schema from './schema.js';
configuration.customTables = {
schema,
migrationFolder: './migrations', // SQLite / PostgreSQL
d1Migrations: migrations, // Cloudflare D1
};
// access the Drizzle instance
const db = crowdinApp.storage.db;

Migration:

  1. Install drizzle-orm and drizzle-kit.
  2. Define your tables as a Drizzle schema and generate migrations (or declare them manually for D1).
  3. Register them via configuration.customTables and rewrite custom queries with the Drizzle API.

See the Database guide for full details.

Public import subpaths have been consolidated. Only documented paths are supported; internal paths may change without notice.

Removed:

  • @crowdin/app-project-module/out/* - internal build output, no longer exposed
  • @crowdin/app-project-module/storage
  • @crowdin/app-project-module/modules/integration/util

Added:

  • @crowdin/app-project-module/test - app testing utilities

Migration: import Storage and other types from the main entrypoint @crowdin/app-project-module, and replace any /out/* imports with the corresponding public subpath. See supported import paths.

The aiTools and aiToolsWidget modules have been removed. Remove these options from your configuration; there is no direct replacement.

MySQL is no longer a supported storage backend. The mysqlConfig option has been removed. Supported databases are now SQLite (default), PostgreSQL, and Cloudflare D1.

Migration: switch to PostgreSQL (or SQLite). There is no automatic MySQL migration - move your data to a supported database manually.

Crowdin app helpers that previously lived in the standalone npm package @crowdin/crowdin-apps-functions are now shipped with this module. Prefer the built-in entry points so your app stays aligned with the Apps SDK version you already depend on.

Migration from @crowdin/crowdin-apps-functions

Section titled “Migration from @crowdin/crowdin-apps-functions”
  • Action required: Remove @crowdin/crowdin-apps-functions from your dependencies and replace imports with the subpaths below.
  • Token helpers (OAuth, app tokens, JWT validation, Crowdin id parsing) - import from @crowdin/app-project-module/functions/token.
  • Crowdin API helpers (files, folders, translations, webhooks, subscriptions) - import from @crowdin/app-project-module/functions/crowdin.

The API surface matches what the standalone library provided; see App Functions for exports, subpath names, and usage examples.

The project now uses react-jsonschema-form v6. Modules that define UI as a formSchema should review the breaking changes below.

  • enumNames - Use ui:enumNames in UiSchema instead of enumNames on the schema
  • idSchema, formContext, classNames, themes, callbacks - see the upgrade guide for details

See the 6.x Upgrade Guide for full details.

Major release introducing Cloudflare Workers support, Express 5 upgrade, and architectural improvements.

  • Action required: Test your application thoroughly after upgrading
  • Potential issues: Some third-party middleware may need updates, subtle error handling differences
  • Action required: If using S3 file processing, manually install:
    Terminal window
    npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
  • Benefit: Smaller bundle size for apps not using AWS S3

All functions now follow the parameter object pattern (also known as an options object or named parameters via destructuring).

This means functions that previously took several positional arguments now accept a single options object - destructured in the signature - which improves readability and makes optional parameters easier to manage.

Before:

// positional parameters
getCrowdinFiles: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any, mode?: CrowdinFilesLoadMode) => Promise<TreeItem[]>;

After:

// parameter object (destructured)
getCrowdinFiles: (options: {
projectId: number;
client: Crowdin;
rootFolder?: SourceFilesModel.Directory;
settings?: any;
mode?: CrowdinFilesLoadMode;
}) => Promise<TreeItem[]>;

Example:

Before:

configuration.projectIntegration.cronJobs = [
{
expression: '*/10 * * * * *',
task: (projectId, credentials, rootFolder, settings) => {
console.log(`Running background task for project: ${projectId}`);
console.log(`Api credentials: ${JSON.stringify(credentials)}`);
console.log(`App config: ${JSON.stringify(settings)}`);
console.log(rootFolder ? JSON.stringify(rootFolder) : 'No root folder');
}
}
];

After:

configuration.projectIntegration.cronJobs = [
{
expression: '*/10 * * * * *',
task: ({ projectId, credentials, rootFolder, settings } = {}) => {
console.log(`Running background task for project: ${projectId}`);
console.log(`Api credentials: ${JSON.stringify(credentials)}`);
console.log(`App config: ${JSON.stringify(settings)}`);
console.log(rootFolder ? JSON.stringify(rootFolder) : 'No root folder');
}
}
];

List of all affected functions (some functions that already used parameter objects were renamed or had parameter names updated):

Updated functions (now accept a parameter object)

Section titled “Updated functions (now accept a parameter object)”

These functions now accept a single destructured options object (e.g., fn({ a, b, c })).

  • decryptCrowdinConnection
  • establishCrowdinConnection
  • log
  • onError
  • onUninstall
  • saveMetadata
  • aiPromptProvider
    • compile
  • aiProvider
    • chatCompletions
  • aiRequestPreCompile
    • processRequest
    • processStream
  • aiTools
    • toolCalls
  • automationAction
    • execute
    • validateSettings
  • customMT
    • translate
File processing (modules: customFileFormat, filePreImport, filePostImport, filePreExport, filePostExport, fileTranslationsAlignmentExport)
Section titled “File processing (modules: customFileFormat, filePreImport, filePostImport, filePreExport, filePostExport, fileTranslationsAlignmentExport)”
  • buildFile
  • exportStrings
  • fileProcess
  • parseFile
  • crowdinWebhookInterceptor
  • crowdinWebhooks
  • getAuthorizationUrl
  • getConfiguration
  • getCrowdinFiles
  • getFileProgress
  • getIntegrationFiles
  • integrationWebhookInterceptor
  • integrationWebhooks
  • matchCrowdinFilesToIntegrationFiles
  • normalizeSettings
  • onLogout
  • performGetTokenRequest (oauthLogin)
  • performRefreshTokenRequest (oauthLogin)
  • task
  • updateCrowdin
  • updateIntegration
  • validateSettings
  • D1 Database: d1Config for serverless SQL database
  • Custom Cron: cron option for Workers scheduled events
  • File Storage: fileStore interface for external storage (S3, R2, etc.)
  • Assets: assetsConfig for Workers Assets integration, assetsPath for custom static directory
  • Webhooks: deferResponse: true required for proper Workers execution
  1. Update package.json: "@crowdin/app-project-module": "^1.0.0"
  2. Install AWS SDK if needed: (see breaking changes above)
  3. Test Express 5 compatibility
  • Updated: Express 4 → 5, React 18 added (internal)
  • Moved to optional: AWS SDK packages