@crowdin/app-project-module
Version:
Module that generates for you all common endpoints for serving standalone Crowdin App
505 lines (504 loc) • 14.4 kB
TypeScript
import Crowdin from '@crowdin/crowdin-api-client';
import { JwtPayload, VerifyOptions } from '@crowdin/crowdin-apps-functions';
import { Request } from 'express';
import { ContextContent } from './modules/context-menu/types';
import { CustomMTLogic } from './modules/custom-mt/types';
import { CustomSpellcheckerModule } from './modules/custom-spell-check/types';
import { EditorPanels } from './modules/editor-right-panel/types';
import { CustomFileFormatLogic, FilePostExportLogic, FilePostImportLogic, FilePreExportLogic, FilePreImportLogic } from './modules/file-processing/types';
import { IntegrationLogic } from './modules/integration/types';
import { Storage } from './storage';
import { MySQLStorageConfig } from './storage/mysql';
import { PostgreStorageConfig } from './storage/postgre';
import { ApiModule } from './modules/api/types';
import { LogErrorFunction, LogFunction } from './util/logger';
import { AiProviderModule } from './modules/ai-provider/types';
import { AiPromptProviderModule } from './modules/ai-prompt-provider/types';
import { AiTool, AiToolWidget } from './modules/ai-tools/types';
import { ExternalQaCheckModule } from './modules/external-qa-check/types';
import { Webhook } from './modules/webhooks/types';
import { WorkflowStepTypeModule } from './modules/workflow-step-type/types';
import { AiRequestProcessorModule, AiStreamProcessorModule } from './modules/ai-request-processors/types';
export interface ClientConfig extends ImagePath {
/**
* Authentication Crowdin App type: "authorization_code", "crowdin_app", "crowdin_agent". Default: "crowdin_app"
*/
authenticationType?: AuthenticationType;
/**
* Crowdin Agent information: name, username, avatarUrl
*/
agent?: Agent;
/**
* client id that we received when registering the app
*/
clientId?: string;
/**
* client secret that we received when registering the app
*/
clientSecret?: string;
/**
* Secret to encrypt/decrypt credentials (by default @clientSecret will be used)
*/
cryptoSecret?: string;
/**
* Options to validate Crowdin JWT token
*/
jwtValidationOptions?: VerifyOptions;
/**
* https url where an app is reachable from the internet (e.g. the one that ngrok generates for us)
*/
baseUrl?: string;
/**
* define custom Crowdin urls (e.g. to work against local Crowdin server)
*/
crowdinUrls?: CrowdinUrls;
/**
* define custom User Agent in requests to Crowdin
*/
crowdinApiUserAgent?: string;
/**
* Set of scopes requested by this app (default 'project')
*/
scopes?: Scope[];
/**
* app name
*/
name: string;
/**
* app identifier
*/
identifier: string;
/**
* app description
*/
description: string;
/**
* link to the app's description/detail page
*/
detailPage?: string;
/**
* Set default app permissions
*/
defaultPermissions?: DefaultPermissions;
/**
* port where to start express application
*/
port?: number;
/**
* folder where module will create sqlite db file to persist credentials (e.g. {@example __dirname})
*/
dbFolder?: string;
/**
* migrate from SQLite to PostgreSQL
*/
migrateToPostgreFromSQLite?: boolean;
/**
* config to configure PostgreSQL as a storage
*/
postgreConfig?: PostgreStorageConfig;
/**
* config to configure MySQL as a storage
*/
mysqlConfig?: MySQLStorageConfig;
/**
* integration module logic
*/
projectIntegration?: IntegrationLogic & ImagePath & Environments;
/**
* custom file format module logic
*/
customFileFormat?: CustomFileFormatLogic;
/**
* custom MT module logic
*/
customMT?: CustomMTLogic & ImagePath & Environments;
/**
* resources module
*/
profileResourcesMenu?: UiModule & ImagePath & Environments;
/**
* profile-settings-menu module
*/
profileSettingsMenu?: UiModule & ImagePath & Environments;
/**
* organization-menu module
*/
organizationMenu?: UiModule & ImagePath;
/**
* organization-settings-menu module
*/
organizationSettingsMenu?: UiModule & ImagePath;
/**
* editor-right-panel module
*/
editorRightPanel?: EditorPanels & Environments;
/**
* project menu module
*/
projectMenu?: UiModule & Environments;
/**
* project menu crowdsource module
*/
projectMenuCrowdsource?: UiModule;
/**
* tools module
*/
projectTools?: UiModule & ImagePath & Environments;
/**
* reports module
*/
projectReports?: UiModule & ImagePath;
/**
* API module
*/
api?: ApiModule;
/**
* context menu module
*/
contextMenu?: ContextModule | ContextModule[];
/**
* modal module
*/
modal?: ModalModule | ModalModule[];
/**
* Install hook
*/
onInstall?: ({ organization, userId, client, }: {
organization: string;
userId: number;
client: Crowdin;
}) => Promise<void>;
/**
* Uninstall hook for cleanup logic
*/
onUninstall?: (organization: string, allCredentials: {
settings?: any;
credentials: any;
}[]) => Promise<void>;
/**
* Error interceptor (can be used to log error in centralized place)
*/
onError?: (error: any, context?: CrowdinContextInfo) => void;
/**
* Disable global error handling of unhandledRejection and uncaughtException events
*/
disableGlobalErrorHandling?: boolean;
/**
* Configuration to log everything that are happening in the app
*/
logger?: Logger;
/**
* Enable status page with optional db and filesystem checks
*/
enableStatusPage?: {
database?: boolean;
filesystem?: boolean;
rateLimit?: number;
};
/**
* Configuration of app pricing
*/
pricing?: Pricing;
filePreImport?: FilePreImportLogic;
filePostImport?: FilePostImportLogic;
filePreExport?: FilePreExportLogic;
filePostExport?: FilePostExportLogic;
/**
* Disable formatting logs
*/
disableLogsFormatter?: boolean;
/**
* AWS configuration for uploading big files to temporary bucket. Used with customFileFormat and file processors modules.
*
* Not necessary to configure if environment variables AWS_REGION and AWS_TMP_BUCKET_NAME are properly set.
*/
awsConfig?: AWSConfig;
customSpellchecker?: CustomSpellcheckerModule;
/**
* ai provider module
*/
aiProvider?: AiProviderModule & ImagePath;
/**
* ai prompt provider module
*/
aiPromptProvider?: AiPromptProviderModule & ImagePath;
/**
* ai request pre-compile processor module
*/
aiRequestPreCompile?: AiRequestProcessorModule;
/**
* ai request post-compile processor module
*/
aiRequestPostCompile?: AiRequestProcessorModule;
/**
* ai request pre-parse processor module
*/
aiRequestPreParse?: AiStreamProcessorModule;
/**
* ai request post-parse processor module
*/
aiRequestPostParse?: AiRequestProcessorModule;
/**
* AI tool_calls modules
*/
aiTools?: AiTool | AiTool[];
/**
* AI tool_calls modules with UI widgets
*/
aiToolsWidget?: AiToolWidget | AiToolWidget[];
/**
* qa check module
*/
externalQaCheck?: ExternalQaCheckModule & ImagePath;
/**
* webhook modules
*/
webhooks?: Webhook | Webhook[];
/**
* workflow step modules
*/
workflowStepType?: WorkflowStepTypeModule | WorkflowStepTypeModule[];
/**
* property that tells backend that AiProvider and AiPromptProvider modules can cooperate only with each one
*/
restrictAiToSameApp?: boolean;
}
export interface Environments {
environments?: Environment | Environment[];
}
type Environment = 'crowdin' | 'crowdin-enterprise';
export type Config = ClientConfig & {
baseUrl: string;
clientId: string;
clientSecret: string;
port: number;
dbFolder: string;
imagePath: string;
};
export type UnauthorizedConfig = Omit<Config, 'clientId' | 'clientSecret'> & {
clientId?: string;
clientSecret?: string;
};
export declare enum AuthenticationType {
CODE = "authorization_code",
APP = "crowdin_app",
AGENT = "crowdin_agent",
NONE = "none"
}
export interface Agent {
name?: string;
username: string;
avatarUrl?: string;
}
export interface CrowdinUrls {
apiUrl?: string;
accountUrl?: string;
subscriptionUrl?: string;
}
export declare enum Scope {
ALL_SCOPES = "all",
NOTIFICATIONS = "notification",
TRANSLATION_MEMORIES = "tm",
MACHINE_TRANSLATION_ENGINES = "mt",
GLOSSARIES = "glossary",
USERS = "user",
TEAMS = "team",
GROUPS = "group",
PROJECTS = "project",
TASKS = "project.task",
REPORTS = "project.report",
TRANSLATION_STATUS = "project.status",
SOURCE_FILES_AND_STRINGS = "project.source",
WEBHOOKS = "project.webhook",
ORGANIZATION_WEBHOOKS = "webhook",
TRANSLATIONS = "project.translation",
SCREENSHOTS = "project.screenshot",
SECURITY_LOGS = "security-log",
VENDORS = "vendor",
FIELDS = "field",
AI = "ai",
AI_PROVIDERS = "ai.provider",
AI_PROMPTS = "ai.prompt",
AI_PROXIES = "ai.proxy",
APPLICATIONS = "application"
}
export interface CrowdinClientRequest extends Request {
crowdinApiClient: Crowdin;
crowdinContext: CrowdinContextInfo;
subscriptionInfo?: SubscriptionInfo;
logInfo: LogFunction;
logError: LogErrorFunction;
isApiCall?: boolean;
}
export interface CrowdinCredentials {
id: string;
appSecret: string;
domain?: string;
userId: number;
agentId?: number;
organizationId: number;
baseUrl: string;
accessToken: string;
refreshToken: string;
expire: string;
type: AccountType;
}
export declare enum AccountType {
NORMAL = "normal",
ENTERPRISE = "enterprise"
}
export interface CrowdinContextInfo {
jwtPayload: JwtPayload;
crowdinId: string;
clientId: string;
appIdentifier: string;
}
export declare enum SubscriptionInfoType {
TRIAL = "trial",
SUBSCRIPTION = "subscription"
}
export interface SubscriptionInfo {
expired: boolean;
subscribeLink?: string;
daysLeft?: number;
type?: SubscriptionInfoType;
}
export declare enum EditorMode {
ASSETS = "assets",
REVIEW = "review",
TRANSLATE = "TRANSLATE",
PROOFREAD = "proofread",
COMFORTABLE = "comfortable",
SIDE_BY_SIDE = "side-by-side",
MULTILINGUAL = "multilingual"
}
interface ModuleContent {
/**
* relative URL to the content page of the module
*/
url?: string;
}
export interface CrowdinAppUtilities extends CrowdinMetadataStore {
establishCrowdinConnection: (authRequest: string | CrowdinClientRequest, moduleKey: string[] | string | undefined) => Promise<{
context: CrowdinContextInfo;
client?: Crowdin;
}>;
encryptCrowdinConnection: (data: {
crowdinId: string;
extra: Record<string, any>;
}) => string;
dencryptCrowdinConnection: (hash: string, autoRenew?: boolean) => Promise<{
client: Crowdin;
extra: Record<string, any>;
}>;
storage: Storage;
}
export interface CrowdinMetadataStore {
saveMetadata: (id: string, metadata: any, crowdinId: string) => Promise<void>;
getMetadata: (id: string) => Promise<any | undefined>;
deleteMetadata: (id: string) => Promise<void>;
/**
* Settings that users manage in the integration module
*/
getUserSettings: (clientId: string) => Promise<any | undefined>;
}
export interface UiModule extends ModuleKey {
/**
* Form schema for react-jsonschema-doc to be used as front-end
* https://rjsf-team.github.io/react-jsonschema-form/docs
*/
formSchema?: object;
/**
* URL to custom endpoint that can be used instead of default one to save form data.
* Endpoint should accept POST requests.
*/
formPostDataUrl?: string;
/**
* URL to custom endpoint that can be used instead of default one to retrieve form data.
* Endpoint should accept GET requests.
*/
formGetDataUrl?: string;
/**
* Additional attributes for react-jsonschema-doc
*/
formUiSchema?: object;
/**
* path to ui folder (e.g. {@example join(__dirname, 'public')})
*/
uiPath?: string;
/**
* page name (default index.html)
*/
fileName?: string;
/**
* Module name
*/
name?: string;
/**
* Temporary property. Indicates if passwords should be masked. Will be dropped when all existing apps will migrate.
*/
maskPasswords?: boolean;
}
export interface ModuleKey {
/**
* key to identify module
*/
key?: string;
}
export interface ImagePath {
/**
* path to app logo (e.g. {@example join(__dirname, 'logo.png')})
*/
imagePath?: string;
}
export interface Logger {
enabled: boolean;
log?: (message: string, context?: CrowdinContextInfo) => void;
}
export interface Pricing {
planType: 'free' | 'recurring';
trial?: number;
trialCrowdin?: number;
trialEnterprise?: number;
cachingSeconds?: number;
infoDisplayDaysThreshold?: number;
}
export declare enum UserPermissions {
OWNER = "owner",
MANAGERS = "managers",
ALL_MEMBERS = "all",
GUESTS = "guests",
RESTRICTED = "restricted"
}
export declare enum ProjectPermissions {
OWN = "own",
RESTRICTED = "restricted"
}
export interface DefaultPermissions {
user?: UserPermissions;
project?: ProjectPermissions;
}
export interface AWSConfig {
/**
* AWS bucket name for temporary files
*/
tmpBucketName?: string;
/**
* AWS region
*/
region?: string;
}
export interface SignaturePatterns {
fileName?: string;
fileContent?: string;
}
export declare enum storageFiles {
SQLITE = "app.sqlite",
SQLITE_BACKUP = "backup_app.sqlite",
DUMP = "dump_table_%s.sql"
}
export interface ModalModule extends ModuleContent, UiModule, Environments {
}
export interface ContextModule extends ContextContent, UiModule, Environments {
}
export {};