create-stackkit-app 0.2.0 → 0.3.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 (65) hide show
  1. package/README.md +46 -31
  2. package/dist/lib/create-project.d.ts.map +1 -1
  3. package/dist/lib/create-project.js +179 -72
  4. package/dist/lib/create-project.js.map +1 -1
  5. package/dist/lib/template-composer.d.ts +17 -0
  6. package/dist/lib/template-composer.d.ts.map +1 -0
  7. package/dist/lib/template-composer.js +199 -0
  8. package/dist/lib/template-composer.js.map +1 -0
  9. package/package.json +5 -4
  10. package/templates/auth/authjs-express/config.json +20 -0
  11. package/templates/auth/authjs-express/files/lib/auth.ts +43 -0
  12. package/templates/auth/authjs-express/files/routes/auth.ts +12 -0
  13. package/templates/auth/authjs-express/lib/auth.ts +43 -0
  14. package/templates/auth/authjs-express/module.json +39 -0
  15. package/templates/auth/authjs-express/routes/auth.ts +12 -0
  16. package/templates/auth/authjs-nextjs/app/api/auth/[...nextauth]/route.ts +3 -0
  17. package/templates/auth/authjs-nextjs/config.json +19 -0
  18. package/templates/auth/authjs-nextjs/files/api/auth/[...nextauth]/route.ts +3 -0
  19. package/templates/auth/authjs-nextjs/files/lib/auth.ts +45 -0
  20. package/templates/auth/authjs-nextjs/lib/auth.ts +45 -0
  21. package/templates/auth/authjs-nextjs/module.json +38 -0
  22. package/templates/auth/better-auth-express/config.json +18 -0
  23. package/templates/auth/better-auth-express/src/lib/auth.ts +12 -0
  24. package/templates/auth/better-auth-express/src/routes/auth.ts +10 -0
  25. package/templates/auth/better-auth-nextjs/app/api/auth/[...all]/route.ts +4 -0
  26. package/templates/auth/better-auth-nextjs/config.json +18 -0
  27. package/templates/auth/better-auth-nextjs/lib/auth.ts +14 -0
  28. package/templates/auth/better-auth-react/config.json +15 -0
  29. package/templates/auth/better-auth-react/files/lib/auth-client.ts +9 -0
  30. package/templates/auth/better-auth-react/lib/auth-client.ts +9 -0
  31. package/templates/auth/better-auth-react/module.json +26 -0
  32. package/templates/auth/nextauth/app/api/auth/[...nextauth]/route.ts +3 -0
  33. package/templates/auth/nextauth/config.json +18 -0
  34. package/templates/auth/nextauth/lib/auth.ts +31 -0
  35. package/templates/bases/express-base/.env.example +2 -0
  36. package/templates/bases/express-base/package.json +23 -0
  37. package/templates/bases/express-base/src/index.ts +27 -0
  38. package/templates/bases/express-base/template.json +7 -0
  39. package/templates/bases/express-base/tsconfig.json +17 -0
  40. package/templates/bases/nextjs-base/.eslintrc.json +3 -0
  41. package/templates/bases/nextjs-base/app/globals.css +3 -0
  42. package/templates/{next-prisma-postgres-shadcn → bases/nextjs-base}/app/layout.tsx +3 -6
  43. package/templates/bases/nextjs-base/app/page.tsx +8 -0
  44. package/templates/{next-prisma-postgres-shadcn → bases/nextjs-base}/next.config.ts +1 -3
  45. package/templates/bases/nextjs-base/package.json +24 -0
  46. package/templates/bases/nextjs-base/template.json +7 -0
  47. package/templates/{next-prisma-postgres-shadcn → bases/nextjs-base}/tsconfig.json +1 -6
  48. package/templates/databases/prisma-mongodb/config.json +21 -0
  49. package/templates/{next-prisma-postgres-shadcn → databases/prisma-mongodb}/lib/db.ts +2 -3
  50. package/templates/databases/prisma-mongodb/prisma/schema.prisma +16 -0
  51. package/templates/databases/prisma-postgresql/config.json +22 -0
  52. package/templates/databases/prisma-postgresql/lib/db.ts +13 -0
  53. package/templates/databases/prisma-postgresql/prisma/schema.prisma +16 -0
  54. package/templates/next-prisma-postgres-shadcn/.env.example +0 -5
  55. package/templates/next-prisma-postgres-shadcn/.eslintrc.json +0 -7
  56. package/templates/next-prisma-postgres-shadcn/.prettierrc +0 -8
  57. package/templates/next-prisma-postgres-shadcn/README.md +0 -85
  58. package/templates/next-prisma-postgres-shadcn/app/api/health/route.ts +0 -25
  59. package/templates/next-prisma-postgres-shadcn/app/globals.css +0 -1
  60. package/templates/next-prisma-postgres-shadcn/app/page.tsx +0 -29
  61. package/templates/next-prisma-postgres-shadcn/lib/env.ts +0 -15
  62. package/templates/next-prisma-postgres-shadcn/package.json +0 -32
  63. package/templates/next-prisma-postgres-shadcn/prisma/schema.prisma +0 -20
  64. package/templates/next-prisma-postgres-shadcn/public/.gitkeep +0 -1
  65. package/templates/next-prisma-postgres-shadcn/template.json +0 -18
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TemplateComposer = void 0;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class TemplateComposer {
10
+ templatesDir;
11
+ constructor(templatesDir) {
12
+ this.templatesDir = templatesDir;
13
+ }
14
+ /**
15
+ * Compose a project from base + database + auth selections
16
+ */
17
+ async compose(targetDir, framework, database, auth) {
18
+ const configs = [];
19
+ const filesToCopy = [];
20
+ // 1. Load base framework template
21
+ const baseConfig = await this.loadConfig(path_1.default.join(this.templatesDir, 'bases', `${framework}-base`));
22
+ configs.push(baseConfig);
23
+ // Copy base files
24
+ const baseFiles = await this.getBaseFiles(framework);
25
+ filesToCopy.push(...baseFiles);
26
+ // 2. Load database configuration if not "none"
27
+ if (database !== 'none') {
28
+ const dbConfig = await this.loadConfig(path_1.default.join(this.templatesDir, 'databases', database));
29
+ // Check compatibility
30
+ if (dbConfig.compatibleWith?.frameworks &&
31
+ !dbConfig.compatibleWith.frameworks.includes(framework)) {
32
+ throw new Error(`${dbConfig.displayName} is not compatible with ${framework}`);
33
+ }
34
+ configs.push(dbConfig);
35
+ // Copy database files
36
+ const dbDir = path_1.default.join(this.templatesDir, 'databases', database);
37
+ const dbFiles = await this.collectFiles(dbDir);
38
+ filesToCopy.push(...dbFiles.map((f) => ({
39
+ source: f,
40
+ dest: path_1.default.join(targetDir, f.replace(dbDir + path_1.default.sep, '')),
41
+ })));
42
+ }
43
+ // 3. Load auth configuration if not "none"
44
+ if (auth !== 'none') {
45
+ const authKey = this.getAuthKey(framework, auth);
46
+ const authDir = path_1.default.join(this.templatesDir, 'auth', authKey);
47
+ if (await fs_extra_1.default.pathExists(authDir)) {
48
+ const authConfig = await this.loadConfig(authDir);
49
+ // Check compatibility
50
+ if (authConfig.compatibleWith?.frameworks &&
51
+ !authConfig.compatibleWith.frameworks.includes(framework)) {
52
+ throw new Error(`${authConfig.displayName} is not compatible with ${framework}`);
53
+ }
54
+ if (authConfig.compatibleWith?.databases &&
55
+ !authConfig.compatibleWith.databases.includes(database)) {
56
+ throw new Error(`${authConfig.displayName} is not compatible with ${database}`);
57
+ }
58
+ configs.push(authConfig);
59
+ // Copy auth files
60
+ const authFiles = await this.collectFiles(authDir);
61
+ filesToCopy.push(...authFiles.map((f) => ({
62
+ source: f,
63
+ dest: path_1.default.join(targetDir, f.replace(authDir + path_1.default.sep, '')),
64
+ })));
65
+ }
66
+ }
67
+ // 4. Merge all configurations
68
+ const mergedConfig = this.mergeConfigs(configs);
69
+ // 5. Copy all files
70
+ await this.copyFiles(filesToCopy);
71
+ // 6. Create/update package.json
72
+ await this.writePackageJson(targetDir, mergedConfig);
73
+ // 7. Create/update .env
74
+ await this.writeEnvFile(targetDir, mergedConfig);
75
+ }
76
+ async loadConfig(dir) {
77
+ const configPath = path_1.default.join(dir, 'config.json');
78
+ const templatePath = path_1.default.join(dir, 'template.json');
79
+ if (await fs_extra_1.default.pathExists(configPath)) {
80
+ return await fs_extra_1.default.readJson(configPath);
81
+ }
82
+ else if (await fs_extra_1.default.pathExists(templatePath)) {
83
+ return await fs_extra_1.default.readJson(templatePath);
84
+ }
85
+ throw new Error(`No configuration found in ${dir}`);
86
+ }
87
+ async getBaseFiles(framework) {
88
+ // For now, use existing complete template
89
+ // In future, this will use minimal base templates
90
+ const baseDir = path_1.default.join(this.templatesDir, 'next-prisma-postgres-shadcn');
91
+ const files = await this.collectFiles(baseDir);
92
+ return files.map((source) => ({
93
+ source,
94
+ dest: source.replace(baseDir, ''),
95
+ }));
96
+ }
97
+ async collectFiles(dir, exclude = ['config.json', 'template.json', 'node_modules']) {
98
+ const files = [];
99
+ if (!(await fs_extra_1.default.pathExists(dir))) {
100
+ return files;
101
+ }
102
+ const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
103
+ for (const entry of entries) {
104
+ if (exclude.includes(entry.name))
105
+ continue;
106
+ const fullPath = path_1.default.join(dir, entry.name);
107
+ if (entry.isDirectory()) {
108
+ const subFiles = await this.collectFiles(fullPath, exclude);
109
+ files.push(...subFiles);
110
+ }
111
+ else {
112
+ files.push(fullPath);
113
+ }
114
+ }
115
+ return files;
116
+ }
117
+ async copyFiles(files) {
118
+ for (const { source, dest } of files) {
119
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(dest));
120
+ await fs_extra_1.default.copy(source, dest, { overwrite: true });
121
+ }
122
+ }
123
+ mergeConfigs(configs) {
124
+ return configs.reduce((merged, config) => {
125
+ return {
126
+ ...merged,
127
+ dependencies: {
128
+ ...merged.dependencies,
129
+ ...config.dependencies,
130
+ },
131
+ devDependencies: {
132
+ ...merged.devDependencies,
133
+ ...config.devDependencies,
134
+ },
135
+ scripts: {
136
+ ...merged.scripts,
137
+ ...config.scripts,
138
+ },
139
+ env: {
140
+ ...merged.env,
141
+ ...config.env,
142
+ },
143
+ };
144
+ }, {});
145
+ }
146
+ async writePackageJson(targetDir, config) {
147
+ const pkgPath = path_1.default.join(targetDir, 'package.json');
148
+ let pkg = {};
149
+ if (await fs_extra_1.default.pathExists(pkgPath)) {
150
+ pkg = await fs_extra_1.default.readJson(pkgPath);
151
+ }
152
+ // Merge dependencies and scripts
153
+ if (config.dependencies) {
154
+ pkg.dependencies = { ...pkg.dependencies, ...config.dependencies };
155
+ }
156
+ if (config.devDependencies) {
157
+ pkg.devDependencies = { ...pkg.devDependencies, ...config.devDependencies };
158
+ }
159
+ if (config.scripts) {
160
+ pkg.scripts = { ...pkg.scripts, ...config.scripts };
161
+ }
162
+ await fs_extra_1.default.writeJson(pkgPath, pkg, { spaces: 2 });
163
+ }
164
+ async writeEnvFile(targetDir, config) {
165
+ if (!config.env || Object.keys(config.env).length === 0) {
166
+ return;
167
+ }
168
+ const envPath = path_1.default.join(targetDir, '.env');
169
+ const envExamplePath = path_1.default.join(targetDir, '.env.example');
170
+ const envContent = Object.entries(config.env)
171
+ .map(([key, value]) => `${key}="${value}"`)
172
+ .join('\n') + '\n';
173
+ // Append or create .env.example
174
+ if (await fs_extra_1.default.pathExists(envExamplePath)) {
175
+ const existing = await fs_extra_1.default.readFile(envExamplePath, 'utf-8');
176
+ if (!existing.includes(envContent)) {
177
+ await fs_extra_1.default.appendFile(envExamplePath, '\n' + envContent);
178
+ }
179
+ }
180
+ else {
181
+ await fs_extra_1.default.writeFile(envExamplePath, envContent);
182
+ }
183
+ // Don't overwrite existing .env, but create if missing
184
+ if (!(await fs_extra_1.default.pathExists(envPath))) {
185
+ await fs_extra_1.default.writeFile(envPath, envContent);
186
+ }
187
+ }
188
+ getAuthKey(framework, auth) {
189
+ // Map framework + auth to specific implementation
190
+ const mapping = {
191
+ 'nextjs-nextauth': 'nextauth',
192
+ 'nextjs-better-auth': 'better-auth-nextjs',
193
+ 'express-better-auth': 'better-auth-express',
194
+ };
195
+ return mapping[`${framework}-${auth}`] || auth;
196
+ }
197
+ }
198
+ exports.TemplateComposer = TemplateComposer;
199
+ //# sourceMappingURL=template-composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-composer.js","sourceRoot":"","sources":["../../src/lib/template-composer.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA0B;AAC1B,gDAAwB;AAmBxB,MAAa,gBAAgB;IACnB,YAAY,CAAS;IAE7B,YAAY,YAAoB;QAC9B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CACX,SAAiB,EACjB,SAAiB,EACjB,QAAgB,EAChB,IAAY;QAEZ,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,MAAM,WAAW,GAA4C,EAAE,CAAC;QAEhE,kCAAkC;QAClC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CACtC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,SAAS,OAAO,CAAC,CAC3D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEzB,kBAAkB;QAClB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACrD,WAAW,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QAE/B,+CAA+C;QAC/C,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;YAE5F,sBAAsB;YACtB,IACE,QAAQ,CAAC,cAAc,EAAE,UAAU;gBACnC,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EACvD,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,CAAC,WAAW,2BAA2B,SAAS,EAAE,CAAC,CAAC;YACjF,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEvB,sBAAsB;YACtB,MAAM,KAAK,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/C,WAAW,CAAC,IAAI,CACd,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACrB,MAAM,EAAE,CAAC;gBACT,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,cAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;aAC5D,CAAC,CAAC,CACJ,CAAC;QACJ,CAAC;QAED,2CAA2C;QAC3C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAE9D,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBAElD,sBAAsB;gBACtB,IACE,UAAU,CAAC,cAAc,EAAE,UAAU;oBACrC,CAAC,UAAU,CAAC,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EACzD,CAAC;oBACD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,WAAW,2BAA2B,SAAS,EAAE,CAAC,CAAC;gBACnF,CAAC;gBAED,IACE,UAAU,CAAC,cAAc,EAAE,SAAS;oBACpC,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EACvD,CAAC;oBACD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,WAAW,2BAA2B,QAAQ,EAAE,CAAC,CAAC;gBAClF,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAEzB,kBAAkB;gBAClB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;gBACnD,WAAW,CAAC,IAAI,CACd,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACvB,MAAM,EAAE,CAAC;oBACT,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,GAAG,cAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;iBAC9D,CAAC,CAAC,CACJ,CAAC;YACJ,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAEhD,oBAAoB;QACpB,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAElC,gCAAgC;QAChC,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAErD,wBAAwB;QACxB,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,GAAW;QAClC,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAErD,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACpC,OAAO,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7C,OAAO,MAAM,kBAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;IACtD,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,SAAiB;QAC1C,0CAA0C;QAC1C,kDAAkD;QAClD,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,6BAA6B,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAE/C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC5B,MAAM;YACN,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SAClC,CAAC,CAAC,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,GAAW,EACX,UAAoB,CAAC,aAAa,EAAE,eAAe,EAAE,cAAc,CAAC;QAEpE,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE3C,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAE5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5D,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,KAA8C;QACpE,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;YACrC,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACvC,MAAM,kBAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,OAAyB;QAC5C,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;YACvC,OAAO;gBACL,GAAG,MAAM;gBACT,YAAY,EAAE;oBACZ,GAAG,MAAM,CAAC,YAAY;oBACtB,GAAG,MAAM,CAAC,YAAY;iBACvB;gBACD,eAAe,EAAE;oBACf,GAAG,MAAM,CAAC,eAAe;oBACzB,GAAG,MAAM,CAAC,eAAe;iBAC1B;gBACD,OAAO,EAAE;oBACP,GAAG,MAAM,CAAC,OAAO;oBACjB,GAAG,MAAM,CAAC,OAAO;iBAClB;gBACD,GAAG,EAAE;oBACH,GAAG,MAAM,CAAC,GAAG;oBACb,GAAG,MAAM,CAAC,GAAG;iBACd;aACF,CAAC;QACJ,CAAC,EAAE,EAAoB,CAAC,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,SAAiB,EAAE,MAAsB;QACtE,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACrD,IAAI,GAAG,GAAQ,EAAE,CAAC;QAElB,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,GAAG,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QAED,iCAAiC;QACjC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,GAAG,CAAC,YAAY,GAAG,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QACrE,CAAC;QAED,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,GAAG,CAAC,eAAe,GAAG,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;QAC9E,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,GAAG,CAAC,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;QAED,MAAM,kBAAE,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,MAAsB;QAClE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAE5D,MAAM,UAAU,GACd,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;aACvB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAEvB,gCAAgC;QAChC,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,kBAAE,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACjD,CAAC;QAED,uDAAuD;QACvD,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACpC,MAAM,kBAAE,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,SAAiB,EAAE,IAAY;QAChD,kDAAkD;QAClD,MAAM,OAAO,GAA2B;YACtC,iBAAiB,EAAE,UAAU;YAC7B,oBAAoB,EAAE,oBAAoB;YAC1C,qBAAqB,EAAE,qBAAqB;SAC7C,CAAC;QAEF,OAAO,OAAO,CAAC,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC;IACjD,CAAC;CACF;AA1PD,4CA0PC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-stackkit-app",
3
- "version": "0.2.0",
4
- "description": "Create a new StackKit project with wizard-style setup",
3
+ "version": "0.3.1",
4
+ "description": "Create a new StackKit project with modular composition",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "create-stackkit": "./bin/create-stackkit.js"
@@ -25,7 +25,8 @@
25
25
  "dev": "tsc --watch",
