@devbro/pashmak 0.1.55 → 0.1.56

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 (38) hide show
  1. package/dist/cjs/app/console/index.js +268 -70
  2. package/dist/cjs/app/console/project/CreateProjectCommand.js +263 -65
  3. package/dist/cjs/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
  4. package/dist/cjs/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
  5. package/dist/cjs/app/console/project/base_project/src/config/default.mts.tpl +13 -20
  6. package/dist/cjs/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
  7. package/dist/cjs/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
  8. package/dist/cjs/app/console/project/base_project/src/initialize.ts.tpl +48 -16
  9. package/dist/cjs/app/console/project/base_project/src/routes.ts.tpl +2 -2
  10. package/dist/cjs/bin/pashmak_cli.js +265 -66
  11. package/dist/cjs/index.js +1785 -1993
  12. package/dist/cjs/middlewares.js +60 -2
  13. package/dist/esm/app/console/project/CreateProjectCommand.d.mts +15 -2
  14. package/dist/esm/app/console/project/CreateProjectCommand.mjs +265 -67
  15. package/dist/esm/app/console/project/CreateProjectCommand.mjs.map +1 -1
  16. package/dist/esm/app/console/project/base_project/src/config/caches.ts.tpl +11 -1
  17. package/dist/esm/app/console/project/base_project/src/config/databases.ts.tpl +8 -6
  18. package/dist/esm/app/console/project/base_project/src/config/default.mts.tpl +13 -20
  19. package/dist/esm/app/console/project/base_project/src/config/loggers.ts.tpl +13 -3
  20. package/dist/esm/app/console/project/base_project/src/config/storages.ts.tpl +1 -2
  21. package/dist/esm/app/console/project/base_project/src/initialize.ts.tpl +48 -16
  22. package/dist/esm/app/console/project/base_project/src/routes.ts.tpl +2 -2
  23. package/dist/esm/bin/pashmak_cli.mjs +2 -1
  24. package/dist/esm/bin/pashmak_cli.mjs.map +1 -1
  25. package/dist/esm/config.mjs.map +1 -1
  26. package/dist/esm/index.d.mts +1 -7
  27. package/dist/esm/index.mjs +1 -32
  28. package/dist/esm/index.mjs.map +1 -1
  29. package/dist/esm/middlewares.d.mts +12 -1
  30. package/dist/esm/middlewares.mjs +52 -0
  31. package/dist/esm/middlewares.mjs.map +1 -1
  32. package/package.json +4 -2
  33. package/dist/cjs/app/console/project/base_project/package.json.tpl +0 -74
  34. package/dist/cjs/app/console/project/base_project/src/config/test.ts.tpl +0 -1
  35. package/dist/esm/app/console/project/base_project/package.json.tpl +0 -74
  36. package/dist/esm/app/console/project/base_project/src/config/test.ts.tpl +0 -1
  37. /package/dist/cjs/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
  38. /package/dist/esm/app/console/project/base_project/src/config/{mailer.ts.tpl → mailers.ts.tpl} +0 -0
@@ -1539,13 +1539,13 @@ function normalize(strArray) {
1539
1539
  }
1540
1540
  __name(normalize, "normalize");
1541
1541
  function urlJoin() {
1542
- var input;
1542
+ var input2;
1543
1543
  if (typeof arguments[0] === "object") {
1544
- input = arguments[0];
1544
+ input2 = arguments[0];
1545
1545
  } else {
1546
- input = [].slice.call(arguments);
1546
+ input2 = [].slice.call(arguments);
1547
1547
  }
1548
- return normalize(input);
1548
+ return normalize(input2);
1549
1549
  }
1550
1550
  __name(urlJoin, "urlJoin");
1551
1551
 
