langctl 0.1.1 → 0.2.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/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "langctl",
3
- "version": "0.1.1",
4
- "description": "CLI-first translation management for developers. Affordable, AI-powered, and built for modern workflows.",
3
+ "version": "0.2.0",
4
+ "description": "Translation management CLI for developers. Manage i18n translations, export to 6 formats (iOS, Android, Flutter, i18next), import translations, and collaborate with teams. Affordable alternative to Lokalise and Crowdin.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "langctl": "./dist/index.js"
8
+ "langctl": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
- "build": "tsc",
11
+ "build": "rm -rf dist && tsc",
12
12
  "dev": "tsx src/index.ts",
13
13
  "start": "node dist/index.js",
14
14
  "prepublishOnly": "npm run build",
@@ -24,13 +24,60 @@
24
24
  "translations",
25
25
  "translate",
26
26
  "language",
27
- "multilingual"
27
+ "multilingual",
28
+ "translation-management",
29
+ "localization-management",
30
+ "translation-tool",
31
+ "i18next",
32
+ "developer-tools",
33
+ "devtools",
34
+ "dev-tool",
35
+ "ios",
36
+ "android",
37
+ "flutter",
38
+ "react",
39
+ "angular",
40
+ "vue",
41
+ "react-native",
42
+ "json",
43
+ "xml",
44
+ "arb",
45
+ "strings",
46
+ "automation",
47
+ "ci-cd",
48
+ "cicd",
49
+ "continuous-integration",
50
+ "workflow",
51
+ "export",
52
+ "import",
53
+ "translation-export",
54
+ "translation-import",
55
+ "team",
56
+ "collaboration",
57
+ "multilanguage",
58
+ "multi-language",
59
+ "lokalise-alternative",
60
+ "crowdin-alternative",
61
+ "phrase-alternative",
62
+ "affordable",
63
+ "free",
64
+ "gettext",
65
+ "po",
66
+ "locale",
67
+ "translation-keys",
68
+ "localization-tool",
69
+ "string-management",
70
+ "mobile-localization",
71
+ "web-localization",
72
+ "app-localization",
73
+ "saas",
74
+ "api"
28
75
  ],
29
76
  "author": "Siddharth Saxena <hello@langctl.com>",
30
77
  "license": "MIT",
31
78
  "repository": {
32
79
  "type": "git",
33
- "url": "https://github.com/siddharthsaxena0/langctl.git"
80
+ "url": "git+https://github.com/siddharthsaxena0/langctl.git"
34
81
  },
35
82
  "bugs": {
36
83
  "url": "https://github.com/siddharthsaxena0/langctl/issues"
@@ -40,7 +87,6 @@
40
87
  "node": ">=16.0.0"
41
88
  },
