stackkit-cli 0.4.2 → 0.4.4

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 (137) hide show
  1. package/README.md +17 -10
  2. package/bin/stackkit.js +10 -1
  3. package/dist/commands/add.js +164 -25
  4. package/dist/commands/init.d.ts +1 -1
  5. package/dist/commands/init.js +34 -29
  6. package/dist/commands/list.js +12 -12
  7. package/dist/index.js +25 -23
  8. package/dist/types/index.d.ts +28 -16
  9. package/dist/utils/code-inject.d.ts +1 -1
  10. package/dist/utils/code-inject.js +6 -6
  11. package/dist/utils/detect.d.ts +1 -1
  12. package/dist/utils/detect.js +48 -44
  13. package/dist/utils/env-editor.js +20 -20
  14. package/dist/utils/files.js +4 -4
  15. package/dist/utils/json-editor.d.ts +3 -3
  16. package/dist/utils/json-editor.js +10 -14
  17. package/dist/utils/logger.d.ts +1 -1
  18. package/dist/utils/logger.js +8 -8
  19. package/dist/utils/package-manager.d.ts +2 -2
  20. package/dist/utils/package-manager.js +33 -26
  21. package/modules/auth/better-auth/files/api/auth/[...all]/route.ts +4 -0
  22. package/modules/auth/better-auth/files/lib/auth.ts +13 -0
  23. package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +63 -0
  24. package/modules/auth/better-auth/module.json +54 -0
  25. package/modules/auth/{clerk-express/files/lib → clerk/files/express}/auth.ts +1 -1
  26. package/modules/auth/{clerk-nextjs/files/lib → clerk/files/nextjs}/auth-provider.tsx +1 -1
  27. package/modules/auth/clerk/files/nextjs/middleware.ts +9 -0
  28. package/modules/auth/{clerk-react/files/lib → clerk/files/react}/auth-provider.tsx +2 -2
  29. package/modules/auth/clerk/module.json +115 -0
  30. package/modules/database/mongoose-mongodb/files/lib/db.ts +45 -7
  31. package/modules/database/mongoose-mongodb/files/models/User.ts +39 -0
  32. package/modules/database/mongoose-mongodb/module.json +59 -7
  33. package/modules/database/prisma/files/lib/prisma.ts +6 -0
  34. package/modules/database/prisma/files/prisma/schema.prisma +8 -0
  35. package/modules/database/prisma/files/prisma.config.ts +12 -0
  36. package/modules/database/prisma/module.json +140 -0
  37. package/package.json +1 -1
  38. package/templates/express/.env.example +3 -0
  39. package/templates/express/eslint.config.cjs +42 -0
  40. package/templates/express/package.json +33 -0
  41. package/templates/express/src/app.ts +51 -0
  42. package/templates/express/src/config/env.ts +12 -0
  43. package/templates/express/src/features/auth/auth.controller.ts +48 -0
  44. package/templates/express/src/features/auth/auth.route.ts +10 -0
  45. package/templates/express/src/features/auth/auth.service.ts +21 -0
  46. package/templates/express/src/middlewares/error.middleware.ts +18 -0
  47. package/templates/{bases/express-base → express}/src/server.ts +3 -3
  48. package/templates/express/template.json +40 -0
  49. package/templates/express/tsconfig.json +30 -0
  50. package/templates/{bases/nextjs-base → nextjs}/app/layout.tsx +1 -5
  51. package/templates/nextjs/app/page.tsx +57 -0
  52. package/templates/{bases/nextjs-base → nextjs}/package.json +2 -1
  53. package/templates/{bases/nextjs-base → nextjs}/template.json +13 -1
  54. package/templates/react-vite/.env.example +2 -0
  55. package/templates/react-vite/README.md +85 -0
  56. package/templates/react-vite/eslint.config.js +23 -0
  57. package/templates/{bases/react-vite-base → react-vite}/index.html +1 -0
  58. package/templates/{bases/react-vite-base → react-vite}/package.json +16 -2
  59. package/templates/react-vite/src/api/client.ts +47 -0
  60. package/templates/react-vite/src/api/services/user.service.ts +18 -0
  61. package/templates/react-vite/src/components/ErrorBoundary.tsx +51 -0
  62. package/templates/react-vite/src/components/Layout.tsx +13 -0
  63. package/templates/react-vite/src/components/Loading.tsx +8 -0
  64. package/templates/react-vite/src/components/SEO.tsx +49 -0
  65. package/templates/react-vite/src/config/constants.ts +5 -0
  66. package/templates/react-vite/src/hooks/index.ts +64 -0
  67. package/templates/react-vite/src/index.css +1 -0
  68. package/templates/react-vite/src/lib/queryClient.ts +12 -0
  69. package/templates/react-vite/src/main.tsx +22 -0
  70. package/templates/react-vite/src/pages/About.tsx +78 -0
  71. package/templates/react-vite/src/pages/Home.tsx +49 -0
  72. package/templates/react-vite/src/pages/NotFound.tsx +24 -0
  73. package/templates/react-vite/src/pages/UserProfile.tsx +40 -0
  74. package/templates/react-vite/src/router.tsx +33 -0
  75. package/templates/react-vite/src/types/api.d.ts +20 -0
  76. package/templates/react-vite/src/types/user.d.ts +6 -0
  77. package/templates/react-vite/src/utils/helpers.ts +51 -0
  78. package/templates/react-vite/src/utils/storage.ts +35 -0
  79. package/templates/react-vite/src/vite-env.d.ts +11 -0
  80. package/templates/react-vite/template.json +46 -0
  81. package/templates/react-vite/tsconfig.json +4 -0
  82. package/templates/react-vite/vite.config.ts +13 -0
  83. package/modules/auth/better-auth-express/files/lib/auth.ts +0 -16
  84. package/modules/auth/better-auth-express/files/routes/auth.ts +0 -12
  85. package/modules/auth/better-auth-express/module.json +0 -38
  86. package/modules/auth/better-auth-nextjs/files/api/auth/[...all]/route.ts +0 -5
  87. package/modules/auth/better-auth-nextjs/files/lib/auth.ts +0 -26
  88. package/modules/auth/better-auth-nextjs/module.json +0 -41
  89. package/modules/auth/better-auth-react/files/lib/auth-client.ts +0 -9
  90. package/modules/auth/better-auth-react/module.json +0 -26
  91. package/modules/auth/clerk-express/module.json +0 -20
  92. package/modules/auth/clerk-nextjs/files/middleware.ts +0 -9
  93. package/modules/auth/clerk-nextjs/module.json +0 -28
  94. package/modules/auth/clerk-react/module.json +0 -19
  95. package/modules/database/drizzle-postgresql/files/drizzle.config.ts +0 -10
  96. package/modules/database/drizzle-postgresql/files/lib/db.ts +0 -7
  97. package/modules/database/drizzle-postgresql/files/lib/schema.ts +0 -8
  98. package/modules/database/drizzle-postgresql/module.json +0 -35
  99. package/modules/database/prisma-mongodb/files/lib/db.ts +0 -9
  100. package/modules/database/prisma-mongodb/files/prisma/schema.prisma +0 -17
  101. package/modules/database/prisma-mongodb/module.json +0 -36
  102. package/modules/database/prisma-postgresql/files/lib/db.ts +0 -9
  103. package/modules/database/prisma-postgresql/files/prisma/schema.prisma +0 -17
  104. package/modules/database/prisma-postgresql/module.json +0 -36
  105. package/templates/bases/express-base/.env.example +0 -2
  106. package/templates/bases/express-base/package.json +0 -23
  107. package/templates/bases/express-base/src/app.ts +0 -34
  108. package/templates/bases/express-base/src/config/env.ts +0 -14
  109. package/templates/bases/express-base/src/middlewares/error.middleware.ts +0 -12
  110. package/templates/bases/express-base/template.json +0 -7
  111. package/templates/bases/express-base/tsconfig.json +0 -14
  112. package/templates/bases/nextjs-base/app/page.tsx +0 -65
  113. package/templates/bases/react-vite-base/README.md +0 -73
  114. package/templates/bases/react-vite-base/eslint.config.js +0 -23
  115. package/templates/bases/react-vite-base/src/App.css +0 -42
  116. package/templates/bases/react-vite-base/src/App.tsx +0 -35
  117. package/templates/bases/react-vite-base/src/index.css +0 -68
  118. package/templates/bases/react-vite-base/src/main.tsx +0 -10
  119. package/templates/bases/react-vite-base/template.json +0 -19
  120. package/templates/bases/react-vite-base/tsconfig.json +0 -7
  121. package/templates/bases/react-vite-base/vite.config.ts +0 -7
  122. /package/templates/{bases/nextjs-base → nextjs}/README.md +0 -0
  123. /package/templates/{bases/nextjs-base → nextjs}/app/favicon.ico +0 -0
  124. /package/templates/{bases/nextjs-base → nextjs}/app/globals.css +0 -0
  125. /package/templates/{bases/nextjs-base → nextjs}/eslint.config.mjs +0 -0
  126. /package/templates/{bases/nextjs-base → nextjs}/next.config.ts +0 -0
  127. /package/templates/{bases/nextjs-base → nextjs}/postcss.config.mjs +0 -0
  128. /package/templates/{bases/nextjs-base → nextjs}/public/file.svg +0 -0
  129. /package/templates/{bases/nextjs-base → nextjs}/public/globe.svg +0 -0
  130. /package/templates/{bases/nextjs-base → nextjs}/public/next.svg +0 -0
  131. /package/templates/{bases/nextjs-base → nextjs}/public/vercel.svg +0 -0
  132. /package/templates/{bases/nextjs-base → nextjs}/public/window.svg +0 -0
  133. /package/templates/{bases/nextjs-base → nextjs}/tsconfig.json +0 -0
  134. /package/templates/{bases/react-vite-base → react-vite}/public/vite.svg +0 -0
  135. /package/templates/{bases/react-vite-base → react-vite}/src/assets/react.svg +0 -0
  136. /package/templates/{bases/react-vite-base → react-vite}/tsconfig.app.json +0 -0
  137. /package/templates/{bases/react-vite-base → react-vite}/tsconfig.node.json +0 -0