@@ -2656,24 +2656,17 @@ var CreateProjectCommand = class extends import_clipanion10.Command {
2656
2656
  category: `Project`,
2657
2657
  description: `Create a new project`,
2658
2658
  details: `
2659
- This command creates a new project with the specified name at the given path.
2660
- If no path is provided, the project will be created in the current directory.
2659
+ This command creates a new project interactively.
2660
+ You will be prompted for the project path and other configuration options.
2661
2661
  `,
2662
- examples: [
2663
- [
2664
- `Create a new project in specified directory`,
2665
- `create project --path /path/to/my-project --git`
2666
- ],
2667
- [
2668
- `Create a new project at a specific path with git initialized`,
2669
- `create project --path /path/to/my-project --git`
2670
- ]
2671
- ]
2672
- });
2673
- projectPath = import_clipanion10.Option.String("--path", { required: true });
2674
- git = import_clipanion10.Option.Boolean(`--git`, false, {
2675
- description: `Initialize a git repository in the new project`
2662
+ examples: [[`Create a new project`, `create project`]]
2676
2663
  });
2664
+ projectPath = "";
2665
+ executor = "";
2666
+ packageManager = "";
2667
+ linter = "";
2668
+ validation_library = "";
2669
+ database_type = "";
2677
2670
  async folderExists(folderPath) {
2678
2671
  try {
2679
2672
  const stats = await fs7.stat(folderPath);
@@ -2686,14 +2679,148 @@ var CreateProjectCommand = class extends import_clipanion10.Command {
2686
2679
  }
2687
2680
  }
2688
2681
  async execute() {
2689
- const projectPath = import_path8.default.join(this.projectPath);
2690
- try {
2691
- await fs7.access(projectPath);
2692
- console.error(`Error: Directory ${projectPath} already exists.`);
2693
- return 1;
2694
- } catch {
2682
+ await this.setupProjectPath();
2683
+ await this.setupGit();
2684
+ await this.setupExecutorAndPackageManager();
2685
+ await this.setupLinter();
2686
+ await this.setupGeneralPackages();
2687
+ await this.setupBaseProject();
2688
+ await this.installPackages();
2689
+ }
2690
+ async processTplFolder(src, dest, data = {}) {
2691
+ const files = await fs7.readdir(src, { withFileTypes: true });
2692
+ for (const file of files) {
2693
+ const srcPath = import_path8.default.join(src, file.name);
2694
+ const destPath = file.isFile() && file.name.endsWith(".tpl") ? import_path8.default.join(dest, file.name.substring(0, file.name.length - 4)) : import_path8.default.join(dest, file.name);
2695
+ if (file.isDirectory()) {
2696
+ await fs7.mkdir(destPath, { recursive: true });
2697
+ await this.processTplFolder(srcPath, destPath, data);
2698
+ } else if (file.name.endsWith(".tpl")) {
2699
+ await this.processTplFile(srcPath, destPath, data);
2700
+ } else {
2701
+ throw new Error(
2702
+ "unexpected non tpl file: " + srcPath + " " + file.name
2703
+ );
2704
+ }
2695
2705
  }
2696
- const validation_library = await (0, import_prompts.select)({
2706
+ }
2707
+ async processTplFile(src, dest, data = {}) {
2708
+ import_handlebars3.default.registerHelper("eq", (a, b) => a === b);
2709
+ const compiledTemplate = import_handlebars3.default.compile(
2710
+ (await fs7.readFile(src)).toString()
2711
+ );
2712
+ const template = await compiledTemplate(data);
2713
+ await fs7.writeFile(dest, template);
2714
+ }
2715
+ async setupProjectPath() {
2716
+ const pathInput = await (0, import_prompts.input)({
2717
+ message: "Enter project path (leave empty to use current directory):",
2718
+ default: ""
2719
+ });
2720
+ this.projectPath = pathInput.trim() ? import_path8.default.resolve(pathInput.trim()) : process.cwd();
2721
+ await fs7.mkdir(this.projectPath, { recursive: true });
2722
+ const files = await fs7.readdir(this.projectPath);
2723
+ if (files.length > 0) {
2724
+ throw new Error(
2725
+ `Directory ${this.projectPath} is not empty. Please use an empty directory.`
2726
+ );
2727
+ }
2728
+ }
2729
+ async setupExecutorAndPackageManager() {
2730
+ this.executor = await (0, import_prompts.select)({
2731
+ message: "Select a TypeScript executor",
2732
+ choices: [
2733
+ {
2734
+ name: "Bun",
2735
+ value: "bun",
2736
+ description: "Fast all-in-one JavaScript runtime"
2737
+ },
2738
+ {
2739
+ name: "TSX",
2740
+ value: "tsx",
2741
+ description: "TypeScript execute (tsx) - Node.js enhanced with esbuild"
2742
+ }
2743
+ ]
2744
+ });
2745
+ this.packageManager = this.executor === "bun" ? "bun" : await (0, import_prompts.select)({
2746
+ message: "Select a package manager",
2747
+ choices: [
2748
+ {
2749
+ name: "Yarn",
2750
+ value: "yarn",
2751
+ description: "Fast, reliable, and secure dependency management"
2752
+ },
2753
+ {
2754
+ name: "npm",
2755
+ value: "npm",
2756
+ description: "Node package manager (default)"
2757
+ },
2758
+ {
2759
+ name: "Bun",
2760
+ value: "bun",
2761
+ description: "Ultra-fast package manager built into Bun"
2762
+ }
2763
+ ],
2764
+ default: "yarn"
2765
+ });
2766
+ (0, import_child_process.execSync)(`${this.packageManager} init -y`, {
2767
+ stdio: "inherit",
2768
+ cwd: this.projectPath
2769
+ });
2770
+ const packageJsonPath = import_path8.default.join(this.projectPath, `package.json`);
2771
+ let packageJson = JSON.parse(await fs7.readFile(packageJsonPath, `utf-8`));
2772
+ packageJson.type = "module";
2773
+ packageJson.scripts = packageJson.scripts || {};
2774
+ packageJson.scripts.prepare = "husky init";
2775
+ packageJson.scripts.clean = "rm -rf dist";
2776
+ if (this.executor === "bun") {
2777
+ packageJson.scripts.dev = "bun run dev";
2778
+ packageJson.scripts.start = "bun run pdev";
2779
+ packageJson.scripts.build = "bun run build";
2780
+ packageJson.scripts.test = "vitest";
2781
+ packageJson.scripts["test:watch"] = "vitest --watch";
2782
+ packageJson.scripts["test:coverage"] = "vitest run --coverage";
2783
+ } else if (this.executor === "tsx") {
2784
+ packageJson.scripts.dev = "tsx --watch -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty";
2785
+ packageJson.scripts.start = "tsx dist/index.js";
2786
+ packageJson.scripts.build = "tsc";
2787
+ packageJson.scripts.test = "vitest";
2788
+ packageJson.scripts["test:watch"] = "vitest --watch";
2789
+ packageJson.scripts["test:coverage"] = "vitest run --coverage";
2790
+ }
2791
+ await fs7.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
2792
+ }
2793
+ async setupLinter() {
2794
+ this.linter = await (0, import_prompts.select)({
2795
+ message: "Select a linter",
2796
+ choices: [
2797
+ {
2798
+ name: "Biome",
2799
+ value: "biome",
2800
+ description: "Fast formatter and linter for JavaScript, TypeScript, and more"
2801
+ },
2802
+ {
2803
+ name: "ESLint",
2804
+ value: "eslint",
2805
+ description: "Find and fix problems in your JavaScript code"
2806
+ }
2807
+ ]
2808
+ });
2809
+ const packageJsonPath = import_path8.default.join(this.projectPath, `package.json`);
2810
+ let packageJson = JSON.parse(await fs7.readFile(packageJsonPath, `utf-8`));
2811
+ if (this.linter === "biome") {
2812
+ packageJson.scripts.lint = "biome check . --ext .ts,.tsx";
2813
+ packageJson.scripts.format = "biome format . --ext .ts,.tsx --write";
2814
+ this.addPackage("@biomejs/biome", true);
2815
+ } else if (this.linter === "eslint") {
2816
+ packageJson.scripts.lint = "eslint . --ext .ts,.tsx";
2817
+ packageJson.scripts.format = "eslint . --ext .ts,.tsx --fix";
2818
+ this.addPackage("eslint", true);
2819
+ }
2820
+ await fs7.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
2821
+ }
2822
+ async setupGeneralPackages() {
2823
+ this.validation_library = await (0, import_prompts.select)({
2697
2824
  message: "Select a package you want for validation",
2698
2825
  choices: [
2699
2826
  {
@@ -2714,8 +2841,42 @@ var CreateProjectCommand = class extends import_clipanion10.Command {
2714
2841
  }
2715
2842
  ]
2716
2843
  });
2717
- await fs7.mkdir(projectPath, { recursive: true });
2718
- console.log(`Created project directory at: ${projectPath}`);
2844
+ this.validation_library === "none" || await this.addPackage(this.validation_library);
2845
+ this.database_type = await (0, import_prompts.select)({
2846
+ message: "Select a database type (you can add more databases later)",
2847
+ choices: [
2848
+ {
2849
+ name: "PostgreSQL",
2850
+ value: "postgresql",
2851
+ description: "A powerful, open source object-relational database system"
2852
+ },
2853
+ {
2854
+ name: "MySQL",
2855
+ value: "mysql",
2856
+ description: "The world's most popular open source database"
2857
+ },
2858
+ {
2859
+ name: "SQLite",
2860
+ value: "sqlite",
2861
+ description: "A C library that provides a lightweight disk-based database"
2862
+ }
2863
+ ]
2864
+ });
2865
+ if (this.database_type === "postgresql") {
2866
+ await this.addPackage("pg pg-cursor");
2867
+ } else if (this.database_type === "mysql") {
2868
+ await this.addPackage("mysql2");
2869
+ } else if (this.database_type === "sqlite") {
2870
+ await this.addPackage("sqlite3");
2871
+ }
2872
+ await this.addPackage("@devbro/pashmak tsconfig-paths dotenv ");
2873
+ await this.addPackage(
2874
+ "husky vitest supertest @types/supertest pino-pretty typescript tsx",
2875
+ true
2876
+ );
2877
+ }
2878
+ async setupBaseProject() {
2879
+ console.log(`Using project directory: ${this.projectPath}`);
2719
2880
  const dirname = typeof __dirname === "undefined" ? import_path8.default.dirname((0, import_url3.fileURLToPath)(import_meta3.url)) : __dirname;
2720
2881
  let basePath = import_path8.default.join(dirname, `./base_project`);
2721
2882
  if (await this.folderExists(basePath) === false) {
@@ -2723,53 +2884,90 @@ var CreateProjectCommand = class extends import_clipanion10.Command {
2723
2884
  }
2724
2885
  console.log(`Using base project path: ${basePath}`);
2725
2886
  const baseProjectPath = basePath;
2726
- await this.processTplFolder(baseProjectPath, projectPath, {
2727
- validation_library
2887
+ await this.processTplFolder(baseProjectPath, this.projectPath, {
2888
+ validation_library: this.validation_library,
2889
+ executor: this.executor,
2890
+ package_manager: this.packageManager,
2891
+ linter: this.linter,
2892
+ database_type: this.database_type
2728
2893
  });
2729
- console.log(`Copied base project files to: ${projectPath}`);
2730
- const packageJsonPath = import_path8.default.join(projectPath, `package.json`);
2731
- const packageJson = JSON.parse(await fs7.readFile(packageJsonPath, `utf-8`));
2732
- packageJson.name = import_change_case_all3.Case.snake(import_path8.default.basename(projectPath));
2894
+ console.log(`Copied base project files to: ${this.projectPath}`);
2895
+ const packageJsonPath = import_path8.default.join(this.projectPath, "package.json");
2896
+ let packageJson = JSON.parse(await fs7.readFile(packageJsonPath, `utf-8`));
2897
+ packageJson.name = import_change_case_all3.Case.snake(import_path8.default.basename(this.projectPath));
2733
2898
  await fs7.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
2734
2899
  console.log(`Updated package.json with project name: ${packageJson.name}`);
2735
- if (this.git) {
2736
- try {
2737
- (0, import_child_process.execSync)(
2738
- 'git init; git add --all; git commit --allow-empty -m "chore: first commit for pashmak"',
2739
- {
2740
- cwd: projectPath
2741
- }
2742
- );
2743
- } catch (error) {
2744
- console.error(`Failed to create project.`, error);
2745
- return 1;
2746
- }
2747
- }
2748
2900
  }
2749
- async processTplFolder(src, dest, data = {}) {
2750
- const files = await fs7.readdir(src, { withFileTypes: true });
2751
- for (const file of files) {
2752
- const srcPath = import_path8.default.join(src, file.name);
2753
- const destPath = file.isFile() && file.name.endsWith(".tpl") ? import_path8.default.join(dest, file.name.substring(0, file.name.length - 4)) : import_path8.default.join(dest, file.name);
2754
- if (file.isDirectory()) {
2755
- await fs7.mkdir(destPath, { recursive: true });
2756
- await this.processTplFolder(srcPath, destPath, data);
2757
- } else if (file.name.endsWith(".tpl")) {
2758
- await this.processTplFile(srcPath, destPath, data);
2759
- } else {
2760
- throw new Error(
2761
- "unexpected non tpl file: " + srcPath + " " + file.name
2762
- );
2763
- }
2901
+ async addPackage(packageName, dev = false) {
2902
+ let install_command = "";
2903
+ switch (this.packageManager) {
2904
+ case "bun":
2905
+ install_command = `bun add ${packageName}${dev ? " -d" : ""}`;
2906
+ break;
2907
+ case "yarn":
2908
+ install_command = `yarn add ${packageName}${dev ? " -D" : ""} --no-install`;
2909
+ break;
2910
+ case "npm":
2911
+ install_command = `npm install ${packageName}${dev ? " --save-dev" : ""} --package-lock-only`;
2912
+ break;
2913
+ }
2914
+ (0, import_child_process.execSync)(install_command, {
2915
+ stdio: "inherit",
2916
+ cwd: this.projectPath
2917
+ });
2918
+ }
2919
+ async installPackages() {
2920
+ const install_command = this.packageManager === "bun" ? `bun install` : this.packageManager === "yarn" ? `yarn` : `npm install`;
2921
+ (0, import_child_process.execSync)(install_command, {
2922
+ stdio: "inherit",
2923
+ cwd: this.projectPath
2924
+ });
2925
+ }
2926
+ async setupGit() {
2927
+ const initGit = await (0, import_prompts.select)({
2928
+ message: "Initialize a git repository?",
2929
+ choices: [
2930
+ {
2931
+ name: "Yes",
2932
+ value: true,
2933
+ description: "Initialize git and create first commit"
2934
+ },
2935
+ {
2936
+ name: "No",
2937
+ value: false,
2938
+ description: "Skip git initialization"
2939
+ }
2940
+ ]
2941
+ });
2942
+ if (initGit) {
2943
+ const gitignoreContent = [
2944
+ "node_modules/",
2945
+ "dist/",
2946
+ ".env",
2947
+ ".env.*",
2948
+ "!.env.example",
2949
+ "*.log",
2950
+ "coverage/",
2951
+ ".DS_Store"
2952
+ ].join("\n") + "\n";
2953
+ await fs7.writeFile(
2954
+ import_path8.default.join(this.projectPath, ".gitignore"),
2955
+ gitignoreContent
2956
+ );
2957
+ (0, import_child_process.execSync)(
2958
+ `git init; git add --all; git commit --allow-empty -m "chore: first commit"`,
2959
+ {
2960
+ cwd: this.projectPath
2961
+ }
2962
+ );
2764
2963
  }
2765
2964
  }
2766
- async processTplFile(src, dest, data = {}) {
2767
- import_handlebars3.default.registerHelper("eq", (a, b) => a === b);
2768
- const compiledTemplate = import_handlebars3.default.compile(
2769
- (await fs7.readFile(src)).toString()
2770
- );
2771
- const template = await compiledTemplate(data);
2772
- await fs7.writeFile(dest, template);
2965
+ async catch(error) {
2966
+ if (Error.isError(error)) {
2967
+ console.error(error.message);
2968
+ } else {
2969
+ console.error(error);
2970
+ }
2773
2971
  }
2774
2972
  };
2775
2973