create-theta-code 1.0.1

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 (68) hide show
  1. package/bin/create.js +9 -0
  2. package/package.json +34 -0
  3. package/src/cli.js +21 -0
  4. package/src/generators/scaffoldProject.js +46 -0
  5. package/src/prompts/getProjectName.js +30 -0
  6. package/src/prompts/getTemplateChoice.js +39 -0
  7. package/src/utils/logger.js +29 -0
  8. package/templates/mongo-js/.env +12 -0
  9. package/templates/mongo-js/.env.example +13 -0
  10. package/templates/mongo-js/.eslintrc.json +24 -0
  11. package/templates/mongo-js/.prettierrc +9 -0
  12. package/templates/mongo-js/README.md +429 -0
  13. package/templates/mongo-js/_env.example +13 -0
  14. package/templates/mongo-js/_gitignore +22 -0
  15. package/templates/mongo-js/package-lock.json +4671 -0
  16. package/templates/mongo-js/package.json +48 -0
  17. package/templates/mongo-js/server.js +67 -0
  18. package/templates/mongo-js/src/config/app.config.js +72 -0
  19. package/templates/mongo-js/src/config/db.config.js +32 -0
  20. package/templates/mongo-js/src/config/env.config.js +49 -0
  21. package/templates/mongo-js/src/config/rateLimiter.config.js +32 -0
  22. package/templates/mongo-js/src/middlewares/auth.middleware.js +20 -0
  23. package/templates/mongo-js/src/middlewares/error.middleware.js +61 -0
  24. package/templates/mongo-js/src/middlewares/notFound.middleware.js +11 -0
  25. package/templates/mongo-js/src/middlewares/requestId.middleware.js +10 -0
  26. package/templates/mongo-js/src/middlewares/requireRole.middleware.js +13 -0
  27. package/templates/mongo-js/src/middlewares/validate.middleware.js +21 -0
  28. package/templates/mongo-js/src/modules/user/user.controller.js +88 -0
  29. package/templates/mongo-js/src/modules/user/user.model.js +45 -0
  30. package/templates/mongo-js/src/modules/user/user.repository.js +47 -0
  31. package/templates/mongo-js/src/modules/user/user.routes.js +32 -0
  32. package/templates/mongo-js/src/modules/user/user.service.js +87 -0
  33. package/templates/mongo-js/src/modules/user/user.validator.js +28 -0
  34. package/templates/mongo-js/src/utils/AppError.js +15 -0
  35. package/templates/mongo-js/src/utils/apiResponse.js +23 -0
  36. package/templates/mongo-js/src/utils/asyncHandler.js +7 -0
  37. package/templates/mongo-js/src/utils/constants.js +16 -0
  38. package/templates/mongo-js/src/utils/jwt.utils.js +40 -0
  39. package/templates/mongo-js/tests/integration/user.routes.test.js +111 -0
  40. package/templates/mongo-js/tests/unit/user.service.test.js +96 -0
  41. package/templates/pg-js/.eslintrc.json +24 -0
  42. package/templates/pg-js/.prettierrc +9 -0
  43. package/templates/pg-js/_env.example +7 -0
  44. package/templates/pg-js/_gitignore +20 -0
  45. package/templates/pg-js/package.json +50 -0
  46. package/templates/pg-js/prisma/schema.prisma +23 -0
  47. package/templates/pg-js/server.js +63 -0
  48. package/templates/pg-js/src/config/app.config.js +48 -0
  49. package/templates/pg-js/src/config/db.config.js +30 -0
  50. package/templates/pg-js/src/config/env.config.js +36 -0
  51. package/templates/pg-js/src/config/rateLimiter.config.js +22 -0
  52. package/templates/pg-js/src/middlewares/auth.middleware.js +32 -0
  53. package/templates/pg-js/src/middlewares/error.middleware.js +50 -0
  54. package/templates/pg-js/src/middlewares/notFound.middleware.js +11 -0
  55. package/templates/pg-js/src/middlewares/validate.middleware.js +21 -0
  56. package/templates/pg-js/src/modules/user/user.controller.js +57 -0
  57. package/templates/pg-js/src/modules/user/user.model.js +20 -0
  58. package/templates/pg-js/src/modules/user/user.repository.js +105 -0
  59. package/templates/pg-js/src/modules/user/user.routes.js +27 -0
  60. package/templates/pg-js/src/modules/user/user.service.js +81 -0
  61. package/templates/pg-js/src/modules/user/user.validator.js +22 -0
  62. package/templates/pg-js/src/utils/AppError.js +14 -0
  63. package/templates/pg-js/src/utils/apiResponse.js +23 -0
  64. package/templates/pg-js/src/utils/asyncHandler.js +7 -0
  65. package/templates/pg-js/src/utils/constants.js +24 -0
  66. package/templates/pg-js/src/utils/jwt.utils.js +39 -0
  67. package/templates/pg-js/tests/integration/user.routes.test.js +95 -0
  68. package/templates/pg-js/tests/unit/user.service.test.js +96 -0