@@ -3,19 +3,31 @@ export interface TemplateMetadata {
3
3
  displayName: string;
4
4
  description: string;
5
5
  tags: string[];
6
- defaultPackageManager: 'pnpm' | 'npm' | 'yarn';
6
+ defaultPackageManager: "pnpm" | "npm" | "yarn" | "bun";
7
7
  features: string[];
8
8
  }
9
9
  export interface ModuleMetadata {
10
10
  name: string;
11
11
  displayName: string;
12
12
  description: string;
13
- category: 'auth' | 'database' | 'ui' | 'other';
13
+ category: "auth" | "database" | "ui" | "other";
14
14
  supportedFrameworks: string[];
15
- dependencies: Record<string, string>;
16
- devDependencies?: Record<string, string>;
15
+ dependencies: {
16
+ common?: Record<string, string>;
17
+ providers?: Record<string, Record<string, string>>;
18
+ } | Record<string, string>;
19
+ devDependencies?: {
20
+ common?: Record<string, string>;
21
+ providers?: Record<string, Record<string, string>>;
22
+ } | Record<string, string>;
17
23
  envVars: EnvVar[];
18
24
  patches: ModulePatch[];
25
+ frameworkPatches?: Record<string, {
26
+ [file: string]: {
27
+ merge?: Record<string, unknown>;
28
+ };
29
+ }>;
30
+ postInstall?: string[];
19
31
  }
