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.
Files changed (49) hide show
  1. package/CONTRIBUTING.md +347 -0
  2. package/LICENSE +21 -0
  3. package/README.md +57 -0
  4. package/docs/AI_PROVIDERS.md +343 -0
  5. package/docs/ARCHITECTURE.md +512 -0
  6. package/docs/CLI.md +438 -0
  7. package/docs/CONFIGURATION.md +453 -0
  8. package/docs/INTEGRATION.md +477 -0
  9. package/docs/ROADMAP.md +248 -0
  10. package/package.json +46 -0
  11. package/packages/ai/README.md +43 -0
  12. package/packages/ai/package.json +42 -0
  13. package/packages/ai/src/facade.ts +120 -0
  14. package/packages/ai/src/index.ts +34 -0
  15. package/packages/ai/src/prompt.ts +117 -0
  16. package/packages/ai/src/providers/gemini.ts +185 -0
  17. package/packages/ai/src/providers/index.ts +9 -0
  18. package/packages/ai/src/types.ts +134 -0
  19. package/packages/ai/tsconfig.json +19 -0
  20. package/packages/cli/README.md +70 -0
  21. package/packages/cli/package.json +44 -0
  22. package/packages/cli/src/cli.ts +30 -0
  23. package/packages/cli/src/commands/deploy.ts +115 -0
  24. package/packages/cli/src/commands/index.ts +9 -0
  25. package/packages/cli/src/commands/init.ts +107 -0
  26. package/packages/cli/src/commands/status.ts +73 -0
  27. package/packages/cli/src/commands/translate.ts +92 -0
  28. package/packages/cli/src/commands/validate.ts +69 -0
  29. package/packages/cli/tsconfig.json +19 -0
  30. package/packages/core/README.md +46 -0
  31. package/packages/core/package.json +50 -0
  32. package/packages/core/src/config.ts +241 -0
  33. package/packages/core/src/index.ts +111 -0
  34. package/packages/core/src/schema-generator.ts +263 -0
  35. package/packages/core/src/schemas.ts +126 -0
  36. package/packages/core/src/types.ts +481 -0
  37. package/packages/core/src/utils.ts +343 -0
  38. package/packages/core/tsconfig.json +19 -0
  39. package/packages/firestore/README.md +60 -0
  40. package/packages/firestore/package.json +48 -0
  41. package/packages/firestore/src/generator.ts +270 -0
  42. package/packages/firestore/src/i18n.ts +262 -0
  43. package/packages/firestore/src/index.ts +54 -0
  44. package/packages/firestore/src/processor.ts +245 -0
  45. package/packages/firestore/src/queue.ts +202 -0
  46. package/packages/firestore/src/task-handler.ts +164 -0
  47. package/packages/firestore/tsconfig.json +19 -0
  48. package/pnpm-workspace.yaml +2 -0
  49. package/turbo.json +31 -0
