melaka 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +347 -0
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/docs/AI_PROVIDERS.md +343 -0
- package/docs/ARCHITECTURE.md +512 -0
- package/docs/CLI.md +438 -0
- package/docs/CONFIGURATION.md +453 -0
- package/docs/INTEGRATION.md +477 -0
- package/docs/ROADMAP.md +248 -0
- package/package.json +46 -0
- package/packages/ai/README.md +43 -0
- package/packages/ai/package.json +42 -0
- package/packages/ai/src/facade.ts +120 -0
- package/packages/ai/src/index.ts +34 -0
- package/packages/ai/src/prompt.ts +117 -0
- package/packages/ai/src/providers/gemini.ts +185 -0
- package/packages/ai/src/providers/index.ts +9 -0
- package/packages/ai/src/types.ts +134 -0
- package/packages/ai/tsconfig.json +19 -0
- package/packages/cli/README.md +70 -0
- package/packages/cli/package.json +44 -0
- package/packages/cli/src/cli.ts +30 -0
- package/packages/cli/src/commands/deploy.ts +115 -0
- package/packages/cli/src/commands/index.ts +9 -0
- package/packages/cli/src/commands/init.ts +107 -0
- package/packages/cli/src/commands/status.ts +73 -0
- package/packages/cli/src/commands/translate.ts +92 -0
- package/packages/cli/src/commands/validate.ts +69 -0
- package/packages/cli/tsconfig.json +19 -0
- package/packages/core/README.md +46 -0
- package/packages/core/package.json +50 -0
- package/packages/core/src/config.ts +241 -0
- package/packages/core/src/index.ts +111 -0
- package/packages/core/src/schema-generator.ts +263 -0
- package/packages/core/src/schemas.ts +126 -0
- package/packages/core/src/types.ts +481 -0
- package/packages/core/src/utils.ts +343 -0
- package/packages/core/tsconfig.json +19 -0
- package/packages/firestore/README.md +60 -0
- package/packages/firestore/package.json +48 -0
- package/packages/firestore/src/generator.ts +270 -0
- package/packages/firestore/src/i18n.ts +262 -0
- package/packages/firestore/src/index.ts +54 -0
- package/packages/firestore/src/processor.ts +245 -0
- package/packages/firestore/src/queue.ts +202 -0
- package/packages/firestore/src/task-handler.ts +164 -0
- package/packages/firestore/tsconfig.json +19 -0
- package/pnpm-workspace.yaml +2 -0
- package/turbo.json +31 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Melaka CLI - Validate Command
|
|
3
|
+
*
|
|
4
|
+
* Validate the melaka.config.ts file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { loadConfig, configExists, getLanguageName } from '@melaka/core';
|
|
9
|
+
|
|
10
|
+
export const validateCommand = new Command('validate')
|
|
11
|
+
.description('Validate melaka.config.ts')
|
|
12
|
+
.action(async () => {
|
|
13
|
+
const chalk = (await import('chalk')).default;
|
|
14
|
+
const ora = (await import('ora')).default;
|
|
15
|
+
|
|
16
|
+
// Check if config exists
|
|
17
|
+
const existsSpinner = ora('Checking for melaka.config.ts...').start();
|
|
18
|
+
const exists = await configExists();
|
|
19
|
+
|
|
20
|
+
if (!exists) {
|
|
21
|
+
existsSpinner.fail('melaka.config.ts not found');
|
|
22
|
+
console.log('');
|
|
23
|
+
console.log(chalk.gray('Run `melaka init` to create one.'));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
existsSpinner.succeed('Found melaka.config.ts');
|
|
28
|
+
|
|
29
|
+
// Load and validate
|
|
30
|
+
const validateSpinner = ora('Validating configuration...').start();
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const config = await loadConfig();
|
|
34
|
+
validateSpinner.succeed('Configuration is valid');
|
|
35
|
+
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(chalk.green('✓ Config file found: melaka.config.ts'));
|
|
38
|
+
|
|
39
|
+
// Languages
|
|
40
|
+
const langList = config.languages
|
|
41
|
+
.map((l) => `${l}`)
|
|
42
|
+
.join(', ');
|
|
43
|
+
console.log(chalk.green(`✓ Languages valid: ${langList}`));
|
|
44
|
+
|
|
45
|
+
// AI Provider
|
|
46
|
+
console.log(chalk.green(`✓ AI provider configured: ${config.ai.provider} (${config.ai.model})`));
|
|
47
|
+
|
|
48
|
+
// Collections
|
|
49
|
+
console.log(chalk.green(`✓ Collections configured: ${config.collections.length}`));
|
|
50
|
+
for (const collection of config.collections) {
|
|
51
|
+
const fieldCount = collection.fields?.length || 'auto';
|
|
52
|
+
const groupFlag = collection.isCollectionGroup ? ' (collection group)' : '';
|
|
53
|
+
console.log(chalk.gray(` - ${collection.path} (${fieldCount} fields)${groupFlag}`));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Glossary
|
|
57
|
+
const glossaryCount = config.glossary ? Object.keys(config.glossary).length : 0;
|
|
58
|
+
console.log(chalk.green(`✓ Glossary entries: ${glossaryCount}`));
|
|
59
|
+
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(chalk.green('✨ Config is valid!'));
|
|
62
|
+
console.log('');
|
|
63
|
+
} catch (error) {
|
|
64
|
+
validateSpinner.fail('Configuration is invalid');
|
|
65
|
+
console.log('');
|
|
66
|
+
console.error(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
"outDir": "./dist",
|
|
15
|
+
"rootDir": "./src"
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @melaka/core
|
|
2
|
+
|
|
3
|
+
Core types, utilities, and configuration for Melaka.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @melaka/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Define Configuration
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { defineConfig } from '@melaka/core';
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
languages: ['ms-MY', 'zh-CN'],
|
|
20
|
+
ai: {
|
|
21
|
+
provider: 'gemini',
|
|
22
|
+
model: 'gemini-2.5-flash',
|
|
23
|
+
},
|
|
24
|
+
collections: [
|
|
25
|
+
{
|
|
26
|
+
path: 'articles',
|
|
27
|
+
fields: ['title', 'content'],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Types
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import type {
|
|
37
|
+
MelakaConfig,
|
|
38
|
+
CollectionConfig,
|
|
39
|
+
FieldMapping,
|
|
40
|
+
TranslationResult,
|
|
41
|
+
} from '@melaka/core';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API Reference
|
|
45
|
+
|
|
46
|
+
See [types.ts](./src/types.ts) for full type definitions.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@melaka/core",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Core types and utilities for Melaka",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
20
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"lint": "eslint src/",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"clean": "rm -rf dist"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"zod": "^3.22.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"firebase-admin": "^12.0.0",
|
|
32
|
+
"tsup": "^8.0.0",
|
|
33
|
+
"typescript": "^5.3.0",
|
|
34
|
+
"vitest": "^1.2.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"firebase-admin": ">=11.0.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"firebase-admin": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/rizahassan/melaka.git",
|
|
47
|
+
"directory": "packages/core"
|
|
48
|
+
},
|
|
49
|
+
"license": "MIT"
|
|
50
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Melaka Core - Config Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates melaka.config.ts configuration files.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { pathToFileURL } from 'url';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { MelakaConfigSchema } from './schemas';
|
|
10
|
+
import type { MelakaConfig, CollectionConfig, AIConfig } from './types';
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Config Loading
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Load and validate a Melaka configuration file.
|
|
18
|
+
*
|
|
19
|
+
* Supports both TypeScript (.ts) and JavaScript (.js) config files.
|
|
20
|
+
* The config file must export a default configuration object.
|
|
21
|
+
*
|
|
22
|
+
* @param configPath - Path to config file (defaults to 'melaka.config.ts' in cwd)
|
|
23
|
+
* @returns Validated configuration
|
|
24
|
+
* @throws Error if config file not found or invalid
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const config = await loadConfig();
|
|
29
|
+
* // or
|
|
30
|
+
* const config = await loadConfig('/path/to/melaka.config.ts');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export async function loadConfig(configPath?: string): Promise<MelakaConfig> {
|
|
34
|
+
const resolvedPath = await resolveConfigPath(configPath);
|
|
35
|
+
|
|
36
|
+
// Check if file exists
|
|
37
|
+
const fs = await import('fs/promises');
|
|
38
|
+
try {
|
|
39
|
+
await fs.access(resolvedPath);
|
|
40
|
+
} catch {
|
|
41
|
+
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Import the config file
|
|
45
|
+
let configModule: unknown;
|
|
46
|
+
try {
|
|
47
|
+
// Use file URL for ESM compatibility
|
|
48
|
+
const fileUrl = pathToFileURL(resolvedPath).href;
|
|
49
|
+
configModule = await import(fileUrl);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Failed to load config file: ${resolvedPath}\n${error instanceof Error ? error.message : String(error)}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Extract default export
|
|
57
|
+
const rawConfig = (configModule as { default?: unknown }).default;
|
|
58
|
+
if (!rawConfig) {
|
|
59
|
+
throw new Error(`Config file must have a default export: ${resolvedPath}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Validate with Zod
|
|
63
|
+
const result = MelakaConfigSchema.safeParse(rawConfig);
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
const errors = result.error.errors
|
|
66
|
+
.map((e) => ` - ${e.path.join('.')}: ${e.message}`)
|
|
67
|
+
.join('\n');
|
|
68
|
+
throw new Error(`Invalid configuration:\n${errors}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result.data as MelakaConfig;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Resolve the config file path.
|
|
76
|
+
*
|
|
77
|
+
* Checks for config files in order: .ts, .js, .mjs
|
|
78
|
+
*
|
|
79
|
+
* @param configPath - Optional explicit path
|
|
80
|
+
* @returns Resolved absolute path
|
|
81
|
+
*/
|
|
82
|
+
async function resolveConfigPath(configPath?: string): Promise<string> {
|
|
83
|
+
if (configPath) {
|
|
84
|
+
return path.resolve(configPath);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const fs = await import('fs/promises');
|
|
88
|
+
const cwd = process.cwd();
|
|
89
|
+
|
|
90
|
+
// Check for config files in order of preference
|
|
91
|
+
const configFiles = [
|
|
92
|
+
'melaka.config.ts',
|
|
93
|
+
'melaka.config.js',
|
|
94
|
+
'melaka.config.mjs',
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
for (const filename of configFiles) {
|
|
98
|
+
const fullPath = path.resolve(cwd, filename);
|
|
99
|
+
try {
|
|
100
|
+
await fs.access(fullPath);
|
|
101
|
+
return fullPath;
|
|
102
|
+
} catch {
|
|
103
|
+
// File doesn't exist, try next
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Default to .ts for error messages
|
|
108
|
+
return path.resolve(cwd, 'melaka.config.ts');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Config Helpers
|
|
113
|
+
// ============================================================================
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Get the effective AI config for a collection.
|
|
117
|
+
*
|
|
118
|
+
* Merges collection-specific AI overrides with root AI config.
|
|
119
|
+
*
|
|
120
|
+
* @param rootConfig - Root Melaka configuration
|
|
121
|
+
* @param collection - Collection configuration
|
|
122
|
+
* @returns Effective AI config
|
|
123
|
+
*/
|
|
124
|
+
export function getEffectiveAIConfig(
|
|
125
|
+
rootConfig: MelakaConfig,
|
|
126
|
+
collection: CollectionConfig
|
|
127
|
+
): AIConfig {
|
|
128
|
+
return {
|
|
129
|
+
...rootConfig.ai,
|
|
130
|
+
...(collection.ai || {}),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the effective batch size for a collection.
|
|
136
|
+
*
|
|
137
|
+
* @param rootConfig - Root Melaka configuration
|
|
138
|
+
* @param collection - Collection configuration
|
|
139
|
+
* @returns Effective batch size
|
|
140
|
+
*/
|
|
141
|
+
export function getEffectiveBatchSize(
|
|
142
|
+
rootConfig: MelakaConfig,
|
|
143
|
+
collection: CollectionConfig
|
|
144
|
+
): number {
|
|
145
|
+
return (
|
|
146
|
+
collection.batchSize ||
|
|
147
|
+
rootConfig.defaults?.batchSize ||
|
|
148
|
+
20
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get the effective max concurrency for a collection.
|
|
154
|
+
*
|
|
155
|
+
* @param rootConfig - Root Melaka configuration
|
|
156
|
+
* @param collection - Collection configuration
|
|
157
|
+
* @returns Effective max concurrency
|
|
158
|
+
*/
|
|
159
|
+
export function getEffectiveMaxConcurrency(
|
|
160
|
+
rootConfig: MelakaConfig,
|
|
161
|
+
collection: CollectionConfig
|
|
162
|
+
): number {
|
|
163
|
+
return (
|
|
164
|
+
collection.maxConcurrency ||
|
|
165
|
+
rootConfig.defaults?.maxConcurrency ||
|
|
166
|
+
10
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get the effective forceUpdate flag for a collection.
|
|
172
|
+
*
|
|
173
|
+
* @param rootConfig - Root Melaka configuration
|
|
174
|
+
* @param collection - Collection configuration
|
|
175
|
+
* @returns Effective forceUpdate value
|
|
176
|
+
*/
|
|
177
|
+
export function getEffectiveForceUpdate(
|
|
178
|
+
rootConfig: MelakaConfig,
|
|
179
|
+
collection: CollectionConfig
|
|
180
|
+
): boolean {
|
|
181
|
+
return (
|
|
182
|
+
collection.forceUpdate ??
|
|
183
|
+
rootConfig.defaults?.forceUpdate ??
|
|
184
|
+
false
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Find a collection config by path.
|
|
190
|
+
*
|
|
191
|
+
* @param config - Root Melaka configuration
|
|
192
|
+
* @param collectionPath - Collection path to find
|
|
193
|
+
* @returns Collection config or undefined
|
|
194
|
+
*/
|
|
195
|
+
export function findCollectionConfig(
|
|
196
|
+
config: MelakaConfig,
|
|
197
|
+
collectionPath: string
|
|
198
|
+
): CollectionConfig | undefined {
|
|
199
|
+
return config.collections.find((c) => c.path === collectionPath);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Config Validation
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Validate a configuration without loading from file.
|
|
208
|
+
*
|
|
209
|
+
* Useful for programmatic config generation or testing.
|
|
210
|
+
*
|
|
211
|
+
* @param config - Configuration object to validate
|
|
212
|
+
* @returns Validated configuration
|
|
213
|
+
* @throws Error if configuration is invalid
|
|
214
|
+
*/
|
|
215
|
+
export function validateConfig(config: unknown): MelakaConfig {
|
|
216
|
+
const result = MelakaConfigSchema.safeParse(config);
|
|
217
|
+
if (!result.success) {
|
|
218
|
+
const errors = result.error.errors
|
|
219
|
+
.map((e) => ` - ${e.path.join('.')}: ${e.message}`)
|
|
220
|
+
.join('\n');
|
|
221
|
+
throw new Error(`Invalid configuration:\n${errors}`);
|
|
222
|
+
}
|
|
223
|
+
return result.data as MelakaConfig;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Check if a config file exists at the given path.
|
|
228
|
+
*
|
|
229
|
+
* @param configPath - Path to check (defaults to 'melaka.config.ts' in cwd)
|
|
230
|
+
* @returns Whether the config file exists
|
|
231
|
+
*/
|
|
232
|
+
export async function configExists(configPath?: string): Promise<boolean> {
|
|
233
|
+
const resolvedPath = await resolveConfigPath(configPath);
|
|
234
|
+
const fs = await import('fs/promises');
|
|
235
|
+
try {
|
|
236
|
+
await fs.access(resolvedPath);
|
|
237
|
+
return true;
|
|
238
|
+
} catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @melaka/core
|
|
3
|
+
*
|
|
4
|
+
* Core types, schemas, and utilities for Melaka - AI-powered Firestore localization.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Types
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
export type {
|
|
14
|
+
// Configuration
|
|
15
|
+
MelakaConfig,
|
|
16
|
+
AIConfig,
|
|
17
|
+
DefaultsConfig,
|
|
18
|
+
CollectionConfig,
|
|
19
|
+
FieldMapping,
|
|
20
|
+
SchemaType,
|
|
21
|
+
// Translation
|
|
22
|
+
MelakaMetadata,
|
|
23
|
+
TranslationStatus,
|
|
24
|
+
TranslationTaskPayload,
|
|
25
|
+
TranslationResult,
|
|
26
|
+
// Migration
|
|
27
|
+
MigrationResult,
|
|
28
|
+
ProgressResult,
|
|
29
|
+
// Helpers
|
|
30
|
+
SeparatedContent,
|
|
31
|
+
TranslationRequest,
|
|
32
|
+
} from './types';
|
|
33
|
+
|
|
34
|
+
// Re-export defineConfig from types
|
|
35
|
+
export { defineConfig } from './types';
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Schemas (Zod)
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
// Config schemas
|
|
43
|
+
MelakaConfigSchema,
|
|
44
|
+
AIConfigSchema,
|
|
45
|
+
AIProviderSchema,
|
|
46
|
+
CollectionConfigSchema,
|
|
47
|
+
DefaultsConfigSchema,
|
|
48
|
+
FieldMappingSchema,
|
|
49
|
+
SchemaTypeSchema,
|
|
50
|
+
// Runtime schemas
|
|
51
|
+
TranslationTaskPayloadSchema,
|
|
52
|
+
MelakaMetadataSchema,
|
|
53
|
+
TranslationStatusSchema,
|
|
54
|
+
// Type inference
|
|
55
|
+
type AIConfigInput,
|
|
56
|
+
type AIConfigOutput,
|
|
57
|
+
type CollectionConfigInput,
|
|
58
|
+
type CollectionConfigOutput,
|
|
59
|
+
type MelakaConfigInput,
|
|
60
|
+
type MelakaConfigOutput,
|
|
61
|
+
} from './schemas';
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Config Loading
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
loadConfig,
|
|
69
|
+
validateConfig,
|
|
70
|
+
configExists,
|
|
71
|
+
getEffectiveAIConfig,
|
|
72
|
+
getEffectiveBatchSize,
|
|
73
|
+
getEffectiveMaxConcurrency,
|
|
74
|
+
getEffectiveForceUpdate,
|
|
75
|
+
findCollectionConfig,
|
|
76
|
+
} from './config';
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// Utilities
|
|
80
|
+
// ============================================================================
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
// Content hashing
|
|
84
|
+
hashContent,
|
|
85
|
+
// Field detection
|
|
86
|
+
detectFieldType,
|
|
87
|
+
isTranslatableType,
|
|
88
|
+
// Content separation
|
|
89
|
+
separateContent,
|
|
90
|
+
// Glossary
|
|
91
|
+
mergeGlossaries,
|
|
92
|
+
formatGlossary,
|
|
93
|
+
// Language
|
|
94
|
+
getLanguageName,
|
|
95
|
+
// ID generation
|
|
96
|
+
generateBatchId,
|
|
97
|
+
} from './utils';
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Schema Generation
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
createFieldSchema,
|
|
105
|
+
createTranslationSchema,
|
|
106
|
+
createSchemaFromMappings,
|
|
107
|
+
createTranslatableSchemaFromMappings,
|
|
108
|
+
validateWithSchema,
|
|
109
|
+
safeValidateWithSchema,
|
|
110
|
+
schemaToJsonSchema,
|
|
111
|
+
} from './schema-generator';
|