20
32
  export interface EnvVar {
21
33
  key: string;
@@ -24,33 +36,33 @@ export interface EnvVar {
24
36
  required: boolean;
25
37
  }
26
38
  export interface ModulePatch {
27
- type: 'create-file' | 'modify-json' | 'append-env' | 'inject-code';
39
+ type: "create-file" | "modify-json" | "append-env" | "inject-code";
28
40
  description: string;
29
- [key: string]: any;
41
+ [key: string]: unknown;
30
42
  }
31
43
  export interface CreateFilePatch extends ModulePatch {
32
- type: 'create-file';
44
+ type: "create-file";
33
45
  source: string;
34
46
  destination: string;
35
47
  condition?: {
36
- router?: 'app' | 'pages';
37
- language?: 'ts' | 'js';
48
+ router?: "app" | "pages";
49
+ language?: "ts" | "js";
38
50
  };
39
51
  }
40
52
  export interface ModifyJsonPatch extends ModulePatch {
41
- type: 'modify-json';
53
+ type: "modify-json";
42
54
  file: string;
43
55
  operations: {
44
56
  path: string;
45
- value: any;
57
+ value: unknown;
46
58
  merge?: boolean;
47
59
  }[];
48
60
  }
49
61
  export interface ProjectInfo {
50
- framework: 'nextjs' | 'express' | 'react' | 'react-vite' | 'unknown';
51
- router: 'app' | 'pages' | 'unknown';
52
- language: 'ts' | 'js';
53
- packageManager: 'npm' | 'yarn' | 'pnpm';
62
+ framework: "nextjs" | "express" | "react" | "react-vite" | "unknown";
63
+ router: "app" | "pages" | "unknown";
64
+ language: "ts" | "js";
65
+ packageManager: "npm" | "yarn" | "pnpm" | "bun";
54
66
  hasAuth: boolean;
55
67
  hasPrisma: boolean;
56
68
  hasDatabase: boolean;
@@ -61,5 +73,5 @@ export interface CLIOptions {
61
73
  dryRun?: boolean;
62
74
  yes?: boolean;
63
75
  noInstall?: boolean;
64
- pm?: 'npm' | 'yarn' | 'pnpm';
76
+ pm?: "npm" | "yarn" | "pnpm" | "bun";
65
77
  }
@@ -3,7 +3,7 @@ export interface CodeInjection {
3
3
  code: string;
4
4
  description: string;
5
5
  }
6
- export declare function injectCode(filePath: string, injection: CodeInjection, position: 'append' | 'prepend' | {
6
+ export declare function injectCode(filePath: string, injection: CodeInjection, position: "append" | "prepend" | {
7
7
  after: string;
8
8
  } | {
9
9
  before: string;
@@ -13,7 +13,7 @@ async function injectCode(filePath, injection, position, options = {}) {
13
13
  if (!(await fs_extra_1.default.pathExists(filePath))) {
14
14
  throw new Error(`File not found: ${filePath}`);
15
15
  }
16
- let content = await fs_extra_1.default.readFile(filePath, 'utf-8');
16
+ let content = await fs_extra_1.default.readFile(filePath, "utf-8");
17
17
  // Check if already injected
18
18
  const startMarker = CODE_MARKER_START(injection.id);
19
19
  if (content.includes(startMarker) && !options.force) {
@@ -26,13 +26,13 @@ async function injectCode(filePath, injection, position, options = {}) {
26
26
  // Prepare the code block with markers
27
27
  const markedCode = `\n${startMarker}\n${injection.code}\n${CODE_MARKER_END(injection.id)}\n`;
28
28
  // Inject based on position
29
- if (position === 'append') {
29
+ if (position === "append") {
30
30
  content += markedCode;
31
31
  }
32
- else if (position === 'prepend') {
32
+ else if (position === "prepend") {
33
33
  content = markedCode + content;
34
34
  }
35
- else if ('after' in position) {
35
+ else if ("after" in position) {
36
36
  const index = content.indexOf(position.after);
37
37
  if (index === -1) {
38
38
  throw new Error(`Could not find marker: ${position.after}`);
@@ -40,14 +40,14 @@ async function injectCode(filePath, injection, position, options = {}) {
40
40
  const insertPos = index + position.after.length;
41
41
  content = content.slice(0, insertPos) + markedCode + content.slice(insertPos);
42
42
  }
43
- else if ('before' in position) {
43
+ else if ("before" in position) {
44
44
  const index = content.indexOf(position.before);
45
45
  if (index === -1) {
46
46
  throw new Error(`Could not find marker: ${position.before}`);
47
47
  }
48
48
  content = content.slice(0, index) + markedCode + content.slice(index);
49
49
  }
50
- await fs_extra_1.default.writeFile(filePath, content, 'utf-8');
50
+ await fs_extra_1.default.writeFile(filePath, content, "utf-8");
51
51
  }
52
52
  function removeInjection(content, id) {
53
53
  const startMarker = CODE_MARKER_START(id);
@@ -1,4 +1,4 @@
1
- import { ProjectInfo } from '../types';
1
+ import { ProjectInfo } from "../types";
2
2
  export declare function detectProjectInfo(targetDir: string): Promise<ProjectInfo>;
3
3
  export declare function getRouterBasePath(projectInfo: ProjectInfo): string;
4
4
  export declare function getLibPath(projectInfo: ProjectInfo): string;
@@ -9,9 +9,9 @@ exports.getLibPath = getLibPath;
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  async function detectProjectInfo(targetDir) {
12
- const packageJsonPath = path_1.default.join(targetDir, 'package.json');
12
+ const packageJsonPath = path_1.default.join(targetDir, "package.json");
13
13
  if (!(await fs_extra_1.default.pathExists(packageJsonPath))) {
14
- throw new Error('No package.json found. This does not appear to be a Node.js project.');
14
+ throw new Error("No package.json found. This does not appear to be a Node.js project.");
15
15
  }
16
16
  const packageJson = await fs_extra_1.default.readJSON(packageJsonPath);
17
17
  // Detect framework
@@ -21,62 +21,66 @@ async function detectProjectInfo(targetDir) {
21
21
  const isVite = packageJson.dependencies?.vite || packageJson.devDependencies?.vite;
22
22
  let framework;
23
23
  if (isNextJs) {
24
- framework = 'nextjs';
24
+ framework = "nextjs";
25
25
  }
26
26
  else if (isExpress) {
27
- framework = 'express';
27
+ framework = "express";
28
28
  }
29
29
  else if (isReact && isVite) {
30
- framework = 'react-vite';
30
+ framework = "react-vite";
31
31
  }
32
32
  else if (isReact) {
33
- framework = 'react';
33
+ framework = "react";
34
34
  }
35
35
  else {
36
- framework = 'unknown';
36
+ framework = "unknown";
37
37
  }
38
- if (framework === 'unknown') {
39
- throw new Error('Only Next.js, Express, and React projects are currently supported.');
38
+ if (framework === "unknown") {
39
+ throw new Error("Only Next.js, Express, and React projects are currently supported.");
40
40
  }
41
41
  // Detect router type (only for Next.js)
42
- let router = 'unknown';
43
- if (framework === 'nextjs') {
44
- const appDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'app'));
45
- const pagesDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'pages'));
46
- const srcAppDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'src', 'app'));
47
- const srcPagesDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'src', 'pages'));
42
+ let router = "unknown";
43
+ if (framework === "nextjs") {
44
+ const appDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "app"));
45
+ const pagesDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "pages"));
46
+ const srcAppDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "src", "app"));
47
+ const srcPagesDirExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "src", "pages"));
48
48
  if (appDirExists || srcAppDirExists) {
49
- router = 'app';
49
+ router = "app";
50
50
  }
51
51
  else if (pagesDirExists || srcPagesDirExists) {
52
- router = 'pages';
52
+ router = "pages";
53
53
  }
54
54
  }
55
55
  // Detect TypeScript vs JavaScript
56
- const tsconfigExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'tsconfig.json'));
57
- const language = tsconfigExists ? 'ts' : 'js';
56
+ const tsconfigExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "tsconfig.json"));
57
+ const language = tsconfigExists ? "ts" : "js";
58
58
  // Detect package manager