@@ -0,0 +1,481 @@
1
+ /**
2
+ * Melaka Core Types
3
+ *
4
+ * This file contains all the core TypeScript interfaces and types
5
+ * used throughout the Melaka SDK.
6
+ */
7
+
8
+ import { Timestamp } from 'firebase-admin/firestore';
9
+
10
+ // ============================================================================
11
+ // Configuration Types
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Root configuration for Melaka.
16
+ * Define in `melaka.config.ts` at your project root.
17
+ */
18
+ export interface MelakaConfig {
19
+ /**
20
+ * Target languages for translation (BCP 47 format).
21
+ * @example ['ms-MY', 'zh-CN', 'ta-IN']
22
+ */
23
+ languages: string[];
24
+
25
+ /**
26
+ * AI provider configuration.
27
+ */
28
+ ai: AIConfig;
29
+
30
+ /**
31
+ * Firebase region for deployed functions.
32
+ * @default 'us-central1'
33
+ */
34
+ region?: string;
35
+
36
+ /**
37
+ * Default settings applied to all collections.
38
+ */
39
+ defaults?: DefaultsConfig;
40
+
41
+ /**
42
+ * Shared glossary applied to all collections.
43
+ * Maps source terms to translations.
44
+ */
45
+ glossary?: Record<string, string>;
46
+
47
+ /**
48
+ * Collections to translate.
49
+ */
50
+ collections: CollectionConfig[];
51
+ }
52
+
53
+ /**
54
+ * AI provider configuration.
55
+ */
56
+ export interface AIConfig {
57
+ /**
58
+ * AI provider to use.
59
+ */
60
+ provider: 'gemini' | 'openai' | 'claude';
61
+
62
+ /**
63
+ * Model name/identifier.
64
+ * @example 'gemini-2.5-flash'
65
+ * @example 'gpt-4o-mini'
66
+ * @example 'claude-sonnet-4-20250514'
67
+ */
68
+ model: string;
69
+
70
+ /**
71
+ * Temperature for generation (0-1).
72
+ * Lower = more consistent, higher = more creative.
73
+ * @default 0.3
74
+ */
75
+ temperature?: number;
76
+
77
+ /**
78
+ * Firebase secret name for API key.
79
+ * @example 'GEMINI_API_KEY'
80
+ */
81
+ apiKeySecret?: string;
82
+
83
+ /**
84
+ * API key directly (for local development only).
85
+ * Prefer `apiKeySecret` for production.
86
+ */
87
+ apiKey?: string;
88
+ }
89
+
90
+ /**
91
+ * Default settings for all collections.
92
+ */
93
+ export interface DefaultsConfig {
94
+ /**
95
+ * Number of documents to process per batch.
96
+ * @default 20
97
+ */
98
+ batchSize?: number;
99
+
100
+ /**
101
+ * Maximum concurrent translation tasks.
102
+ * @default 10
103
+ */
104
+ maxConcurrency?: number;
105
+
106
+ /**
107
+ * Force re-translation even if content unchanged.
108
+ * @default false
109
+ */
110
+ forceUpdate?: boolean;
111
+ }
112
+
113
+ /**
114
+ * Configuration for a collection to translate.
115
+ */
116
+ export interface CollectionConfig {
117
+ /**
118
+ * Firestore collection path.
119
+ * @example 'articles'
120
+ * @example 'quiz'
121
+ */
122
+ path: string;
123
+
124
+ /**
125
+ * Use collection group query (for subcollections).
126
+ * @default false
127
+ */
128
+ isCollectionGroup?: boolean;
129
+
130
+ /**
131
+ * Fields to translate.
132
+ * If omitted, auto-detects translatable string fields.
133
+ */
134
+ fields?: string[];
135
+
136
+ /**
137
+ * Detailed field mapping configuration.
138
+ * Use for fine-grained control over translation behavior.
139
+ */
140
+ fieldMappings?: FieldMapping[];
141
+
142
+ /**
143
+ * Custom prompt/context for AI translation.
144
+ * Helps the AI understand the content type.
145
+ */
146
+ prompt?: string;
147
+
148
+ /**
149
+ * Collection-specific glossary (merged with shared glossary).
150
+ */
151
+ glossary?: Record<string, string>;
152
+
153
+ /**
154
+ * Override AI config for this collection.
155
+ */
156
+ ai?: Partial<AIConfig>;
157
+
158
+ /**
159
+ * Override batch size for this collection.
160
+ */
161
+ batchSize?: number;
162
+
163
+ /**
164
+ * Override max concurrency for this collection.
165
+ */
166
+ maxConcurrency?: number;
167
+
168
+ /**
169
+ * Override force update for this collection.
170
+ */
171
+ forceUpdate?: boolean;
172
+ }
173
+
174
+ /**
175
+ * Detailed field mapping configuration.
176
+ */
177
+ export interface FieldMapping {
178
+ /**
179
+ * Field name in source document.
180
+ */
181
+ sourceField: string;
182
+
183
+ /**
184
+ * Field name in translation (defaults to sourceField).
185
+ */
186
+ targetField?: string;
187
+
188
+ /**
189
+ * Schema type for the field.
190
+ * Used for schema generation and to determine translatability.
191
+ */
192
+ schemaType?: SchemaType;
193
+
194
+ /**
195
+ * Whether the field is required.
196
+ * Translation fails if required field is missing.
197
+ */
198
+ required?: boolean;
199
+
200
+ /**
201
+ * Description to help AI understand field context.
202
+ */
203
+ description?: string;
204
+ }
205
+
206
+ /**
207
+ * Supported schema types for field mappings.
208
+ */
209
+ export type SchemaType =
210
+ | 'string'
211
+ | 'string[]'
212
+ | 'number'
213
+ | 'number[]'
214
+ | 'boolean'
215
+ | 'object'
216
+ | 'object[]'
217
+ | 'object|null'
218
+ | 'DocumentReference'
219
+ | 'DocumentReference[]';
220
+
221
+ // ============================================================================
222
+ // Translation Types
223
+ // ============================================================================
224
+
225
+ /**
226
+ * Metadata stored with each translation in the i18n subcollection.
227
+ */
228
+ export interface MelakaMetadata {
229
+ /**
230
+ * SHA256 hash of source content for change detection.
231
+ */
232
+ source_hash: string;
233
+
234
+ /**
235
+ * Timestamp when translation was created/updated.
236
+ */
237
+ translated_at: Timestamp;
238
+
239
+ /**
240
+ * AI model used for translation.
241
+ */
242
+ model: string;
243
+
244
+ /**
245
+ * Translation status.
246
+ */
247
+ status: TranslationStatus;
248
+
249
+ /**
250
+ * Whether translation has been human-reviewed.
251
+ */
252
+ reviewed: boolean;
253
+
254
+ /**
255
+ * Error message if status is 'failed'.
256
+ */
257
+ error?: string;
258
+ }
259
+
260
+ /**
261
+ * Translation status values.
262
+ */
263
+ export type TranslationStatus = 'completed' | 'failed' | 'pending';
264
+
265
+ /**
266
+ * Payload for translation Cloud Task.
267
+ */
268
+ export interface TranslationTaskPayload {
269
+ /**
270
+ * Full path to the document's collection.
271
+ */
272
+ collectionPath: string;
273
+
274
+ /**
275
+ * Document ID.
276
+ */
277
+ documentId: string;
278
+
279
+ /**
280
+ * Target language code.
281
+ */
282
+ targetLanguage: string;
283
+
284
+ /**
285
+ * Collection configuration.
286
+ */
287
+ config: CollectionConfig;
288
+
289
+ /**
290
+ * Batch ID for tracking.
291
+ */
292
+ batchId: string;
293
+ }
294
+
295
+ /**
296
+ * Result of a translation operation.
297
+ */
298
+ export interface TranslationResult {
299
+ /**
300
+ * Whether translation succeeded.
301
+ */
302
+ success: boolean;
303
+
304
+ /**
305
+ * Document ID.
306
+ */
307
+ documentId: string;
308
+
309
+ /**
310
+ * Target language.
311
+ */
312
+ language: string;
313
+
314
+ /**
315
+ * Error message if failed.
316
+ */
317
+ error?: string;
318
+
319
+ /**
320
+ * Duration in milliseconds.
321
+ */
322
+ durationMs?: number;
323
+ }
324
+
325
+ // ============================================================================
326
+ // Migration Types
327
+ // ============================================================================
328
+
329
+ /**
330
+ * Result of a migration/batch translation operation.
331
+ */
332
+ export interface MigrationResult {
333
+ /**
334
+ * Whether migration completed successfully.
335
+ */
336
+ success: boolean;
337
+
338
+ /**
339
+ * Human-readable message.
340
+ */
341
+ message: string;
342
+
343
+ /**
344
+ * Batch ID for tracking.
345
+ */
346
+ batchId: string;
347
+
348
+ /**
349
+ * Total documents in collection.
350
+ */
351
+ totalDocuments: number;
352
+
353
+ /**
354
+ * Number of tasks successfully enqueued.
355
+ */
356
+ tasksEnqueued: number;
357
+
358
+ /**
359
+ * Number of tasks that failed to enqueue.
360
+ */
361
+ failed: number;
362
+ }
363
+
364
+ /**
365
+ * Progress of a translation migration.
366
+ */
367
+ export interface ProgressResult {
368
+ /**
369
+ * Total documents in collection.
370
+ */
371
+ totalDocuments: number;
372
+
373
+ /**
374
+ * Successfully translated documents.
375
+ */
376
+ completedCount: number;
377
+
378
+ /**
379
+ * Failed translations.
380
+ */
381
+ failedCount: number;
382
+
383
+ /**
384
+ * Pending translations.
385
+ */
386
+ pendingCount: number;
387
+
388
+ /**
389
+ * Progress percentage (0-100).
390
+ */
391
+ progress: number;
392
+
393
+ /**
394
+ * Overall status.
395
+ */
396
+ status: 'completed' | 'in-progress';
397
+ }
398
+
399
+ // ============================================================================
400
+ // Helper Types
401
+ // ============================================================================
402
+
403
+ /**
404
+ * Content separated by translatability.
405
+ */
406
+ export interface SeparatedContent {
407
+ /**
408
+ * Content to be translated (strings and string arrays).
409
+ */
410
+ translatable: Record<string, unknown>;
411
+
412
+ /**
413
+ * Content to be copied as-is (numbers, refs, etc.).
414
+ */
415
+ nonTranslatable: Record<string, unknown>;
416
+
417
+ /**
418
+ * Detected schema types for each field.
419
+ */
420
+ detectedTypes: Record<string, SchemaType>;
421
+ }
422
+
423
+ /**
424
+ * Request to the translation facade.
425
+ */
426
+ export interface TranslationRequest<TInput, TOutput> {
427
+ /**
428
+ * Zod schema for input validation.
429
+ */
430
+ inputSchema: unknown; // z.ZodSchema<TInput>
431
+
432
+ /**
433
+ * Zod schema for output validation.
434
+ */
435
+ outputSchema: unknown; // z.ZodSchema<TOutput>
436
+
437
+ /**
438
+ * Data to translate.
439
+ */
440
+ inputData: TInput;
441
+
442
+ /**
443
+ * Target language.
444
+ */
445
+ language: string;
446
+
447
+ /**
448
+ * Custom translation prompt.
449
+ */
450
+ prompt?: string;
451
+
452
+ /**
453
+ * Glossary of term translations.
454
+ */
455
+ glossary?: Record<string, string>;
456
+ }
457
+
458
+ // ============================================================================
459
+ // Config Helper
460
+ // ============================================================================
461
+
462
+ /**
463
+ * Define a Melaka configuration with type checking.
464
+ *
465
+ * @example
466
+ * ```typescript
467
+ * // melaka.config.ts
468
+ * import { defineConfig } from 'melaka';
469
+ *
470
+ * export default defineConfig({
471
+ * languages: ['ms-MY'],
472
+ * ai: { provider: 'gemini', model: 'gemini-2.5-flash' },
473
+ * collections: [
474
+ * { path: 'articles', fields: ['title', 'content'] },
475
+ * ],
476
+ * });
477
+ * ```
478
+ */
479
+ export function defineConfig(config: MelakaConfig): MelakaConfig {
480
+ return config;
481
+ }