gotodev 1.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/cli.js ADDED
@@ -0,0 +1,458 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Gotodev CLI - Lightning-fast app creator
5
+ * Usage: gotodev create [app-name] [options]
6
+ */
7
+
8
+ const { Command } = require('commander');
9
+ const inquirer = require('inquirer');
10
+ const ora = require('ora').default;
11
+ const chalk = require('chalk');
12
+ const fs = require('fs-extra');
13
+ const path = require('path');
14
+ const { execSync } = require('child_process');
15
+
16
+ const program = new Command();
17
+ const { GotodevCompiler } = require('./index.js');
18
+
19
+ // Framework presets
20
+ const FRAMEWORKS = {
21
+ react: {
22
+ name: 'React',
23
+ description: 'React with TypeScript',
24
+ files: {
25
+ 'src/App.tsx': `import React, { useState } from 'react';
26
+
27
+ export default function App() {
28
+ const [count, setCount] = useState(0);
29
+
30
+ return (
31
+ <div style={{ padding: '20px', fontFamily: 'system-ui' }}>
32
+ <h1>⚡ Gotodev React App</h1>
33
+ <p>Count: {count}</p>
34
+ <button onClick={() => setCount(count + 1)}>Increment</button>
35
+ </div>
36
+ );
37
+ }`,
38
+ 'src/index.tsx': `import React from 'react';
39
+ import { createRoot } from 'react-dom/client';
40
+ import App from './App';
41
+
42
+ const container = document.getElementById('root');
43
+ if (container) {
44
+ createRoot(container).render(<App />);
45
+ }`,
46
+ 'index.html': `<!DOCTYPE html>
47
+ <html>
48
+ <head>
49
+ <title>Gotodev React App</title>
50
+ <meta charset="UTF-8" />
51
+ </head>
52
+ <body>
53
+ <div id="root"></div>
54
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
55
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
56
+ <script type="module" src="/src/index.tsx"></script>
57
+ </body>
58
+ </html>`,
59
+ 'package.json': `{
60
+ "name": "my-react-app",
61
+ "version": "1.0.0",
62
+ "type": "module",
63
+ "scripts": {
64
+ "dev": "gotodev dev",
65
+ "build": "gotodev build"
66
+ }
67
+ }`
68
+ }
69
+ },
70
+ vue: {
71
+ name: 'Vue',
72
+ description: 'Vue 3 with TypeScript',
73
+ files: {
74
+ 'src/App.vue': `<template>
75
+ <div style="padding: 20px; font-family: system-ui;">
76
+ <h1>⚡ Gotodev Vue App</h1>
77
+ <p>Count: {{ count }}</p>
78
+ <button @click="count++">Increment</button>
79
+ </div>
80
+ </template>
81
+
82
+ <script setup lang="ts">
83
+ import { ref } from 'vue';
84
+ const count = ref(0);
85
+ </script>`,
86
+ 'src/main.ts': `import { createApp } from 'vue';
87
+ import App from './App.vue';
88
+
89
+ createApp(App).mount('#app');`,
90
+ 'index.html': `<!DOCTYPE html>
91
+ <html>
92
+ <head>
93
+ <title>Gotodev Vue App</title>
94
+ <meta charset="UTF-8" />
95
+ </head>
96
+ <body>
97
+ <div id="app"></div>
98
+ <script type="module" src="/src/main.ts"></script>
99
+ </body>
100
+ </html>`,
101
+ 'package.json': `{
102
+ "name": "my-vue-app",
103
+ "version": "1.0.0",
104
+ "type": "module",
105
+ "scripts": {
106
+ "dev": "gotodev dev",
107
+ "build": "gotodev build"
108
+ }
109
+ }`
110
+ }
111
+ },
112
+ svelte: {
113
+ name: 'Svelte',
114
+ description: 'Svelte with TypeScript',
115
+ files: {
116
+ 'src/App.svelte': `<script lang="ts">
117
+ let count: number = 0;
118
+ </script>
119
+
120
+ <style>
121
+ div { padding: 20px; font-family: system-ui; }
122
+ h1 { color: #ff3e00; }
123
+ </style>
124
+
125
+ <div>
126
+ <h1>⚡ Gotodev Svelte App</h1>
127
+ <p>Count: {count}</p>
128
+ <button on:click={() => count++}>Increment</button>
129
+ </div>`,
130
+ 'src/main.ts': `import App from './App.svelte';
131
+
132
+ const app = new App({
133
+ target: document.body,
134
+ });
135
+
136
+ export default app;`,
137
+ 'index.html': `<!DOCTYPE html>
138
+ <html>
139
+ <head>
140
+ <title>Gotodev Svelte App</title>
141
+ <meta charset="UTF-8" />
142
+ </head>
143
+ <body>
144
+ <script type="module" src="/src/main.ts"></script>
145
+ </body>
146
+ </html>`,
147
+ 'package.json': `{
148
+ "name": "my-svelte-app",
149
+ "version": "1.0.0",
150
+ "type": "module",
151
+ "scripts": {
152
+ "dev": "gotodev dev",
153
+ "build": "gotodev build"
154
+ }
155
+ }`
156
+ }
157
+ },
158
+ vanilla: {
159
+ name: 'Vanilla',
160
+ description: 'Pure TypeScript',
161
+ files: {
162
+ 'src/main.ts': `const app = document.getElementById('app');
163
+ if (app) {
164
+ app.innerHTML = \`
165
+ <h1>⚡ Gotodev Vanilla App</h1>
166
+ <p>TypeScript ready!</p>
167
+ \`;
168
+ }`,
169
+ 'index.html': `<!DOCTYPE html>
170
+ <html>
171
+ <head>
172
+ <title>Gotodev Vanilla App</title>
173
+ <meta charset="UTF-8" />
174
+ </head>
175
+ <body>
176
+ <div id="app"></div>
177
+ <script type="module" src="/src/main.ts"></script>
178
+ </body>
179
+ </html>`,
180
+ 'package.json': `{
181
+ "name": "my-vanilla-app",
182
+ "version": "1.0.0",
183
+ "type": "module",
184
+ "scripts": {
185
+ "dev": "gotodev dev",
186
+ "build": "gotodev build"
187
+ }
188
+ }`
189
+ }
190
+ }
191
+ };
192
+
193
+ // Helper: Compile TypeScript with Gotodev
194
+ async function compileWithGotodev(code, filename) {
195
+ const compiler = new GotodevCompiler({
196
+ strip_types: true,
197
+ transform_jsx: true,
198
+ target: 'es2020'
199
+ });
200
+
201
+ const result = compiler.transform(code, filename);
202
+ return result.code;
203
+ }
204
+
205
+ // Helper: Create project structure
206
+ async function createProject(projectName, framework) {
207
+ const spinner = ora(`Creating ${framework} app...`).start();
208
+
209
+ try {
210
+ const projectPath = path.join(process.cwd(), projectName);
211
+
212
+ // Check if directory exists
213
+ if (fs.existsSync(projectPath)) {
214
+ spinner.fail(`Directory ${projectName} already exists!`);
215
+ process.exit(1);
216
+ }
217
+
218
+ // Create directory
219
+ fs.mkdirSync(projectPath, { recursive: true });
220
+
221
+ const preset = FRAMEWORKS[framework];
222
+
223
+ // Create files
224
+ for (const [filePath, content] of Object.entries(preset.files)) {
225
+ const fullPath = path.join(projectPath, filePath);
226
+ const dir = path.dirname(fullPath);
227
+
228
+ fs.mkdirSync(dir, { recursive: true });
229
+
230
+ // Compile TypeScript files
231
+ if (filePath.endsWith('.tsx') || filePath.endsWith('.ts')) {
232
+ spinner.text = `Compiling ${filePath}...`;
233
+ const compiled = await compileWithGotodev(content, filePath);
234
+ fs.writeFileSync(fullPath.replace(/\.(tsx|ts)$/, '.js'), compiled);
235
+
236
+ // Also keep original for reference
237
+ fs.writeFileSync(fullPath, content);
238
+ } else {
239
+ fs.writeFileSync(fullPath, content);
240
+ }
241
+ }
242
+
243
+ // Create README
244
+ const readme = `# ${projectName}
245
+
246
+ Generated with **Gotodev** ⚡
247
+
248
+ ## Quick Start
249
+
250
+ \`\`\`bash
251
+ # Install dependencies (if any)
252
+ npm install
253
+
254
+ # Start development server
255
+ npm run dev
256
+
257
+ # Build for production
258
+ npm run build
259
+ \`\`\`
260
+
261
+ ## Framework: ${preset.name}
262
+
263
+ ${preset.description}
264
+
265
+ ## Why Gotodev?
266
+
267
+ - ⚡ **Instant** - Built with Rust for speed
268
+ - 🎯 **Modern** - TypeScript + latest frameworks
269
+ - 🔥 **Hot Reload** - Fast development
270
+ - 📦 **Optimized** - Production-ready builds
271
+
272
+ ## Commands
273
+
274
+ - \`npm run dev\` - Start dev server
275
+ - \`npm run build\` - Create production bundle
276
+
277
+ ---
278
+
279
+ Made with ❤️ using Gotodev`;
280
+
281
+ fs.writeFileSync(path.join(projectPath, 'README.md'), readme);
282
+
283
+ spinner.succeed(`✅ ${preset.name} app created successfully!`);
284
+
285
+ console.log(`\n${chalk.green('🎉 Success!')}`);
286
+ console.log(`\n${chalk.cyan('Next steps:')}`);
287
+ console.log(` cd ${projectName}`);
288
+ console.log(` npm install`);
289
+ console.log(` npm run dev`);
290
+
291
+ return true;
292
+ } catch (error) {
293
+ spinner.fail(`Failed to create project: ${error.message}`);
294
+ return false;
295
+ }
296
+ }
297
+
298
+ // Helper: Start dev server
299
+ async function startDevServer() {
300
+ const spinner = ora('Starting dev server...').start();
301
+
302
+ try {
303
+ // Check if we're in a project
304
+ const packageJson = path.join(process.cwd(), 'package.json');
305
+ if (!fs.existsSync(packageJson)) {
306
+ spinner.fail('Not in a project directory');
307
+ process.exit(1);
308
+ }
309
+
310
+ // Simple dev server implementation
311
+ const http = require('http');
312
+ const fs = require('fs');
313
+ const path = require('path');
314
+
315
+ const PORT = 3000;
316
+
317
+ const server = http.createServer((req, res) => {
318
+ let filePath = req.url === '/' ? '/index.html' : req.url;
319
+ filePath = path.join(process.cwd(), filePath);
320
+
321
+ // Try to serve compiled JS files
322
+ if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
323
+ filePath = filePath.replace(/\.(tsx|ts)$/, '.js');
324
+ }
325
+
326
+ if (fs.existsSync(filePath)) {
327
+ const content = fs.readFileSync(filePath, 'utf8');
328
+ const ext = path.extname(filePath);
329
+
330
+ const contentTypes = {
331
+ '.html': 'text/html',
332
+ '.js': 'application/javascript',
333
+ '.css': 'text/css',
334
+ '.json': 'application/json'
335
+ };
336
+
337
+ res.writeHead(200, {
338
+ 'Content-Type': contentTypes[ext] || 'text/plain',
339
+ 'Access-Control-Allow-Origin': '*'
340
+ });
341
+ res.end(content);
342
+ } else {
343
+ res.writeHead(404);
344
+ res.end('Not found');
345
+ }
346
+ });
347
+
348
+ server.listen(PORT, () => {
349
+ spinner.succeed(`Dev server running at http://localhost:${PORT}`);
350
+ console.log(`${chalk.yellow('Press Ctrl+C to stop')}`);
351
+ });
352
+
353
+ // Watch for changes
354
+ fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
355
+ if (filename && (filename.endsWith('.ts') || filename.endsWith('.tsx'))) {
356
+ console.log(`${chalk.green('🔄 File changed:')} ${filename}`);
357
+ }
358
+ });
359
+
360
+ } catch (error) {
361
+ spinner.fail(`Failed to start server: ${error.message}`);
362
+ }
363
+ }
364
+
365
+ // Helper: Build project
366
+ async function buildProject() {
367
+ const spinner = ora('Building project...').start();
368
+
369
+ try {
370
+ // Check if we're in a project
371
+ const packageJson = path.join(process.cwd(), 'package.json');
372
+ if (!fs.existsSync(packageJson)) {
373
+ spinner.fail('Not in a project directory');
374
+ process.exit(1);
375
+ }
376
+
377
+ // Create dist directory
378
+ const distPath = path.join(process.cwd(), 'dist');
379
+ fs.mkdirSync(distPath, { recursive: true });
380
+
381
+ // Compile all TypeScript files
382
+ const srcPath = path.join(process.cwd(), 'src');
383
+ if (fs.existsSync(srcPath)) {
384
+ const files = fs.readdirSync(srcPath, { recursive: true });
385
+
386
+ for (const file of files) {
387
+ const filePath = path.join(srcPath, file);
388
+ if (fs.statSync(filePath).isFile() && (file.endsWith('.ts') || file.endsWith('.tsx'))) {
389
+ const content = fs.readFileSync(filePath, 'utf8');
390
+ const compiled = await compileWithGotodev(content, file);
391
+
392
+ const destPath = path.join(distPath, file.replace(/\.(tsx|ts)$/, '.js'));
393
+ const destDir = path.dirname(destPath);
394
+ fs.mkdirSync(destDir, { recursive: true });
395
+ fs.writeFileSync(destPath, compiled);
396
+ }
397
+ }
398
+ }
399
+
400
+ // Copy HTML
401
+ const htmlPath = path.join(process.cwd(), 'index.html');
402
+ if (fs.existsSync(htmlPath)) {
403
+ fs.copySync(htmlPath, path.join(distPath, 'index.html'));
404
+ }
405
+
406
+ spinner.succeed('✅ Build complete!');
407
+ console.log(`\n�� Output: ${chalk.cyan('dist/')}`);
408
+ console.log(`🚀 To serve: ${chalk.yellow('cd dist && python3 -m http.server 8000')}`);
409
+
410
+ } catch (error) {
411
+ spinner.fail(`Build failed: ${error.message}`);
412
+ }
413
+ }
414
+
415
+ // Main CLI
416
+ program
417
+ .name('gotodev')
418
+ .description('⚡ Lightning-fast app creator for React, Vue, and more')
419
+ .version('0.1.0');
420
+
421
+ program
422
+ .command('create <app-name>')
423
+ .description('Create a new app')
424
+ .option('-f, --framework <framework>', 'Framework to use', 'react')
425
+ .action(async (appName, options) => {
426
+ const frameworks = Object.keys(FRAMEWORKS);
427
+
428
+ if (!frameworks.includes(options.framework)) {
429
+ console.log(`${chalk.red('Error:')} Invalid framework "${options.framework}"`);
430
+ console.log(`Available: ${frameworks.join(', ')}`);
431
+ process.exit(1);
432
+ }
433
+
434
+ await createProject(appName, options.framework);
435
+ });
436
+
437
+ program
438
+ .command('dev')
439
+ .description('Start development server')
440
+ .action(startDevServer);
441
+
442
+ program
443
+ .command('build')
444
+ .description('Build for production')
445
+ .action(buildProject);
446
+
447
+ program
448
+ .command('list')
449
+ .description('List available frameworks')
450
+ .action(() => {
451
+ console.log('\nAvailable frameworks:');
452
+ Object.entries(FRAMEWORKS).forEach(([key, value]) => {
453
+ console.log(` ${chalk.cyan(key.padEnd(10))} - ${value.description}`);
454
+ });
455
+ console.log('');
456
+ });
457
+
458
+ program.parse(process.argv);
package/index.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /** JavaScript-accessible compilation result */
7
+ export interface CompilationResult {
8
+ code: string
9
+ map?: string
10
+ durationMs: number
11
+ success: boolean
12
+ }
13
+ /** JavaScript-accessible transform options */
14
+ export interface TransformOptions {
15
+ stripTypes?: boolean
16
+ transformJsx?: boolean
17
+ target?: string
18
+ sourceMap?: boolean
19
+ }
20
+ /**
21
+ * Utility function to transform a single code string without creating a compiler instance
22
+ * This is useful for one-off transformations and benchmarking
23
+ */
24
+ export declare function transformCode(code: string, filename?: string | undefined | null): CompilationResult
25
+ /**
26
+ * # GotodevCompiler - NAPI-RS Bridge
27
+ *
28
+ * This is the main entry point for Node.js code to access the Rust compiler.
29
+ * The `#[napi]` macro generates all necessary FFI bindings automatically.
30
+ *
31
+ * ## Zero-Overhead Bridge Architecture
32
+ *
33
+ * 1. **Direct Memory Mapping**: NAPI-RS maps JavaScript strings directly to
34
+ * Rust memory without copying when possible.
35
+ *
36
+ * 2. **Automatic Type Conversion**: Complex types are serialized via serde
37
+ * with minimal overhead, using JSON as a zero-copy interchange format.
38
+ *
39
+ * 3. **Lifetime Management**: NAPI-RS handles JavaScript GC integration,
40
+ * ensuring Rust objects are properly retained/released.
41
+ */
42
+ export declare class GotodevCompiler {
43
+ /** Create a new compiler instance */
44
+ constructor(options?: TransformOptions | undefined | null)
45
+ /**
46
+ * Transform TypeScript/JavaScript code to JavaScript
47
+ *
48
+ * # Arguments
49
+ * * `code` - Source code to transform
50
+ * * `filename` - Optional filename for source type detection
51
+ *
52
+ * # Returns
53
+ * CompilationResult with transformed code and metadata
54
+ */
55
+ transform(code: string, filename?: string | undefined | null): CompilationResult
56
+ /**
57
+ * Batch transform multiple files
58
+ *
59
+ * This demonstrates the parallel processing capabilities of the core engine.
60
+ * Files are processed concurrently using Rayon's work-stealing scheduler.
61
+ */
62
+ transformBatch(files: Array<[string, string | undefined | null]>): Array<CompilationResult>
63
+ /** Get compiler version information */
64
+ version(): string
65
+ }