26
26
  "build": "tsc",
27
27
  "clean": "rm -rf dist",
28
- "typecheck": "tsc --noEmit"
28
+ "typecheck": "tsc --noEmit",
29
+ "prepublishOnly": "npm run build && cp -r ../../templates ."
29
30
  },
30
31
  "keywords": [
31
32
  "create",
@@ -50,4 +51,4 @@
50
51
  "@types/validate-npm-package-name": "^4.0.2",
51
52
  "typescript": "^5.3.3"
52
53
  }
53
- }
54
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "authjs-express",
3
+ "displayName": "Auth.js (Express)",
4
+ "description": "Authentication with Auth.js for Express",
5
+ "frameworks": ["express"],
6
+ "dependencies": {
7
+ "@auth/express": "^0.7.6",
8
+ "@auth/core": "^0.37.4"
9
+ },
10
+ "envVars": {
11
+ "AUTH_SECRET": {
12
+ "value": "",
13
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32"
14
+ },
15
+ "AUTH_TRUST_HOST": {
16
+ "value": "true",
17
+ "description": "Trust the host header (required for Express)"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,43 @@
1
+ import { Auth } from '@auth/core';
2
+ import GitHub from '@auth/core/providers/github';
3
+ import Google from '@auth/core/providers/google';
4
+ import Credentials from '@auth/core/providers/credentials';
5
+
6
+ export const authConfig = {
7
+ secret: process.env.AUTH_SECRET,
8
+ trustHost: true,
9
+ providers: [
10
+ // GitHub OAuth Provider
11
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
12
+ // GitHub({
13
+ // clientId: process.env.GITHUB_ID!,
14
+ // clientSecret: process.env.GITHUB_SECRET!,
15
+ // }),
16
+
17
+ // Google OAuth Provider
18
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
19
+ // Google({
20
+ // clientId: process.env.GOOGLE_ID!,
21
+ // clientSecret: process.env.GOOGLE_SECRET!,
22
+ // }),
23
+
24
+ // Credentials Provider (email/password)
25
+ Credentials({
26
+ credentials: {
27
+ email: { label: 'Email', type: 'email' },
28
+ password: { label: 'Password', type: 'password' },
29
+ },
30
+ authorize: async (credentials) => {
31
+ // Add your own authentication logic here
32
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
33
+ return {
34
+ id: '1',
35
+ name: 'Demo User',
36
+ email: 'demo@example.com',
37
+ };
38
+ }
39
+ return null;
40
+ },
41
+ }),
42
+ ],
43
+ };
@@ -0,0 +1,12 @@
1
+ import { Router } from 'express';
2
+ import { Auth } from '@auth/core';
3
+ import { authConfig } from '../lib/auth';
4
+
5
+ const router = Router();
6
+
7
+ router.all('/auth/*', async (req, res) => {
8
+ const response = await Auth(req, authConfig);
9
+ return res.status(response.status).json(response.body);
10
+ });
11
+
12
+ export default router;
@@ -0,0 +1,43 @@
1
+ import { Auth } from '@auth/core';
2
+ import GitHub from '@auth/core/providers/github';
3
+ import Google from '@auth/core/providers/google';
4
+ import Credentials from '@auth/core/providers/credentials';
5
+
6
+ export const authConfig = {
7
+ secret: process.env.AUTH_SECRET,
8
+ trustHost: true,
9
+ providers: [
10
+ // GitHub OAuth Provider
11
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
12
+ // GitHub({
13
+ // clientId: process.env.GITHUB_ID!,
14
+ // clientSecret: process.env.GITHUB_SECRET!,
15
+ // }),
16
+
17
+ // Google OAuth Provider
18
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
19
+ // Google({
20
+ // clientId: process.env.GOOGLE_ID!,
21
+ // clientSecret: process.env.GOOGLE_SECRET!,
22
+ // }),
23
+
24
+ // Credentials Provider (email/password)
25
+ Credentials({
26
+ credentials: {
27
+ email: { label: 'Email', type: 'email' },
28
+ password: { label: 'Password', type: 'password' },
29
+ },
30
+ authorize: async (credentials) => {
31
+ // Add your own authentication logic here
32
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
33
+ return {
34
+ id: '1',
35
+ name: 'Demo User',
36
+ email: 'demo@example.com',
37
+ };
38
+ }
39
+ return null;
40
+ },
41
+ }),
42
+ ],
43
+ };
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "auth",
3
+ "displayName": "Auth.js (Express)",
4
+ "description": "Authentication with Auth.js for Express",
5
+ "category": "auth",
6
+ "supportedFrameworks": ["express"],
7
+ "dependencies": {
8
+ "@auth/express": "^0.7.6",
9
+ "@auth/core": "^0.37.4"
10
+ },
11
+ "envVars": [
12
+ {
13
+ "key": "AUTH_SECRET",
14
+ "value": "",
15
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32",
16
+ "required": true
17
+ },
18
+ {
19
+ "key": "AUTH_TRUST_HOST",
20
+ "value": "true",
21
+ "description": "Trust the host header (required for Express)",
22
+ "required": true
23
+ }
24
+ ],
25
+ "patches": [
26
+ {
27
+ "type": "create-file",
28
+ "description": "Create Auth.js configuration",
29
+ "source": "lib/auth.ts",
30
+ "destination": "src/lib/auth.ts"
31
+ },
32
+ {
33
+ "type": "create-file",
34
+ "description": "Create auth routes",
35
+ "source": "routes/auth.ts",
36
+ "destination": "src/routes/auth.ts"
37
+ }
38
+ ]
39
+ }
@@ -0,0 +1,12 @@
1
+ import { Router } from 'express';
2
+ import { Auth } from '@auth/core';
3
+ import { authConfig } from '../lib/auth';
4
+
5
+ const router = Router();
6
+
7
+ router.all('/auth/*', async (req, res) => {
8
+ const response = await Auth(req, authConfig);
9
+ return res.status(response.status).json(response.body);
10
+ });
11
+
12
+ export default router;
@@ -0,0 +1,3 @@
1
+ import { handlers } from '@/lib/auth';
2
+
3
+ export const { GET, POST } = handlers;
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "authjs-nextjs",
3
+ "displayName": "Auth.js v5 (Next.js)",
4
+ "description": "Modern authentication with Auth.js v5 (NextAuth successor)",
5
+ "frameworks": ["nextjs"],
6
+ "dependencies": {
7
+ "next-auth": "^5.0.0-beta.25"
8
+ },
9
+ "envVars": {
10
+ "AUTH_SECRET": {
11
+ "value": "",
12
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32"
13
+ },
14
+ "AUTH_URL": {
15
+ "value": "http://localhost:3000",
16
+ "description": "Canonical URL of your site (change in production)"
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ import { handlers } from '@/lib/auth';
2
+
3
+ export const { GET, POST } = handlers;
@@ -0,0 +1,45 @@
1
+ import NextAuth from 'next-auth';
2
+ import GitHub from 'next-auth/providers/github';
3
+ import Google from 'next-auth/providers/google';
4
+ import Credentials from 'next-auth/providers/credentials';
5
+
6
+ export const { handlers, signIn, signOut, auth } = NextAuth({
7
+ providers: [
8
+ // GitHub OAuth Provider
9
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
10
+ // GitHub({
11
+ // clientId: process.env.GITHUB_ID!,
12
+ // clientSecret: process.env.GITHUB_SECRET!,
13
+ // }),
14
+
15
+ // Google OAuth Provider
16
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
17
+ // Google({
18
+ // clientId: process.env.GOOGLE_ID!,
19
+ // clientSecret: process.env.GOOGLE_SECRET!,
20
+ // }),
21
+
22
+ // Credentials Provider (email/password)
23
+ Credentials({
24
+ credentials: {
25
+ email: { label: 'Email', type: 'email' },
26
+ password: { label: 'Password', type: 'password' },
27
+ },
28
+ authorize: async (credentials) => {
29
+ // Add your own authentication logic here
30
+ // This is just a demo - DO NOT use in production
31
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
32
+ return {
33
+ id: '1',
34
+ name: 'Demo User',
35
+ email: 'demo@example.com',
36
+ };
37
+ }
38
+ return null;
39
+ },
40
+ }),
41
+ ],
42
+ pages: {
43
+ signIn: '/auth/signin',
44
+ },
45
+ });
@@ -0,0 +1,45 @@
1
+ import NextAuth from 'next-auth';
2
+ import GitHub from 'next-auth/providers/github';
3
+ import Google from 'next-auth/providers/google';
4
+ import Credentials from 'next-auth/providers/credentials';
5
+
6
+ export const { handlers, signIn, signOut, auth } = NextAuth({
7
+ providers: [
8
+ // GitHub OAuth Provider
9
+ // Uncomment and add GITHUB_ID and GITHUB_SECRET to .env
10
+ // GitHub({
11
+ // clientId: process.env.GITHUB_ID!,
12
+ // clientSecret: process.env.GITHUB_SECRET!,
13
+ // }),
14
+
15
+ // Google OAuth Provider
16
+ // Uncomment and add GOOGLE_ID and GOOGLE_SECRET to .env
17
+ // Google({
18
+ // clientId: process.env.GOOGLE_ID!,
19
+ // clientSecret: process.env.GOOGLE_SECRET!,
20
+ // }),
21
+
22
+ // Credentials Provider (email/password)
23
+ Credentials({
24
+ credentials: {
25
+ email: { label: 'Email', type: 'email' },
26
+ password: { label: 'Password', type: 'password' },
27
+ },
28
+ authorize: async (credentials) => {
29
+ // Add your own authentication logic here
30
+ // This is just a demo - DO NOT use in production
31
+ if (credentials?.email === 'demo@example.com' && credentials?.password === 'demo') {
32
+ return {
33
+ id: '1',
34
+ name: 'Demo User',
35
+ email: 'demo@example.com',
36
+ };
37
+ }
38
+ return null;
39
+ },
40
+ }),
41
+ ],
42
+ pages: {
43
+ signIn: '/auth/signin',
44
+ },
45
+ });
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "auth",
3
+ "displayName": "Auth.js v5 (Next.js)",
4
+ "description": "Modern authentication with Auth.js v5 (NextAuth successor)",
5
+ "category": "auth",
6
+ "supportedFrameworks": ["nextjs"],
7
+ "dependencies": {
8
+ "next-auth": "^5.0.0-beta.25"
9
+ },
10
+ "envVars": [
11
+ {
12
+ "key": "AUTH_SECRET",
13
+ "value": "",
14
+ "description": "Secret for encrypting tokens. Generate with: openssl rand -base64 32",
15
+ "required": true
16
+ },
17
+ {
18
+ "key": "AUTH_URL",
19
+ "value": "http://localhost:3000",
20
+ "description": "Canonical URL of your site (change in production)",
21
+ "required": false
22
+ }
23
+ ],
24
+ "patches": [
25
+ {
26
+ "type": "create-file",
27
+ "description": "Create Auth.js configuration",
28
+ "source": "lib/auth.ts",
29
+ "destination": "{{lib}}/auth.ts"
30
+ },
31
+ {
32
+ "type": "create-file",
33
+ "description": "Create Auth.js API route",
34
+ "source": "api/auth/[...nextauth]/route.ts",
35
+ "destination": "{{router}}/api/auth/[...nextauth]/route.ts"
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "better-auth-express",
3
+ "displayName": "Better Auth (Express)",
4
+ "auth": "better-auth",
5
+ "compatibleWith": {
6
+ "frameworks": ["express"],
7
+ "databases": ["prisma-postgresql", "prisma-mongodb"]
8
+ },
9
+ "dependencies": {
10
+ "better-auth": "^1.1.4",
11
+ "@better-auth/prisma": "^1.1.4"
12
+ },
13
+ "env": {
14
+ "BETTER_AUTH_SECRET": "your-secret-here",
15
+ "BETTER_AUTH_URL": "http://localhost:3000"
16
+ },
17
+ "files": ["src/lib/auth.ts", "src/routes/auth.ts"]
18
+ }
@@ -0,0 +1,12 @@
1
+ import { prismaAdapter } from '@better-auth/prisma';
2
+ import { betterAuth } from 'better-auth';
3
+ import { prisma } from './db';
4
+
5
+ export const auth = betterAuth({
6
+ database: prismaAdapter(prisma, {
7
+ provider: 'postgresql',
8
+ }),
9
+ emailAndPassword: {
10
+ enabled: true,
11
+ },
12
+ });
@@ -0,0 +1,10 @@
1
+ import { Router } from 'express';
2
+ import { auth } from '../lib/auth';
3
+
4
+ const router = Router();
5
+
6
+ router.all('*', async (req, res) => {
7
+ return auth.handler(req, res);
8
+ });
9
+
10
+ export default router;
@@ -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);
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "better-auth-nextjs",
3
+ "displayName": "Better Auth (Next.js)",
4
+ "auth": "better-auth",
5
+ "compatibleWith": {
6
+ "frameworks": ["nextjs"],
7
+ "databases": ["prisma-postgresql", "prisma-mongodb"]
8
+ },
9
+ "dependencies": {
10
+ "better-auth": "^1.1.4",
11
+ "@better-auth/prisma": "^1.1.4"
12
+ },
13
+ "env": {
14
+ "BETTER_AUTH_SECRET": "your-secret-here",
15
+ "BETTER_AUTH_URL": "http://localhost:3000"
16
+ },
17
+ "files": ["lib/auth.ts", "app/api/auth/[...all]/route.ts"]
18
+ }
@@ -0,0 +1,14 @@
1
+ import { prismaAdapter } from '@better-auth/prisma';
2
+ import { betterAuth } from 'better-auth';
3
+ import { prisma } from './db';
4
+
5
+ export const auth = betterAuth({
6
+ database: prismaAdapter(prisma, {
7
+ provider: 'postgresql',
8
+ }),
9
+ emailAndPassword: {
10
+ enabled: true,
11
+ },
12
+ });
13
+
14
+ export type Session = typeof auth.$Infer.Session;