59
- const yarnLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'yarn.lock'));
60
- const pnpmLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'pnpm-lock.yaml'));
61
- let packageManager = 'npm';
59
+ const yarnLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "yarn.lock"));
60
+ const pnpmLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "pnpm-lock.yaml"));
61
+ const bunLockExists = await fs_extra_1.default.pathExists(path_1.default.join(targetDir, "bun.lockb"));
62
+ let packageManager = "npm";
62
63
  if (pnpmLockExists) {
63
- packageManager = 'pnpm';
64
+ packageManager = "pnpm";
64
65
  }
65
66
  else if (yarnLockExists) {
66
- packageManager = 'yarn';
67
+ packageManager = "yarn";
68
+ }
69
+ else if (bunLockExists) {
70
+ packageManager = "bun";
67
71
  }
68
72
  // Check for existing integrations
69
- const hasAuth = !!(packageJson.dependencies?.['next-auth'] ||
70
- packageJson.dependencies?.['better-auth'] ||
71
- packageJson.dependencies?.['@auth/core'] ||
72
- packageJson.dependencies?.['@clerk/nextjs'] ||
73
- packageJson.dependencies?.['@kinde-oss/kinde-auth-nextjs'] ||
74
- packageJson.dependencies?.['passport']);
75
- const hasPrisma = !!(packageJson.dependencies?.['@prisma/client'] || packageJson.devDependencies?.['prisma']);
73
+ const hasAuth = !!(packageJson.dependencies?.["next-auth"] ||
74
+ packageJson.dependencies?.["better-auth"] ||
75
+ packageJson.dependencies?.["@auth/core"] ||
76
+ packageJson.dependencies?.["@clerk/nextjs"] ||
77
+ packageJson.dependencies?.["@kinde-oss/kinde-auth-nextjs"] ||
78
+ packageJson.dependencies?.["passport"]);
79
+ const hasPrisma = !!(packageJson.dependencies?.["@prisma/client"] || packageJson.devDependencies?.["prisma"]);
76
80
  const hasDatabase = hasPrisma ||