42
89
  "dependencies": {
43
- "@supabase/supabase-js": "^2.89.0",
44
90
  "chalk": "^5.6.2",
45
91
  "commander": "^14.0.2",
46
92
  "conf": "^15.0.2",
@@ -1,293 +0,0 @@
1
- # 🚀 Publishing Langctl CLI to npm
2
-
3
- **Date:** January 5, 2026
4
- **Package:** langctl
5
- **Version:** 0.1.0
6
-
7
- ---
8
-
9
- ## ✅ Pre-Publish Checklist
10
-
11
- Before publishing, verify these items:
12
-
13
- - [x] Package name available: `langctl` ✅
14
- - [x] README.md complete with examples ✅
15
- - [x] package.json properly configured ✅
16
- - [x] .npmignore configured ✅
17
- - [x] TypeScript source code ready ✅
18
- - [x] License file present (MIT) ✅
19
-
20
- ---
21
-
22
- ## 📋 Step-by-Step Publishing Guide
23
-
24
- ### Step 1: Verify npm Login
25
-
26
- Check if you're logged into npm:
27
-
28
- ```bash
29
- npm whoami
30
- ```
31
-
32
- **If not logged in:**
33
-
34
- ```bash
35
- npm login
36
- ```
37
-
38
- Enter your credentials:
39
- - Username
40
- - Password
41
- - Email
42
- - One-time password (if 2FA enabled)
43
-
44
- ---
45
-
46
- ### Step 2: Final Build & Test
47
-
48
- ```bash
49
- cd /Users/siddharthsaxena/Documents/projects/langctl/langctl-cli
50
-
51
- # Clean previous build
52
- rm -rf dist/
53
-
54
- # Fresh build
55
- npm run build
56
-
57
- # Verify build succeeded
58
- ls -la dist/
59
- ```
60
-
61
- **Expected:** You should see `.js` and `.d.ts` files in dist/
62
-
63
- ---
64
-
65
- ### Step 3: Test Package Locally
66
-
67
- Before publishing, test the package works:
68
-
69
- ```bash
70
- # Link package globally for testing
71
- npm link
72
-
73
- # Test the CLI
74
- langctl --version
75
- langctl --help
76
-
77
- # If it works, unlink
78
- npm unlink -g langctl
79
- ```
80
-
81
- ---
82
-
83
- ### Step 4: Dry Run (Recommended)
84
-
85
- See what will be published WITHOUT actually publishing:
86
-
87
- ```bash
88
- npm pack --dry-run
89
- ```
90
-
91
- This shows:
92
- - ✅ Files that will be included
93
- - ✅ Package size
94
- - ✅ No errors
95
-
96
- ---
97
-
98
- ### Step 5: Create Package Tarball (Optional)
99
-
100
- Create actual tarball to inspect:
101
-
102
- ```bash
103
- npm pack
104
- ```
105
-
106
- This creates: `langctl-0.1.0.tgz`
107
-
108
- **To inspect:**
109
- ```bash
110
- tar -xzf langctl-0.1.0.tgz
111
- ls -la package/
112
- ```
113
-
114
- **Clean up after:**
115
- ```bash
116
- rm langctl-0.1.0.tgz
117
- rm -rf package/
118
- ```
119
-
120
- ---
121
-
122
- ### Step 6: Publish to npm! 🚀
123
-
124
- **First time publishing (public package):**
125
-
126
- ```bash
127
- npm publish --access public
128
- ```
129
-
130
- **Expected output:**
131
- ```
132
- npm notice
133
- npm notice 📦 langctl@0.1.0
134
- npm notice === Tarball Contents ===
135
- npm notice 1.1kB LICENSE
136
- npm notice 2.3kB README.md
137
- npm notice 845B package.json
138
- npm notice 15.2kB dist/...
139
- npm notice === Tarball Details ===
140
- npm notice name: langctl
141
- npm notice version: 0.1.0
142
- npm notice package size: XX.X kB
143
- npm notice unpacked size: XXX.X kB
144
- npm notice total files: XX
145
- npm notice
146
- + langctl@0.1.0
147
- ```
148
-
149
- ---
150
-
151
- ### Step 7: Verify Publication
152
-
153
- **Check on npm:**
154
- 1. Visit: https://www.npmjs.com/package/langctl
155
- 2. Verify README displays correctly
156
- 3. Check version number
157
-
158
- **Test installation:**
159
- ```bash
160
- # In a different directory
161
- npx langctl@latest --version
162
- ```
163
-
164
- ---
165
-
166
- ## 🎉 Success! Package Published
167
-
168
- Your CLI is now available globally at:
169
- - **npm:** https://www.npmjs.com/package/langctl
170
- - **Install:** `npm install -g langctl`
171
- - **Use:** `npx langctl`
172
-
173
- ---
174
-
175
- ## 📊 Post-Publish Tasks
176
-
177
- ### Update Landing Page
178
-
179
- Add npm install instructions to langctl.com:
180
-
181
- ```bash
182
- npm install -g langctl
183
- ```
184
-
185
- ### Update README (if needed)
186
-
187
- If you notice issues, you can publish patches:
188
-
189
- ```bash
190
- # Fix README or other files
191
- # Bump version
192
- npm version patch # 0.1.0 → 0.1.1
193
-
194
- # Rebuild and republish
195
- npm run build
196
- npm publish
197
- ```
198
-
199
- ### Monitor npm Stats
200
-
201
- Check download stats:
202
- - https://www.npmjs.com/package/langctl
203
- - https://npmtrends.com/langctl
204
-
205
- ---
206
-
207
- ## 🔧 Troubleshooting
208
-
209
- ### Error: "You do not have permission to publish"
210
-
211
- **Solution:**
212
- ```bash
213
- npm login
214
- npm whoami # Verify correct account
215
- ```
216
-
217
- ### Error: "Package name already exists"
218
-
219
- **Solution:** The name is taken. Since you reserved it, make sure you're logged in correctly.
220
-
221
- ### Error: "Must be logged in to publish"
222
-
223
- **Solution:**
224
- ```bash
225
- npm login
226
- ```
227
-
228
- ### Build errors
229
-
230
- **Solution:**
231
- ```bash
232
- rm -rf node_modules/ dist/
233
- npm install
234
- npm run build
235
- ```
236
-
237
- ---
238
-
239
- ## 📈 Version Updates (Future)
240
-
241
- **Patch (bug fixes):** 0.1.0 → 0.1.1
242
- ```bash
243
- npm version patch
244
- npm run build
245
- npm publish
246
- ```
247
-
248
- **Minor (new features):** 0.1.0 → 0.2.0
249
- ```bash
250
- npm version minor
251
- npm run build
252
- npm publish
253
- ```
254
-
255
- **Major (breaking changes):** 0.1.0 → 1.0.0
256
- ```bash
257
- npm version major
258
- npm run build
259
- npm publish
260
- ```
261
-
262
- ---
263
-
264
- ## ✅ Final Checklist
265
-
266
- Before running `npm publish`:
267
-
268
- - [ ] Logged into npm (`npm whoami`)
269
- - [ ] Build succeeded (`npm run build`)
270
- - [ ] Local test passed (`npm link` + test commands)
271
- - [ ] Dry run clean (`npm pack --dry-run`)
272
- - [ ] Ready to publish! (`npm publish --access public`)
273
-
274
- ---
275
-
276
- ## 🎯 Quick Command Summary
277
-
278
- ```bash
279
- # From langctl-cli directory:
280
- npm whoami # Verify login
281
- npm run build # Build TypeScript
282
- npm pack --dry-run # Preview package
283
- npm publish --access public # Publish!
284
- npx langctl@latest --version # Verify
285
- ```
286
-
287
- ---
288
-
289
- **Good luck! You're about to publish your first npm package! 🚀**
290
-
291
- **Questions? Issues?**
292
- - npm support: https://www.npmjs.com/support
293
- - Package page: https://www.npmjs.com/package/langctl
package/QUICK_PUBLISH.md DELETED
@@ -1,64 +0,0 @@
1
- # 🚀 PUBLISH LANGCTL - QUICK COMMANDS
2
-
3
- **Run these commands in order on YOUR MAC:**
4
-
5
- ```bash
6
- # 1. Navigate to CLI directory
7
- cd /Users/siddharthsaxena/Documents/projects/langctl/langctl-cli
8
-
9
- # 2. Check npm login
10
- npm whoami
11
-
12
- # 3. If not logged in:
13
- npm login
14
-
15
- # 4. Build the package
16
- npm run build
17
-
18
- # 5. Test locally (optional but recommended)
19
- npm link
20
- langctl --version
21
- langctl --help
22
- npm unlink -g langctl
23
-
24
- # 6. Dry run to preview
25
- npm pack --dry-run
26
-
27
- # 7. PUBLISH! 🚀
28
- npm publish --access public
29
-
30
- # 8. Verify it worked
31
- npx langctl@latest --version
32
- ```
33
-
34
- ---
35
-
36
- ## ✅ Expected Result
37
-
38
- After `npm publish`, you should see:
39
-
40
- ```
41
- + langctl@0.1.0
42
- ```
43
-
44
- Then check: https://www.npmjs.com/package/langctl
45
-
46
- ---
47
-
48
- ## 🎉 That's It!
49
-
50
- Your CLI is now installable worldwide:
51
-
52
- ```bash
53
- npm install -g langctl
54
- ```
55
-
56
- or
57
-
58
- ```bash
59
- npx langctl --help
60
- ```
61
-
62
- ---
63
-
64
- **Full guide:** See `NPM_PUBLISH_GUIDE.md` for detailed instructions and troubleshooting.
package/SECURITY_FIX.md DELETED
@@ -1,167 +0,0 @@
1
- # 🔒 Security Fix - Supabase Credentials
2
-
3
- **Date:** January 5, 2026
4
- **Issue:** Supabase credentials were being stored in user config files
5
- **Status:** ✅ FIXED
6
-
7
- ---
8
-
9
- ## 🚨 What Was Wrong
10
-
11
- Previously, the CLI was:
12
- - ❌ Storing Supabase URL in `~/.langctl/config.json`
13
- - ❌ Storing Supabase anon key in `~/.langctl/config.json`
14
- - ❌ Asking users about "Supabase configuration" during init
15
- - ❌ Exposing backend implementation details to users
16
-
17
- **Why this was bad:**
18
- - Users could see our backend credentials
19
- - Users could manipulate Supabase connection
20
- - Exposed unnecessary implementation details
21
- - Confused users with technical jargon
22
-
23
- ---
24
-
25
- ## ✅ What's Fixed
26
-
27
- Now the CLI:
28
- - ✅ Hardcodes Supabase credentials in source code
29
- - ✅ Only stores user credentials (API key, org ID, preferences)
30
- - ✅ Users never see or interact with Supabase
31
- - ✅ Clean, simple user experience
32
-
33
- ---
34
-
35
- ## 📄 Files Changed
36
-
37
- ### 1. `src/config.ts`
38
- **Removed from interface:**
39
- ```typescript
40
- // REMOVED - no longer stored
41
- supabaseUrl?: string;
42
- supabaseAnonKey?: string;
43
- ```
44
-
45
- **Now only stores:**
46
- ```typescript
47
- apiKey?: string; // User's API key
48
- organizationId?: string; // User's org ID
49
- organizationName?: string; // User's org name
50
- defaultProject?: string; // User preference
51
- defaultLanguage?: string; // User preference
52
- ```
53
-
54
- ### 2. `src/supabase.ts`
55
- **Before:**
56
- ```typescript
57
- // BAD - pulled from user config
58
- const supabaseUrl = config.get('supabaseUrl');
59
- const supabaseAnonKey = config.get('supabaseAnonKey');
60
- ```
61
-
62
- **After:**
63
- ```typescript
64
- // GOOD - hardcoded in source
65
- const SUPABASE_URL = 'https://bcgnmvkgkbhbxzzflwdb.supabase.co';
66
- const SUPABASE_ANON_KEY = 'eyJhbGci...';
67
- ```
68
-
69
- ### 3. `src/commands/init.ts`
70
- **Before:**
71
- ```typescript
72
- // BAD - saved to user config
73
- config.set('supabaseUrl', SUPABASE_URL);
74
- config.set('supabaseAnonKey', SUPABASE_ANON_KEY);
75
- ```
76
-
77
- **After:**
78
- ```typescript
79
- // GOOD - just initializes, doesn't save
80
- initializeSupabase();
81
- ```
82
-
83
- ### 4. `src/commands/config.ts`
84
- **Before:**
85
- ```typescript
86
- // BAD - displayed Supabase credentials
87
- supabaseAnonKey: allConfig.supabaseAnonKey ? maskSensitive(...) : undefined
88
- ```
89
-
90
- **After:**
91
- ```typescript
92
- // GOOD - only displays user data
93
- apiKey: allConfig.apiKey ? maskApiKey(allConfig.apiKey) : undefined,
94
- organizationId: allConfig.organizationId,
95
- organizationName: allConfig.organizationName
96
- ```
97
-
98
- ---
99
-
100
- ## 🔐 Security Notes
101
-
102
- **Is it safe to hardcode Supabase credentials in the CLI?**
103
-
104
- ✅ **YES!** This is perfectly safe because:
105
-
106
- 1. **Anon key is designed for client-side use**
107
- - It's meant to be public-facing
108
- - Row Level Security (RLS) protects all data
109
- - Users can only access what they're authorized for
110
-
111
- 2. **RLS policies enforce security**
112
- - Users can only see their own organization data
113
- - API key verification happens server-side (Edge Function)
114
- - All operations are protected by RLS
115
-
116
- 3. **This is standard practice**
117
- - Same as mobile apps that embed API credentials
118
- - Same as web apps that expose client keys
119
- - Backend security, not client security
120
-
121
- **What if someone decompiles the CLI?**
122
- - They'll see the Supabase URL and anon key
123
- - But they CANNOT access data without a valid API key
124
- - API keys are user-specific and verified server-side
125
- - RLS prevents unauthorized access
126
-
127
- ---
128
-
129
- ## 📊 What Users See Now
130
-
131
- ### Config File (`~/.langctl/config.json`)
132
- ```json
133
- {
134
- "apiKey": "lc_abc123...",
135
- "organizationId": "uuid-here",
136
- "organizationName": "My Company",
137
- "defaultLanguage": "en"
138
- }
139
- ```
140
-
141
- **Clean and simple!** No backend implementation details.
142
-
143
- ### Running `langctl config`
144
- ```
145
- 📋 Langctl Configuration
146
-
147
- apiKey: lc_abc123...wxyz
148
- organizationId: 550e8400-e29b-41d4-a716-446655440000
149
- organizationName: My Company
150
- defaultLanguage: en
151
-
152
- Config file: /Users/username/.langctl/config.json
153
- ```
154
-
155
- **Only user-relevant information!**
156
-
157
- ---
158
-
159
- ## ✅ Ready to Publish
160
-
161
- This security fix is complete. The CLI now:
162
- - ✅ Keeps backend credentials private
163
- - ✅ Only exposes user data to users
164
- - ✅ Maintains full security with RLS
165
- - ✅ Provides clean user experience
166
-
167
- **Safe to publish to npm!** 🚀
@@ -1,14 +0,0 @@
1
- import { SupabaseClient } from '@supabase/supabase-js';
2
- /**
3
- * Initialize Supabase client with hardcoded credentials
4
- */
5
- export declare function initializeSupabase(): SupabaseClient;
6
- /**
7
- * Get existing Supabase client or initialize it
8
- */
9
- export declare function getSupabase(): SupabaseClient;
10
- /**
11
- * Reset Supabase client (useful for tests)
12
- */
13
- export declare function resetSupabase(): void;
14
- //# sourceMappingURL=supabase.d.ts.map
package/dist/supabase.js DELETED
@@ -1,30 +0,0 @@
1
- import { createClient } from '@supabase/supabase-js';
2
- // Hardcoded Supabase credentials (safe for client-side use with RLS)
3
- const SUPABASE_URL = 'https://bcgnmvkgkbhbxzzflwdb.supabase.co';
4
- const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJjZ25tdmtna2JoYnh6emZsd2RiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzQ3OTE4ODEsImV4cCI6MjA1MDM2Nzg4MX0.LqZYO8GGQfI-C9WCF_a2NTKqIrO1TDsPXU9LHRE8b0E';
5
- let supabaseClient = null;
6
- /**
7
- * Initialize Supabase client with hardcoded credentials
8
- */
9
- export function initializeSupabase() {
10
- if (!supabaseClient) {
11
- supabaseClient = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
12
- }
13
- return supabaseClient;
14
- }
15
- /**
16
- * Get existing Supabase client or initialize it
17
- */
18
- export function getSupabase() {
19
- if (!supabaseClient) {
20
- return initializeSupabase();
21
- }
22
- return supabaseClient;
23
- }
24
- /**
25
- * Reset Supabase client (useful for tests)
26
- */
27
- export function resetSupabase() {
28
- supabaseClient = null;
29
- }
30
- //# sourceMappingURL=supabase.js.map