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
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# Contributing to Melaka
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Melaka! This document provides guidelines for contributing.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js 18+
|
|
10
|
+
- pnpm 8+
|
|
11
|
+
- Firebase CLI
|
|
12
|
+
- A Firebase project for testing
|
|
13
|
+
|
|
14
|
+
### Setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Clone the repository
|
|
18
|
+
git clone https://github.com/rizahassan/melaka.git
|
|
19
|
+
cd melaka
|
|
20
|
+
|
|
21
|
+
# Install dependencies
|
|
22
|
+
pnpm install
|
|
23
|
+
|
|
24
|
+
# Build all packages
|
|
25
|
+
pnpm build
|
|
26
|
+
|
|
27
|
+
# Run tests
|
|
28
|
+
pnpm test
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Project Structure
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
melaka/
|
|
35
|
+
├── packages/
|
|
36
|
+
│ ├── core/ # Config, types, utilities
|
|
37
|
+
│ ├── firestore/ # Firestore adapter
|
|
38
|
+
│ ├── ai/ # AI provider adapters
|
|
39
|
+
│ └── cli/ # Command-line interface
|
|
40
|
+
├── examples/ # Example projects
|
|
41
|
+
├── docs/ # Documentation
|
|
42
|
+
└── scripts/ # Build scripts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Development Workflow
|
|
48
|
+
|
|
49
|
+
### 1. Create a Branch
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git checkout -b feature/your-feature-name
|
|
53
|
+
# or
|
|
54
|
+
git checkout -b fix/your-bug-fix
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2. Make Changes
|
|
58
|
+
|
|
59
|
+
- Write code following the style guide
|
|
60
|
+
- Add tests for new functionality
|
|
61
|
+
- Update documentation as needed
|
|
62
|
+
|
|
63
|
+
### 3. Test
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Run all tests
|
|
67
|
+
pnpm test
|
|
68
|
+
|
|
69
|
+
# Run tests for a specific package
|
|
70
|
+
pnpm --filter @melaka/core test
|
|
71
|
+
|
|
72
|
+
# Run tests in watch mode
|
|
73
|
+
pnpm test:watch
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Lint and Format
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Lint code
|
|
80
|
+
pnpm lint
|
|
81
|
+
|
|
82
|
+
# Format code
|
|
83
|
+
pnpm format
|
|
84
|
+
|
|
85
|
+
# Type check
|
|
86
|
+
pnpm typecheck
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 5. Commit
|
|
90
|
+
|
|
91
|
+
We use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Features
|
|
95
|
+
git commit -m "feat(core): add glossary merging"
|
|
96
|
+
|
|
97
|
+
# Bug fixes
|
|
98
|
+
git commit -m "fix(firestore): handle empty collections"
|
|
99
|
+
|
|
100
|
+
# Documentation
|
|
101
|
+
git commit -m "docs: update configuration examples"
|
|
102
|
+
|
|
103
|
+
# Breaking changes
|
|
104
|
+
git commit -m "feat(cli)!: change deploy command options"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 6. Submit PR
|
|
108
|
+
|
|
109
|
+
- Push your branch
|
|
110
|
+
- Create a Pull Request
|
|
111
|
+
- Fill out the PR template
|
|
112
|
+
- Wait for review
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Code Style
|
|
117
|
+
|
|
118
|
+
### TypeScript
|
|
119
|
+
|
|
120
|
+
- Use TypeScript for all code
|
|
121
|
+
- Enable strict mode
|
|
122
|
+
- Document public APIs with JSDoc
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
/**
|
|
126
|
+
* Translate a document to the specified language.
|
|
127
|
+
*
|
|
128
|
+
* @param doc - The source document
|
|
129
|
+
* @param language - Target language code (BCP 47)
|
|
130
|
+
* @returns The translated document
|
|
131
|
+
* @throws {TranslationError} If translation fails
|
|
132
|
+
*/
|
|
133
|
+
export async function translateDocument(
|
|
134
|
+
doc: DocumentData,
|
|
135
|
+
language: string
|
|
136
|
+
): Promise<TranslatedDocument> {
|
|
137
|
+
// ...
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Naming
|
|
142
|
+
|
|
143
|
+
- **Files:** `kebab-case.ts`
|
|
144
|
+
- **Classes:** `PascalCase`
|
|
145
|
+
- **Functions/variables:** `camelCase`
|
|
146
|
+
- **Constants:** `SCREAMING_SNAKE_CASE`
|
|
147
|
+
- **Types/Interfaces:** `PascalCase`
|
|
148
|
+
|
|
149
|
+
### Imports
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// External packages first
|
|
153
|
+
import { z } from 'zod';
|
|
154
|
+
import { Firestore } from 'firebase-admin/firestore';
|
|
155
|
+
|
|
156
|
+
// Internal packages
|
|
157
|
+
import { MelakaConfig } from '@melaka/core';
|
|
158
|
+
|
|
159
|
+
// Relative imports last
|
|
160
|
+
import { translateDocument } from './translate';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Testing
|
|
166
|
+
|
|
167
|
+
### Unit Tests
|
|
168
|
+
|
|
169
|
+
Use Vitest for unit tests:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { describe, it, expect } from 'vitest';
|
|
173
|
+
import { createContentHash } from './hash';
|
|
174
|
+
|
|
175
|
+
describe('createContentHash', () => {
|
|
176
|
+
it('should create consistent hashes', () => {
|
|
177
|
+
const content = { title: 'Hello', body: 'World' };
|
|
178
|
+
const hash1 = createContentHash(content);
|
|
179
|
+
const hash2 = createContentHash(content);
|
|
180
|
+
|
|
181
|
+
expect(hash1).toBe(hash2);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should detect content changes', () => {
|
|
185
|
+
const hash1 = createContentHash({ title: 'Hello' });
|
|
186
|
+
const hash2 = createContentHash({ title: 'World' });
|
|
187
|
+
|
|
188
|
+
expect(hash1).not.toBe(hash2);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Integration Tests
|
|
194
|
+
|
|
195
|
+
For Firebase integration tests, use the emulator:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { describe, it, beforeAll, afterAll } from 'vitest';
|
|
199
|
+
import { initializeTestEnvironment } from '@firebase/rules-unit-testing';
|
|
200
|
+
|
|
201
|
+
describe('Firestore Integration', () => {
|
|
202
|
+
let testEnv;
|
|
203
|
+
|
|
204
|
+
beforeAll(async () => {
|
|
205
|
+
testEnv = await initializeTestEnvironment({
|
|
206
|
+
projectId: 'test-project',
|
|
207
|
+
firestore: { host: 'localhost', port: 8080 },
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
afterAll(async () => {
|
|
212
|
+
await testEnv.cleanup();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Tests...
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Documentation
|
|
222
|
+
|
|
223
|
+
### README Files
|
|
224
|
+
|
|
225
|
+
Each package should have a README with:
|
|
226
|
+
|
|
227
|
+
- Description
|
|
228
|
+
- Installation
|
|
229
|
+
- Basic usage
|
|
230
|
+
- API reference
|
|
231
|
+
|
|
232
|
+
### JSDoc
|
|
233
|
+
|
|
234
|
+
Document all public APIs:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
/**
|
|
238
|
+
* Configuration for a collection to translate.
|
|
239
|
+
*/
|
|
240
|
+
export interface CollectionConfig {
|
|
241
|
+
/**
|
|
242
|
+
* Firestore collection path.
|
|
243
|
+
* @example 'articles'
|
|
244
|
+
* @example 'users/{uid}/posts'
|
|
245
|
+
*/
|
|
246
|
+
path: string;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Fields to translate. If omitted, auto-detects string fields.
|
|
250
|
+
*/
|
|
251
|
+
fields?: string[];
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Docs Folder
|
|
256
|
+
|
|
257
|
+
Update `docs/` for user-facing documentation.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Pull Request Guidelines
|
|
262
|
+
|
|
263
|
+
### PR Title
|
|
264
|
+
|
|
265
|
+
Use conventional commit format:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
feat(core): add support for nested fields
|
|
269
|
+
fix(cli): handle missing config file gracefully
|
|
270
|
+
docs: add troubleshooting guide
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### PR Description
|
|
274
|
+
|
|
275
|
+
Include:
|
|
276
|
+
|
|
277
|
+
- **What:** Brief description of changes
|
|
278
|
+
- **Why:** Motivation and context
|
|
279
|
+
- **How:** Implementation approach
|
|
280
|
+
- **Testing:** How you tested the changes
|
|
281
|
+
|
|
282
|
+
### Checklist
|
|
283
|
+
|
|
284
|
+
- [ ] Tests pass (`pnpm test`)
|
|
285
|
+
- [ ] Linting passes (`pnpm lint`)
|
|
286
|
+
- [ ] Types check (`pnpm typecheck`)
|
|
287
|
+
- [ ] Documentation updated
|
|
288
|
+
- [ ] Changeset added (if needed)
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Changesets
|
|
293
|
+
|
|
294
|
+
We use [Changesets](https://github.com/changesets/changesets) for versioning:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
# Add a changeset for your changes
|
|
298
|
+
pnpm changeset
|
|
299
|
+
|
|
300
|
+
# Follow the prompts to describe your changes
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Issue Guidelines
|
|
306
|
+
|
|
307
|
+
### Bug Reports
|
|
308
|
+
|
|
309
|
+
Include:
|
|
310
|
+
|
|
311
|
+
- Melaka version
|
|
312
|
+
- Node.js version
|
|
313
|
+
- Firebase SDK version
|
|
314
|
+
- Steps to reproduce
|
|
315
|
+
- Expected vs actual behavior
|
|
316
|
+
- Error messages/logs
|
|
317
|
+
|
|
318
|
+
### Feature Requests
|
|
319
|
+
|
|
320
|
+
Include:
|
|
321
|
+
|
|
322
|
+
- Use case description
|
|
323
|
+
- Proposed solution
|
|
324
|
+
- Alternative approaches considered
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Code of Conduct
|
|
329
|
+
|
|
330
|
+
- Be respectful and inclusive
|
|
331
|
+
- Welcome newcomers
|
|
332
|
+
- Focus on constructive feedback
|
|
333
|
+
- Assume good intentions
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Getting Help
|
|
338
|
+
|
|
339
|
+
- **Questions:** Open a [Discussion](https://github.com/rizahassan/melaka/discussions)
|
|
340
|
+
- **Bugs:** Open an [Issue](https://github.com/rizahassan/melaka/issues)
|
|
341
|
+
- **Chat:** Join our Discord (coming soon)
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## License
|
|
346
|
+
|
|
347
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Riza Hassan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 🌏 Melaka
|
|
2
|
+
|
|
3
|
+
**AI-powered localization for Firebase Firestore**
|
|
4
|
+
|
|
5
|
+
Melaka is an open-source SDK and CLI for automatically translating Firestore documents using AI. Named after the historic Malaysian state known as a lingua franca hub where many languages were spoken, Melaka brings seamless multilingual support to your Firebase applications.
|
|
6
|
+
|
|
7
|
+
## Why Melaka?
|
|
8
|
+
|
|
9
|
+
Firebase has no great i18n solution today. Melaka fills that gap with:
|
|
10
|
+
|
|
11
|
+
- 🤖 **AI-Powered Translation** — Uses Gemini, OpenAI, or Claude for context-aware translations
|
|
12
|
+
- 📝 **Declarative Config** — Define what to translate in a simple config file
|
|
13
|
+
- 🔄 **Auto-Sync** — Firestore triggers keep translations up-to-date automatically
|
|
14
|
+
- 📦 **i18n Subcollections** — Battle-tested pattern: `/{doc}/i18n/{locale}`
|
|
15
|
+
- 🔍 **Change Detection** — Content hashing prevents unnecessary re-translations
|
|
16
|
+
- 📖 **Glossary Support** — Consistent terminology across your app
|
|
17
|
+
- ✅ **Human Review Workflow** — Mark translations as reviewed
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install Melaka CLI
|
|
23
|
+
npm install -g melaka
|
|
24
|
+
|
|
25
|
+
# Initialize in your Firebase project
|
|
26
|
+
cd your-firebase-project
|
|
27
|
+
melaka init
|
|
28
|
+
|
|
29
|
+
# Configure your collections
|
|
30
|
+
# Edit melaka.config.ts
|
|
31
|
+
|
|
32
|
+
# Deploy translation triggers
|
|
33
|
+
melaka deploy
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
- [Integration Guide](./docs/INTEGRATION.md) — Step-by-step setup
|
|
39
|
+
- [Configuration](./docs/CONFIGURATION.md) — Config file reference
|
|
40
|
+
- [CLI Reference](./docs/CLI.md) — Command documentation
|
|
41
|
+
- [AI Providers](./docs/AI_PROVIDERS.md) — Supported AI models
|
|
42
|
+
- [Architecture](./docs/ARCHITECTURE.md) — System design and components
|
|
43
|
+
- [Contributing](./CONTRIBUTING.md) — Development guide
|
|
44
|
+
|
|
45
|
+
## Status
|
|
46
|
+
|
|
47
|
+
🚧 **Early Development** — Not ready for production use yet.
|
|
48
|
+
|
|
49
|
+
See [ROADMAP.md](./docs/ROADMAP.md) for planned features.
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT License — see [LICENSE](./LICENSE)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
*Built with 💙 in Malaysia*
|