package/bin/create.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ // bin/create.js — Entry point for create-theta-code CLI. Routes to runCLI orchestrator only.
3
+
4
+ import { runCLI } from '../src/cli.js';
5
+
6
+ runCLI(process.argv.slice(2)).catch((err) => {
7
+ console.error(err.message);
8
+ process.exit(1);
9
+ });
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "create-theta-code",
3
+ "version": "1.0.1",
4
+ "description": "Production-grade Node.js + Express scaffolding CLI",
5
+ "type": "module",
6
+ "main": "src/cli.js",
7
+ "bin": {
8
+ "create-theta-code": "bin/create.js"
9
+ },
10
+ "files": [
11
+ "bin",
12
+ "src",
13
+ "templates"
14
+ ],
15
+ "scripts": {
16
+ "dev": "node bin/create.js",
17
+ "test": "echo \"Error: no test specified\" && exit 1"
18
+ },
19
+ "keywords": [
20
+ "scaffolding",
21
+ "cli",
22
+ "nodejs",
23
+ "express",
24
+ "boilerplate"
25
+ ],
26
+ "author": "Theta Labs",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@clack/prompts": "^0.7.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ }
34
+ }
package/src/cli.js ADDED
@@ -0,0 +1,21 @@
1
+ // src/cli.js — CLI orchestrator. Collects prompts, calls scaffoldProject, manages flow.
2
+
3
+ import { printBanner, printSuccess } from './utils/logger.js';
4
+ import { getProjectName } from './prompts/getProjectName.js';
5
+ import { getTemplateChoice } from './prompts/getTemplateChoice.js';
6
+ import { scaffoldProject } from './generators/scaffoldProject.js';
7
+ import { resolve } from 'node:path';
8
+
9
+ async function runCLI(argv) {
10
+ printBanner();
11
+
12
+ const projectName = await getProjectName(argv);
13
+ const templateType = await getTemplateChoice();
14
+
15
+ const currentDir = process.cwd();
16
+ const projectPath = await scaffoldProject(projectName, templateType, currentDir);
17
+
18
+ printSuccess(projectName, templateType, projectPath);
19
+ }
20
+
21
+ export { runCLI };
@@ -0,0 +1,46 @@
1
+ // src/generators/scaffoldProject.js — Copies template, injects project name, renames hidden files.
2
+
3
+ import { cp, readFile, writeFile, rename } from 'node:fs/promises';
4
+ import { join } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { dirname } from 'node:path';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ async function scaffoldProject(projectName, templateType, targetDir) {
12
+ const templatePath = join(__dirname, '..', '..', 'templates', templateType);
13
+ const projectPath = join(targetDir, projectName);
14
+
15
+ // Copy entire template directory
16
+ await cp(templatePath, projectPath, { recursive: true });
17
+
18
+ // Rename _gitignore to .gitignore
19
+ const gitignorePath = join(projectPath, '_gitignore');
20
+ const realGitignorePath = join(projectPath, '.gitignore');
21
+ try {
22
+ await rename(gitignorePath, realGitignorePath);
23
+ } catch (err) {
24
+ // File might not exist, continue
25
+ }
26
+
27
+ // Rename _env.example to .env.example
28
+ const envExamplePath = join(projectPath, '_env.example');
29
+ const realEnvExamplePath = join(projectPath, '.env.example');
30
+ try {
31
+ await rename(envExamplePath, realEnvExamplePath);
32
+ } catch (err) {
33
+ // File might not exist, continue
34
+ }
35
+
36
+ // Update package.json with project name
37
+ const packageJsonPath = join(projectPath, 'package.json');
38
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
39
+ packageJson.name = projectName;
40
+ packageJson.description = `${projectName} - Production-grade Node.js API built with create-theta-code`;
41
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
42
+
43
+ return projectPath;
44
+ }
45
+
46
+ export { scaffoldProject };
@@ -0,0 +1,30 @@
1
+ // src/prompts/getProjectName.js — Reads project name from argv[0] or prompts interactively.
2
+
3
+ import { text } from '@clack/prompts';
4
+ import { isCancel } from '@clack/prompts';
5
+
6
+ async function getProjectName(argv) {
7
+ if (argv.length > 0 && argv[0].trim()) {
8
+ return argv[0].trim();
9
+ }
10
+
11
+ const name = await text({
12
+ message: 'Enter project name:',
13
+ placeholder: 'theta-code-app',
14
+ validate: (input) => {
15
+ if (!input.trim()) return 'Project name is required';
16
+ if (!/^[a-z0-9-]+$/.test(input.trim())) {
17
+ return 'Project name must contain only lowercase letters, numbers, and hyphens';
18
+ }
19
+ return;
20
+ },
21
+ });
22
+
23
+ if (isCancel(name)) {
24
+ process.exit(0);
25
+ }
26
+
27
+ return name;
28
+ }
29
+
30
+ export { getProjectName };
@@ -0,0 +1,39 @@
1
+ // src/prompts/getTemplateChoice.js — Prompts user to choose DB and language. Returns template type.
2
+
3
+ import { select } from '@clack/prompts';
4
+ import { isCancel } from '@clack/prompts';
5
+
6
+ async function getTemplateChoice() {
7
+ const dbChoice = await select({
8
+ message: 'Choose database:',
9
+ options: [
10
+ { value: 'mongo', label: 'MongoDB + Mongoose' },
11
+ { value: 'pg', label: 'PostgreSQL + Prisma' },
12
+ ],
13
+ });
14
+
15
+ if (isCancel(dbChoice)) {
16
+ process.exit(0);
17
+ }
18
+
19
+ const langChoice = await select({
20
+ message: 'Choose language:',
21
+ options: [
22
+ { value: 'js', label: 'JavaScript' },
23
+ { value: 'ts', label: 'TypeScript (coming soon)' },
24
+ ],
25
+ });
26
+
27
+ if (isCancel(langChoice)) {
28
+ process.exit(0);
29
+ }
30
+
31
+ if (langChoice === 'ts') {
32
+ console.log('TypeScript templates coming soon! Defaulting to JavaScript.');
33
+ return `${dbChoice}-js`;
34
+ }
35
+
36
+ return `${dbChoice}-${langChoice}`;
37
+ }
38
+
39
+ export { getTemplateChoice };
@@ -0,0 +1,29 @@
1
+ // src/utils/logger.js — Display banner and success messages only. No logging infrastructure.
2
+
3
+ import { fileURLToPath } from 'node:url';
4
+ import { dirname } from 'node:path';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ function printBanner() {
10
+ console.log('\n╔════════════════════════════════════════╗');
11
+ console.log('║ 🚀 create-theta-code ║');
12
+ console.log('║ Production-Grade Node.js Scaffolding ║');
13
+ console.log('╚════════════════════════════════════════╝\n');
14
+ }
15
+
16
+ function printSuccess(projectName, templateType, projectPath) {
17
+ console.log('\n✅ Project created successfully!\n');
18
+ console.log(`📁 Name: ${projectName}`);
19
+ console.log(`🛠️ Template: ${templateType}`);
20
+ console.log(`📂 Path: ${projectPath}\n`);
21
+ console.log('Next steps:');
22
+ console.log(` 1. cd ${projectName}`);
23
+ console.log(' 2. npm install');
24
+ console.log(' 3. cp .env.example .env');
25
+ console.log(' 4. Fill .env with your configuration');
26
+ console.log(' 5. npm start\n');
27
+ }
28
+
29
+ export { printBanner, printSuccess };
@@ -0,0 +1,12 @@
1
+ NODE_ENV=test
2
+ MONGODB_URI=mongodb://localhost:27017/test
3
+ JWT_SECRET=this_is_a_test_secret_that_is_long_enough
4
+ JWT_REFRESH_SECRET=this_is_a_test_refresh_secret_long_enough
5
+ JWT_EXPIRES_IN=7d
6
+ JWT_REFRESH_EXPIRES_IN=30d
7
+ BCRYPT_SALT_ROUNDS=12
8
+ RATE_LIMIT_WINDOW_MS=900000
9
+ RATE_LIMIT_MAX=100
10
+ AUTH_RATE_LIMIT_MAX=10
11
+ CORS_ORIGIN=http://localhost:3000
12
+ LOG_LEVEL=debug
@@ -0,0 +1,13 @@
1
+ NODE_ENV=development
2
+ PORT=3000
3
+ MONGODB_URI=
4
+ JWT_SECRET=
5
+ JWT_REFRESH_SECRET=
6
+ JWT_EXPIRES_IN=7d
7
+ JWT_REFRESH_EXPIRES_IN=30d
8
+ BCRYPT_SALT_ROUNDS=12
9
+ RATE_LIMIT_WINDOW_MS=900000
10
+ RATE_LIMIT_MAX=100
11
+ AUTH_RATE_LIMIT_MAX=10
12
+ CORS_ORIGIN=http://localhost:3000
13
+ LOG_LEVEL=info
@@ -0,0 +1,24 @@
1
+ {
2
+ "extends": ["eslint:recommended"],
3
+ "env": {
4
+ "node": true,
5
+ "es2022": true
6
+ },
7
+ "parserOptions": {
8
+ "ecmaVersion": 2022,
9
+ "sourceType": "module"
10
+ },
11
+ "rules": {
12
+ "no-console": "off",
13
+ "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
14
+ "prefer-const": "error",
15
+ "no-var": "error",
16
+ "eqeqeq": ["error", "always"],
17
+ "curly": "error",
18
+ "brace-style": ["error", "1tbs"],
19
+ "quotes": ["error", "single", { "avoidEscape": true }],
20
+ "semi": ["error", "always"],
21
+ "comma-dangle": ["error", "always-multiline"],
22
+ "indent": ["error", 2]
23
+ }
24
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "arrowParens": "always"
9
+ }