77
- !!(packageJson.dependencies?.['mongoose'] ||
78
- packageJson.dependencies?.['typeorm'] ||
79
- packageJson.dependencies?.['drizzle-orm']);
81
+ !!(packageJson.dependencies?.["mongoose"] ||
82
+ packageJson.dependencies?.["typeorm"] ||
83
+ packageJson.dependencies?.["drizzle-orm"]);
80
84
  return {
81
85
  framework,
82
86
  router,
@@ -89,19 +93,19 @@ async function detectProjectInfo(targetDir) {
89
93
  };
90
94
  }
91
95
  function getRouterBasePath(projectInfo) {
92
- const srcExists = fs_extra_1.default.existsSync(path_1.default.join(projectInfo.rootDir, 'src'));
93
- if (projectInfo.router === 'app') {
94
- return srcExists ? 'src/app' : 'app';
96
+ const srcExists = fs_extra_1.default.existsSync(path_1.default.join(projectInfo.rootDir, "src"));
97
+ if (projectInfo.router === "app") {
98
+ return srcExists ? "src/app" : "app";
95
99
  }
96
- else if (projectInfo.router === 'pages') {
97
- return srcExists ? 'src/pages' : 'pages';
100
+ else if (projectInfo.router === "pages") {
101
+ return srcExists ? "src/pages" : "pages";
98
102
  }
99
- throw new Error('Unknown router type');
103
+ throw new Error("Unknown router type");
100
104
  }
101
105
  function getLibPath(projectInfo) {
102
- if (projectInfo.framework === 'express') {
103
- return 'src/lib';
106
+ if (projectInfo.framework === "express") {
107
+ return "src/lib";
104
108
  }
105
- const srcExists = fs_extra_1.default.existsSync(path_1.default.join(projectInfo.rootDir, 'src'));
106
- return srcExists ? 'src/lib' : 'lib';
109
+ const srcExists = fs_extra_1.default.existsSync(path_1.default.join(projectInfo.rootDir, "src"));
110
+ return srcExists ? "src/lib" : "lib";
107
111
  }
@@ -8,28 +8,28 @@ exports.removeEnvVariables = removeEnvVariables;
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const logger_1 = require("./logger");
11
- const ENV_MARKER_START = '# StackKit:';
12
- const ENV_MARKER_END = '# End StackKit';
11
+ const ENV_MARKER_START = "# StackKit:";
12
+ const ENV_MARKER_END = "# End StackKit";
13
13
  async function addEnvVariables(projectRoot, variables, options = {}) {
14
- const envExamplePath = path_1.default.join(projectRoot, '.env.example');
15
- const envPath = path_1.default.join(projectRoot, '.env');
14
+ const envExamplePath = path_1.default.join(projectRoot, ".env.example");
15
+ const envPath = path_1.default.join(projectRoot, ".env");
16
16
  // Add to .env.example
17
- await appendToEnvFile(envExamplePath, variables, 'example', options);
17
+ await appendToEnvFile(envExamplePath, variables, "example", options);
18
18
  // Add to .env if it exists or create it
19
19
  const envExists = await fs_extra_1.default.pathExists(envPath);
20
20
  if (envExists || options.force) {
21
- await appendToEnvFile(envPath, variables, 'local', options);
21
+ await appendToEnvFile(envPath, variables, "local", options);
22
22
  }
23
- logger_1.logger.success('Environment variables added');
23
+ logger_1.logger.success("Environment variables added");
24
24
  }
25
25
  async function appendToEnvFile(filePath, variables, fileType, options = {}) {
26
- let content = '';
26
+ let content = "";
27
27
  if (await fs_extra_1.default.pathExists(filePath)) {
28
- content = await fs_extra_1.default.readFile(filePath, 'utf-8');
28
+ content = await fs_extra_1.default.readFile(filePath, "utf-8");
29
29
  }
30
30
  // Check if variables already exist
31
31
  const existingKeys = new Set();
32
- const lines = content.split('\n');
32
+ const lines = content.split("\n");
33
33
  for (const line of lines) {
34
34
  const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
35
35
  if (match) {
@@ -49,25 +49,25 @@ async function appendToEnvFile(filePath, variables, fileType, options = {}) {
49
49
  return;
50
50
  }
51
51
  // Ensure file ends with newline
52
- if (content && !content.endsWith('\n')) {
53
- content += '\n';
52
+ if (content && !content.endsWith("\n")) {
53
+ content += "\n";
54
54
  }
55
55
  // Add marker and variables
56
- content += '\n';
56
+ content += "\n";
57
57
  content += `${ENV_MARKER_START} Added by StackKit\n`;
58
58
  for (const variable of newVariables) {
59
59
  if (variable.description) {
60
60
  content += `# ${variable.description}\n`;
61
61
  }
62
- const value = fileType === 'example' ? variable.value || '' : variable.value || '';
62
+ const value = fileType === "example" ? variable.value || "" : variable.value || "";
63
63
  content += `${variable.key}=${value}\n`;
64
64
  }
65
65
  content += `${ENV_MARKER_END}\n`;
66
- await fs_extra_1.default.writeFile(filePath, content, 'utf-8');
66
+ await fs_extra_1.default.writeFile(filePath, content, "utf-8");
67
67
  }
68
68
  async function removeEnvVariables(projectRoot, keys) {
69
- const envExamplePath = path_1.default.join(projectRoot, '.env.example');
70
- const envPath = path_1.default.join(projectRoot, '.env');
69
+ const envExamplePath = path_1.default.join(projectRoot, ".env.example");
70
+ const envPath = path_1.default.join(projectRoot, ".env");
71
71
  await removeFromEnvFile(envExamplePath, keys);
72
72
  if (await fs_extra_1.default.pathExists(envPath)) {
73
73
  await removeFromEnvFile(envPath, keys);
@@ -77,8 +77,8 @@ async function removeFromEnvFile(filePath, keys) {
77
77
  if (!(await fs_extra_1.default.pathExists(filePath))) {
78
78
  return;
79
79
  }
80
- let content = await fs_extra_1.default.readFile(filePath, 'utf-8');
81
- const lines = content.split('\n');
80
+ const content = await fs_extra_1.default.readFile(filePath, "utf-8");
81
+ const lines = content.split("\n");
82
82
  const newLines = [];
83
83
  for (const line of lines) {
84
84
  const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
@@ -87,5 +87,5 @@ async function removeFromEnvFile(filePath, keys) {
87
87
  }
88
88
  newLines.push(line);
89
89
  }
90
- await fs_extra_1.default.writeFile(filePath, newLines.join('\n'), 'utf-8');
90
+ await fs_extra_1.default.writeFile(filePath, newLines.join("\n"), "utf-8");
91
91
  }
@@ -21,11 +21,11 @@ async function copyTemplate(templatePath, targetPath, projectName) {
21
21
  filter: (src) => {
22
22
  const basename = path_1.default.basename(src);
23
23
  // Skip template.json metadata file and node_modules
24
- return basename !== 'template.json' && basename !== 'node_modules';
24
+ return basename !== "template.json" && basename !== "node_modules";
25
25
  },
26
26
  });
27
27
  // Update package.json with project name
28
- const packageJsonPath = path_1.default.join(targetPath, 'package.json');
28
+ const packageJsonPath = path_1.default.join(targetPath, "package.json");
29
29
  if (await fs_extra_1.default.pathExists(packageJsonPath)) {
30
30
  const packageJson = await fs_extra_1.default.readJSON(packageJsonPath);
31
31
  packageJson.name = projectName;
@@ -40,10 +40,10 @@ async function createFile(targetPath, content, options = {}) {
40
40
  return;
41
41
  }
42
42
  await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
43
- await fs_extra_1.default.writeFile(targetPath, content, 'utf-8');
43
+ await fs_extra_1.default.writeFile(targetPath, content, "utf-8");
44
44
  }
45
45
  async function readFile(filePath) {
46
- return fs_extra_1.default.readFile(filePath, 'utf-8');
46
+ return fs_extra_1.default.readFile(filePath, "utf-8");
47
47
  }
48
48
  async function fileExists(filePath) {
49
49
  return fs_extra_1.default.pathExists(filePath);
@@ -1,8 +1,8 @@
1
- export declare function modifyJson(filePath: string, modifier: (json: any) => any, options?: {
1
+ export declare function modifyJson(filePath: string, modifier: (_json: Record<string, unknown>) => Record<string, unknown>, options?: {
2
2
  create?: boolean;
3
3
  force?: boolean;
4
4
  }): Promise<void>;
5
- export declare function addToPackageJson(filePath: string, section: 'dependencies' | 'devDependencies' | 'scripts', additions: Record<string, string>): Promise<void>;
6
- export declare function setJsonValue(filePath: string, path: string, value: any, options?: {
5
+ export declare function addToPackageJson(filePath: string, section: "dependencies" | "devDependencies" | "scripts", additions: Record<string, string>): Promise<void>;
6
+ export declare function setJsonValue(filePath: string, path: string, value: unknown, options?: {
7
7
  merge?: boolean;
8
8
  }): Promise<void>;
@@ -12,24 +12,20 @@ async function modifyJson(filePath, modifier, options = {}) {
12
12
  if (!exists && !options.create) {
13
13
  throw new Error(`File not found: ${filePath}`);
14
14
  }
15
- let json = {};
16
- if (exists) {
17
- json = await fs_extra_1.default.readJSON(filePath);
18
- }
19
- const modified = modifier(json);
15
+ const modified = modifier(exists ? await fs_extra_1.default.readJSON(filePath) : {});
20
16
  await fs_extra_1.default.writeJSON(filePath, modified, { spaces: 2 });
21
17
  }
22
18
  async function addToPackageJson(filePath, section, additions) {
23
- await modifyJson(filePath, (json) => {
24
- json[section] = json[section] || {};
25
- Object.assign(json[section], additions);
26
- return json;
19
+ await modifyJson(filePath, (_json) => {
20
+ _json[section] = _json[section] || {};
21
+ Object.assign(_json[section], additions);
22
+ return _json;
27
23
  });
28
24
  }
29
25
  async function setJsonValue(filePath, path, value, options = {}) {
30
- await modifyJson(filePath, (json) => {
31
- const keys = path.split('.');
32
- let current = json;
26
+ await modifyJson(filePath, (_json) => {
27
+ const keys = path.split(".");
28
+ let current = _json;
33
29
  for (let i = 0; i < keys.length - 1; i++) {
34
30
  const key = keys[i];
35
31
  if (!current[key]) {
@@ -38,12 +34,12 @@ async function setJsonValue(filePath, path, value, options = {}) {
38
34
  current = current[key];
39
35
  }
40
36
  const lastKey = keys[keys.length - 1];
41
- if (options.merge && typeof current[lastKey] === 'object' && typeof value === 'object') {
37
+ if (options.merge && typeof current[lastKey] === "object" && typeof value === "object") {
42
38
  current[lastKey] = { ...current[lastKey], ...value };
43
39
  }
44
40
  else {
45
41
  current[lastKey] = value;
46
42
  }
47
- return json;
43
+ return _json;
48
44
  });
49
45
  }
@@ -1,4 +1,4 @@
1
- import { Ora } from 'ora';
1
+ import { Ora } from "ora";
2
2
  export declare class Logger {
3
3
  private spinner;
4
4
  info(message: string): void;
@@ -11,22 +11,22 @@ class Logger {
11
11
  this.spinner = null;
12
12
  }
13
13
  info(message) {
14
- console.log(chalk_1.default.blue(''), message);
14
+ process.stdout.write(chalk_1.default.blue("") + " " + message + "\n");
15
15
  }
16
16
  success(message) {
17
- console.log(chalk_1.default.green(''), message);
17
+ process.stdout.write(chalk_1.default.green("") + " " + message + "\n");
18
18
  }
19
19
  error(message) {
20
- console.log(chalk_1.default.red(''), message);
20
+ process.stderr.write(chalk_1.default.red("") + " " + message + "\n");
21
21
  }
22
22
  warn(message) {
23
- console.log(chalk_1.default.yellow(''), message);
23
+ process.stdout.write(chalk_1.default.yellow("") + " " + message + "\n");
24
24
  }
25
25
  log(message) {
26
- console.log(message);
26
+ process.stdout.write(message + "\n");
27
27
  }
28
28
  newLine() {
29
- console.log();
29
+ process.stdout.write("\n");
30
30
  }
31
31
  startSpinner(text) {
32
32
  this.spinner = (0, ora_1.default)(text).start();
@@ -49,10 +49,10 @@ class Logger {
49
49
  }
50
50
  }
51
51
  header(text) {
52
- console.log(chalk_1.default.bold.cyan(text));
52
+ process.stdout.write(chalk_1.default.bold.cyan(text) + "\n");
53
53
  }
54
54
  footer() {
55
- console.log();
55
+ process.stdout.write("\n");
56
56
  }
57
57
  }
58
58
  exports.Logger = Logger;
@@ -1,5 +1,5 @@
1
- export type PackageManager = 'npm' | 'yarn' | 'pnpm';
1
+ export type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
2
2
  export declare function detectPackageManager(cwd: string): Promise<PackageManager>;
3
- export declare function installDependencies(cwd: string, pm: PackageManager, dev?: boolean): Promise<void>;
3
+ export declare function installDependencies(cwd: string, pm: PackageManager): Promise<void>;
4
4
  export declare function addDependencies(cwd: string, pm: PackageManager, packages: string[], dev?: boolean): Promise<void>;
5
5
  export declare function initGit(cwd: string): Promise<void>;
@@ -16,63 +16,70 @@ async function detectPackageManager(cwd) {
16
16
  return pm;
17
17
  }
18
18
  catch {
19
- return 'npm';
19
+ return "npm";
20
20
  }
21
21
  }
22
- async function installDependencies(cwd, pm, dev = false) {
22
+ async function installDependencies(cwd, pm) {
23
23
  const spinner = logger_1.logger.startSpinner(`Installing dependencies with ${pm}...`);
24
24
  try {
25
25
  const args = [];
26
- if (pm === 'npm') {
27
- args.push('install');
26
+ if (pm === "npm") {
27
+ args.push("install");
28
28
  }
29
- else if (pm === 'yarn') {
30
- args.push('install');
29
+ else if (pm === "yarn") {
30
+ args.push("install");
31
31
  }
32
- else if (pm === 'pnpm') {
33
- args.push('install');
32
+ else if (pm === "pnpm") {
33
+ args.push("install");
34
34
  }
35
- await (0, execa_1.default)(pm, args, { cwd, stdio: 'pipe' });
35
+ else if (pm === "bun") {
36
+ args.push("install");
37
+ }
38
+ await (0, execa_1.default)(pm, args, { cwd, stdio: "pipe" });
36
39
  spinner.succeed(`Dependencies installed successfully`);
37
40
  }
38
41
  catch (error) {
39
42
  spinner.fail(`Failed to install dependencies`);
40
- throw error;
43
+ throw new Error(`Failed to install dependencies: ${error}`);
41
44
  }
42
45
  }
43
46
  async function addDependencies(cwd, pm, packages, dev = false) {
44
47
  if (packages.length === 0)
45
48
  return;
46
- const spinner = logger_1.logger.startSpinner(`Adding ${dev ? 'dev ' : ''}dependencies: ${packages.join(', ')}...`);
49
+ const spinner = logger_1.logger.startSpinner(`Adding ${dev ? "dev " : ""}dependencies: ${packages.join(", ")}...`);
47
50
  try {
48
51
  const args = [];
49
- if (pm === 'npm') {
50
- args.push('install', dev ? '--save-dev' : '--save', ...packages);
52
+ if (pm === "npm") {
53
+ args.push("install", dev ? "--save-dev" : "--save", ...packages);
54
+ }
55
+ else if (pm === "yarn") {
56
+ args.push("add", dev ? "--dev" : "", ...packages);
51
57
  }
52
- else if (pm === 'yarn') {
53
- args.push('add', dev ? '--dev' : '', ...packages);
58
+ else if (pm === "pnpm") {
59
+ args.push("add", dev ? "-D" : "", ...packages);
54
60
  }
55
- else if (pm === 'pnpm') {
56
- args.push('add', dev ? '-D' : '', ...packages);
61
+ else if (pm === "bun") {
62
+ // bun uses `bun add` and `-d` for dev dependencies
63
+ args.push("add", ...(dev ? ["-d"] : []), ...packages);
57
64
  }
58
- await (0, execa_1.default)(pm, args.filter(Boolean), { cwd, stdio: 'pipe' });
65
+ await (0, execa_1.default)(pm, args.filter(Boolean), { cwd, stdio: "pipe" });
59
66
  spinner.succeed(`Dependencies added successfully`);
60
67
  }
61
68
  catch (error) {
62
69
  spinner.fail(`Failed to add dependencies`);
63
- throw error;
70
+ throw new Error(`Failed to add dependencies: ${error}`); // error is used here
64
71
  }
65
72
  }
66
73
  async function initGit(cwd) {
67
- const spinner = logger_1.logger.startSpinner('Initializing git repository...');
74
+ const spinner = logger_1.logger.startSpinner("Initializing git repository...");
68
75
  try {
69
- await (0, execa_1.default)('git', ['init'], { cwd });
70
- await (0, execa_1.default)('git', ['add', '.'], { cwd });
71
- await (0, execa_1.default)('git', ['commit', '-m', 'Initial commit from StackKit'], { cwd });
72
- spinner.succeed('Git repository initialized');
76
+ await (0, execa_1.default)("git", ["init"], { cwd });
77
+ await (0, execa_1.default)("git", ["add", "."], { cwd });
78
+ await (0, execa_1.default)("git", ["commit", "-m", "Initial commit from StackKit"], { cwd });
79
+ spinner.succeed("Git repository initialized");
73
80
  }
74
- catch (error) {
75
- spinner.fail('Failed to initialize git repository');
81
+ catch {
82
+ spinner.fail("Failed to initialize git repository");
76
83
  // Don't throw - git init is optional
77
84
  }
78
85
  }
@@ -0,0 +1,4 @@
1
+ import { auth } from "@/lib/auth";
2
+ import { toNextJsHandler } from "better-auth/next-js";
3
+
4
+ export const { GET, POST } = toNextJsHandler(auth);