stackkit 0.1.9 → 0.2.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.
- package/README.md +15 -24
- package/dist/cli/add.js +42 -107
- package/dist/cli/create.js +28 -15
- package/dist/cli/doctor.js +203 -21
- package/dist/cli/list.js +37 -1
- package/dist/index.js +104 -6
- package/dist/lib/discovery/module-discovery.d.ts +0 -7
- package/dist/lib/discovery/module-discovery.js +26 -23
- package/dist/lib/discovery/shared.d.ts +6 -0
- package/dist/lib/discovery/shared.js +50 -0
- package/dist/lib/framework/framework-utils.js +43 -3
- package/dist/lib/pm/package-manager.js +58 -31
- package/modules/auth/authjs/generator.json +1 -1
- package/modules/auth/better-auth/files/lib/auth.ts +5 -1
- package/package.json +1 -1
- package/templates/express/README.md +43 -0
- package/templates/express/template.json +9 -1
- package/templates/nextjs/.env.example +1 -0
- package/templates/nextjs/README.md +24 -1
- package/templates/nextjs/app/page.tsx +3 -3
- package/templates/nextjs/template.json +2 -0
- package/templates/react/README.md +35 -2
- package/templates/react/src/lib/queryClient.ts +2 -2
- package/templates/react/src/pages/Home.tsx +3 -3
- package/templates/react/src/utils/utils.ts +3 -0
- package/templates/react/template.json +2 -0
- package/templates/react/src/config/constants.ts +0 -5
- package/templates/react/src/hooks/index.ts +0 -64
- package/templates/react/src/utils/helpers.ts +0 -51
package/dist/cli/list.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.listCommand = listCommand;
|
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const module_discovery_1 = require("../lib/discovery/module-discovery");
|
|
11
|
+
const shared_1 = require("../lib/discovery/shared");
|
|
10
12
|
const logger_1 = require("../lib/ui/logger");
|
|
11
13
|
const package_root_1 = require("../lib/utils/package-root");
|
|
12
14
|
async function listCommand(options) {
|
|
@@ -34,6 +36,14 @@ async function listCommand(options) {
|
|
|
34
36
|
if (showModules) {
|
|
35
37
|
const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
|
|
36
38
|
const modules = await getAvailableModules(modulesDir);
|
|
39
|
+
// Discover modules to derive provider lists dynamically
|
|
40
|
+
let discovered;
|
|
41
|
+
try {
|
|
42
|
+
discovered = await (0, module_discovery_1.discoverModules)(path_1.default.join((0, package_root_1.getPackageRoot)(), "modules"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
discovered = { frameworks: [], databases: [], auth: [] };
|
|
46
|
+
}
|
|
37
47
|
if (modules.length > 0) {
|
|
38
48
|
hasModules = true;
|
|
39
49
|
logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
|
|
@@ -68,7 +78,33 @@ async function listCommand(options) {
|
|
|
68
78
|
: isLastMod
|
|
69
79
|
? "│ └──"
|
|
70
80
|
: "│ ├──";
|
|
71
|
-
|
|
81
|
+
// Compute provider names from discovered database choices
|
|
82
|
+
const choices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], "nextjs");
|
|
83
|
+
const prismaProviders = choices
|
|
84
|
+
.filter((c) => c.value.startsWith("prisma-"))
|
|
85
|
+
.map((c) => {
|
|
86
|
+
const m = c.name.match(/\(([^)]+)\)/);
|
|
87
|
+
return m ? m[1] : c.name;
|
|
88
|
+
});
|
|
89
|
+
const providersText = prismaProviders.length > 0
|
|
90
|
+
? prismaProviders.join(", ")
|
|
91
|
+
: (() => {
|
|
92
|
+
const detected = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)()).map((p) => {
|
|
93
|
+
if (p === "postgresql")
|
|
94
|
+
return "PostgreSQL";
|
|
95
|
+
if (p === "mongodb")
|
|
96
|
+
return "MongoDB";
|
|
97
|
+
if (p === "mysql")
|
|
98
|
+
return "MySQL";
|
|
99
|
+
if (p === "sqlite")
|
|
100
|
+
return "SQLite";
|
|
101
|
+
return p;
|
|
102
|
+
});
|
|
103
|
+
return detected.length > 0
|
|
104
|
+
? detected.join(", ")
|
|
105
|
+
: "PostgreSQL, MongoDB, MySQL, SQLite";
|
|
106
|
+
})();
|
|
107
|
+
logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
|
|
72
108
|
}
|
|
73
109
|
});
|
|
74
110
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,113 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
37
|
const commander_1 = require("commander");
|
|
5
|
-
const
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const fs_1 = require("fs");
|
|
40
|
+
const path_1 = require("path");
|
|
6
41
|
const add_1 = require("./cli/add");
|
|
42
|
+
const create_1 = require("./cli/create");
|
|
7
43
|
const doctor_1 = require("./cli/doctor");
|
|
8
44
|
const list_1 = require("./cli/list");
|
|
45
|
+
const shared_1 = require("./lib/discovery/shared");
|
|
9
46
|
const logger_1 = require("./lib/ui/logger");
|
|
10
|
-
const
|
|
11
|
-
const path_1 = require("path");
|
|
47
|
+
const package_root_1 = require("./lib/utils/package-root");
|
|
12
48
|
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
|
|
49
|
+
function buildOptionHints() {
|
|
50
|
+
try {
|
|
51
|
+
const pkgRoot = (0, package_root_1.getPackageRoot)();
|
|
52
|
+
const modulesDir = (0, path_1.join)(pkgRoot, "modules");
|
|
53
|
+
const dbs = [];
|
|
54
|
+
const auths = [];
|
|
55
|
+
if (fs.existsSync((0, path_1.join)(modulesDir, "database"))) {
|
|
56
|
+
for (const d of fs.readdirSync((0, path_1.join)(modulesDir, "database"))) {
|
|
57
|
+
const moduleJson = (0, path_1.join)(modulesDir, "database", d, "module.json");
|
|
58
|
+
if (fs.existsSync(moduleJson)) {
|
|
59
|
+
try {
|
|
60
|
+
const m = JSON.parse((0, fs_1.readFileSync)(moduleJson, "utf-8"));
|
|
61
|
+
if (m && m.name === "prisma") {
|
|
62
|
+
try {
|
|
63
|
+
const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
|
|
64
|
+
if (providers.length > 0) {
|
|
65
|
+
for (const p of providers)
|
|
66
|
+
dbs.push(`prisma-${p}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
dbs.push("prisma");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
dbs.push("prisma");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (m && m.name) {
|
|
77
|
+
dbs.push(m.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* ignore */
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (fs.existsSync((0, path_1.join)(modulesDir, "auth"))) {
|
|
87
|
+
for (const a of fs.readdirSync((0, path_1.join)(modulesDir, "auth"))) {
|
|
88
|
+
const moduleJson = (0, path_1.join)(modulesDir, "auth", a, "module.json");
|
|
89
|
+
if (fs.existsSync(moduleJson)) {
|
|
90
|
+
try {
|
|
91
|
+
const m = JSON.parse((0, fs_1.readFileSync)(moduleJson, "utf-8"));
|
|
92
|
+
if (m && m.name)
|
|
93
|
+
auths.push(m.name);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* ignore */
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
databaseHint: dbs.length > 0 ? dbs.join(", ") : "prisma, mongoose, none",
|
|
103
|
+
authHint: auths.length > 0 ? auths.join(", ") : "better-auth, authjs, none",
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return { databaseHint: "prisma, mongoose, none", authHint: "better-auth, authjs, none" };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const hints = buildOptionHints();
|
|
13
111
|
const program = new commander_1.Command();
|
|
14
112
|
program
|
|
15
113
|
.name("stackkit")
|
|
@@ -37,9 +135,9 @@ program
|
|
|
37
135
|
.description("Create a new StackKit project")
|
|
38
136
|
.usage("[project-name] [options]")
|
|
39
137
|
.option("-f, --framework <framework>", "Framework: nextjs, express, react")
|
|
40
|
-
.option("-d, --database <database>",
|
|
41
|
-
.option("--prisma-provider <provider>", "Prisma provider
|
|
42
|
-
.option("-a, --auth <auth>",
|
|
138
|
+
.option("-d, --database <database>", `Database: ${hints.databaseHint}`)
|
|
139
|
+
.option("--prisma-provider <provider>", "Prisma provider")
|
|
140
|
+
.option("-a, --auth <auth>", `Auth: ${hints.authHint}`)
|
|
43
141
|
.option("-l, --language <language>", "Language: typescript, javascript")
|
|
44
142
|
.option("-p, --package-manager <pm>", "Package manager: pnpm, npm, yarn, bun")
|
|
45
143
|
.option("--skip-install", "Skip dependency installation")
|
|
@@ -38,13 +38,6 @@ export declare function getValidDatabaseOptions(databases: ModuleMetadata[]): st
|
|
|
38
38
|
* Get valid auth options for CLI
|
|
39
39
|
*/
|
|
40
40
|
export declare function getValidAuthOptions(authModules: ModuleMetadata[]): string[];
|
|
41
|
-
/**
|
|
42
|
-
* Parse database option into database name and provider
|
|
43
|
-
*/
|
|
44
|
-
export declare function parseDatabaseOption(dbOption: string): {
|
|
45
|
-
database: string;
|
|
46
|
-
provider?: string;
|
|
47
|
-
};
|
|
48
41
|
/**
|
|
49
42
|
* Get compatible auth options for given framework and database
|
|
50
43
|
*/
|
|
@@ -6,12 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.discoverModules = discoverModules;
|
|
7
7
|
exports.getValidDatabaseOptions = getValidDatabaseOptions;
|
|
8
8
|
exports.getValidAuthOptions = getValidAuthOptions;
|
|
9
|
-
exports.parseDatabaseOption = parseDatabaseOption;
|
|
10
9
|
exports.getCompatibleAuthOptions = getCompatibleAuthOptions;
|
|
11
10
|
exports.getDatabaseChoices = getDatabaseChoices;
|
|
12
11
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
12
|
const path_1 = __importDefault(require("path"));
|
|
14
13
|
const package_root_1 = require("../utils/package-root");
|
|
14
|
+
const shared_1 = require("./shared");
|
|
15
15
|
/**
|
|
16
16
|
* Discover all available modules from the modules directory
|
|
17
17
|
*/
|
|
@@ -119,11 +119,17 @@ function getValidDatabaseOptions(databases) {
|
|
|
119
119
|
const options = ["none"];
|
|
120
120
|
for (const db of databases) {
|
|
121
121
|
if (db.name === "prisma") {
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
const providers = (0, shared_1.getPrismaProvidersFromGenerator)();
|
|
123
|
+
if (providers.length > 0) {
|
|
124
|
+
for (const p of providers)
|
|
125
|
+
options.push(`prisma-${p}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
options.push("prisma");
|
|
129
|
+
}
|
|
124
130
|
}
|
|
125
131
|
else if (db.name === "mongoose") {
|
|
126
|
-
options.push("mongoose"
|
|
132
|
+
options.push("mongoose");
|
|
127
133
|
}
|
|
128
134
|
else {
|
|
129
135
|
// For other databases, add the name directly
|
|
@@ -142,22 +148,7 @@ function getValidAuthOptions(authModules) {
|
|
|
142
148
|
}
|
|
143
149
|
return options;
|
|
144
150
|
}
|
|
145
|
-
|
|
146
|
-
* Parse database option into database name and provider
|
|
147
|
-
*/
|
|
148
|
-
function parseDatabaseOption(dbOption) {
|
|
149
|
-
if (dbOption === "none") {
|
|
150
|
-
return { database: "none" };
|
|
151
|
-
}
|
|
152
|
-
if (dbOption.startsWith("prisma-")) {
|
|
153
|
-
const provider = dbOption.split("-")[1];
|
|
154
|
-
return { database: "prisma", provider };
|
|
155
|
-
}
|
|
156
|
-
if (dbOption === "mongoose" || dbOption === "mongoose") {
|
|
157
|
-
return { database: "mongoose" };
|
|
158
|
-
}
|
|
159
|
-
return { database: dbOption };
|
|
160
|
-
}
|
|
151
|
+
// parseDatabaseOption moved to shared helpers
|
|
161
152
|
/**
|
|
162
153
|
* Get compatible auth options for given framework and database
|
|
163
154
|
*/
|
|
@@ -168,11 +159,13 @@ function getCompatibleAuthOptions(authModules, framework, database) {
|
|
|
168
159
|
if (auth.supportedFrameworks && !auth.supportedFrameworks.includes(framework)) {
|
|
169
160
|
continue;
|
|
170
161
|
}
|
|
162
|
+
// Normalize database option (handle prisma-<provider> values)
|
|
163
|
+
const parsedDb = (0, shared_1.parseDatabaseOption)(database || "").database;
|
|
171
164
|
// Special compatibility rules
|
|
172
|
-
if (auth.name === "authjs" && (
|
|
165
|
+
if (auth.name === "authjs" && (parsedDb !== "prisma" || framework !== "nextjs")) {
|
|
173
166
|
continue;
|
|
174
167
|
}
|
|
175
|
-
if (auth.name === "better-auth" &&
|
|
168
|
+
if (auth.name === "better-auth" && parsedDb === "none" && framework !== "react") {
|
|
176
169
|
continue;
|
|
177
170
|
}
|
|
178
171
|
compatible.push({
|
|
@@ -195,7 +188,17 @@ function getDatabaseChoices(databases, framework) {
|
|
|
195
188
|
continue;
|
|
196
189
|
}
|
|
197
190
|
if (db.name === "prisma") {
|
|
198
|
-
|
|
191
|
+
const providers = (0, shared_1.getPrismaProvidersFromGenerator)();
|
|
192
|
+
if (providers.length > 0) {
|
|
193
|
+
for (const p of providers)
|
|
194
|
+
choices.push({
|
|
195
|
+
name: `Prisma (${p.charAt(0).toUpperCase() + p.slice(1)})`,
|
|
196
|
+
value: `prisma-${p}`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
choices.push({ name: "Prisma", value: "prisma" });
|
|
201
|
+
}
|
|
199
202
|
}
|
|
200
203
|
else if (db.name === "mongoose") {
|
|
201
204
|
choices.push({ name: "Mongoose", value: "mongoose" });
|
|
@@ -0,0 +1,50 @@
|
|
|
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.parseDatabaseOption = parseDatabaseOption;
|
|
7
|
+
exports.getPrismaProvidersFromGenerator = getPrismaProvidersFromGenerator;
|
|
8
|
+
exports.isPrismaOption = isPrismaOption;
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const package_root_1 = require("../utils/package-root");
|
|
11
|
+
function parseDatabaseOption(dbOption) {
|
|
12
|
+
if (!dbOption)
|
|
13
|
+
return { database: "none" };
|
|
14
|
+
if (dbOption === "none")
|
|
15
|
+
return { database: "none" };
|
|
16
|
+
if (dbOption.startsWith("prisma-")) {
|
|
17
|
+
const provider = dbOption.split("-")[1];
|
|
18
|
+
return { database: "prisma", provider };
|
|
19
|
+
}
|
|
20
|
+
if (dbOption === "prisma")
|
|
21
|
+
return { database: "prisma" };
|
|
22
|
+
if (dbOption === "mongoose")
|
|
23
|
+
return { database: "mongoose" };
|
|
24
|
+
return { database: dbOption };
|
|
25
|
+
}
|
|
26
|
+
function getPrismaProvidersFromGenerator(modulesDir) {
|
|
27
|
+
const pkgRoot = modulesDir || (0, package_root_1.getPackageRoot)();
|
|
28
|
+
const genPath = path_1.default.join(pkgRoot, "modules", "database", "prisma", "generator.json");
|
|
29
|
+
try {
|
|
30
|
+
const gen = require(genPath);
|
|
31
|
+
const providers = new Set();
|
|
32
|
+
if (Array.isArray(gen.operations)) {
|
|
33
|
+
for (const op of gen.operations) {
|
|
34
|
+
if (op.condition && op.condition.prismaProvider)
|
|
35
|
+
providers.add(String(op.condition.prismaProvider));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return Array.from(providers);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isPrismaOption(value) {
|
|
45
|
+
if (!value)
|
|
46
|
+
return false;
|
|
47
|
+
if (value === "prisma")
|
|
48
|
+
return true;
|
|
49
|
+
return value.startsWith("prisma-");
|
|
50
|
+
}
|
|
@@ -45,15 +45,55 @@ class FrameworkUtils {
|
|
|
45
45
|
this.frameworkConfigs.set(frameworkName, config);
|
|
46
46
|
return config;
|
|
47
47
|
}
|
|
48
|
-
//
|
|
48
|
+
// Derive compatibility dynamically from available modules if possible
|
|
49
49
|
const defaultConfig = {
|
|
50
50
|
name: frameworkName,
|
|
51
51
|
displayName: frameworkName.charAt(0).toUpperCase() + frameworkName.slice(1),
|
|
52
52
|
compatibility: {
|
|
53
|
-
databases: [
|
|
54
|
-
auth: [
|
|
53
|
+
databases: [],
|
|
54
|
+
auth: [],
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
|
+
try {
|
|
58
|
+
const modulesDir = path.join(templatesDir, "..", "modules");
|
|
59
|
+
const dbDir = path.join(modulesDir, "database");
|
|
60
|
+
const authDir = path.join(modulesDir, "auth");
|
|
61
|
+
if (await fs.pathExists(dbDir)) {
|
|
62
|
+
const dbs = await fs.readdir(dbDir);
|
|
63
|
+
for (const d of dbs) {
|
|
64
|
+
const moduleJson = path.join(dbDir, d, "module.json");
|
|
65
|
+
if (await fs.pathExists(moduleJson)) {
|
|
66
|
+
try {
|
|
67
|
+
const m = await fs.readJson(moduleJson);
|
|
68
|
+
if (m && m.name)
|
|
69
|
+
defaultConfig.compatibility.databases.push(m.name);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// ignore malformed
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (await fs.pathExists(authDir)) {
|
|
78
|
+
const auths = await fs.readdir(authDir);
|
|
79
|
+
for (const a of auths) {
|
|
80
|
+
const moduleJson = path.join(authDir, a, "module.json");
|
|
81
|
+
if (await fs.pathExists(moduleJson)) {
|
|
82
|
+
try {
|
|
83
|
+
const m = await fs.readJson(moduleJson);
|
|
84
|
+
if (m && m.name)
|
|
85
|
+
defaultConfig.compatibility.auth.push(m.name);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// ignore malformed
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// ignore discovery errors and leave empty lists
|
|
96
|
+
}
|
|
57
97
|
this.frameworkConfigs.set(frameworkName, defaultConfig);
|
|
58
98
|
return defaultConfig;
|
|
59
99
|
}
|
|
@@ -20,41 +20,32 @@ async function detectPackageManager(cwd) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
async function installDependencies(cwd, pm) {
|
|
23
|
-
const args = [];
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
else if (pm === "yarn") {
|
|
28
|
-
args.push("install");
|
|
29
|
-
}
|
|
30
|
-
else if (pm === "pnpm") {
|
|
31
|
-
args.push("install");
|
|
32
|
-
}
|
|
33
|
-
else if (pm === "bun") {
|
|
34
|
-
args.push("install");
|
|
35
|
-
}
|
|
36
|
-
await (0, execa_1.default)(pm, args, { cwd, stdio: "pipe" });
|
|
23
|
+
const args = ["install"];
|
|
24
|
+
const stdio = "pipe";
|
|
25
|
+
await (0, execa_1.default)(pm, args, { cwd, stdio });
|
|
37
26
|
}
|
|
38
27
|
async function addDependencies(cwd, pm, packages, dev = false) {
|
|
39
28
|
if (packages.length === 0)
|
|
40
29
|
return;
|
|
41
30
|
const spinner = logger_1.logger.startSpinner(`Adding ${dev ? "dev " : ""}dependencies: ${packages.join(", ")}...`);
|
|
42
31
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
const stdio = "pipe";
|
|
33
|
+
let args = [];
|
|
34
|
+
switch (pm) {
|
|
35
|
+
case "npm":
|
|
36
|
+
args = ["install", ...(dev ? ["--save-dev"] : []), ...packages];
|
|
37
|
+
break;
|
|
38
|
+
case "yarn":
|
|
39
|
+
args = ["add", ...(dev ? ["--dev"] : []), ...packages];
|
|
40
|
+
break;
|
|
41
|
+
case "pnpm":
|
|
42
|
+
args = ["add", ...(dev ? ["-D"] : []), ...packages];
|
|
43
|
+
break;
|
|
44
|
+
case "bun":
|
|
45
|
+
args = ["add", ...(dev ? ["-d"] : []), ...packages];
|
|
46
|
+
break;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
args.push("add", dev ? "--dev" : "", ...packages);
|
|
49
|
-
}
|
|
50
|
-
else if (pm === "pnpm") {
|
|
51
|
-
args.push("add", dev ? "-D" : "", ...packages);
|
|
52
|
-
}
|
|
53
|
-
else if (pm === "bun") {
|
|
54
|
-
// bun uses `bun add` and `-d` for dev dependencies
|
|
55
|
-
args.push("add", ...(dev ? ["-d"] : []), ...packages);
|
|
56
|
-
}
|
|
57
|
-
await (0, execa_1.default)(pm, args.filter(Boolean), { cwd, stdio: "pipe" });
|
|
48
|
+
await (0, execa_1.default)(pm, args, { cwd, stdio });
|
|
58
49
|
spinner.succeed(`Dependencies added successfully`);
|
|
59
50
|
}
|
|
60
51
|
catch (error) {
|
|
@@ -63,7 +54,43 @@ async function addDependencies(cwd, pm, packages, dev = false) {
|
|
|
63
54
|
}
|
|
64
55
|
}
|
|
65
56
|
async function initGit(cwd) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
const spinner = logger_1.logger.startSpinner("Initializing git repository...");
|
|
58
|
+
const run = async (stdio) => {
|
|
59
|
+
await (0, execa_1.default)("git", ["init"], { cwd, stdio });
|
|
60
|
+
await (0, execa_1.default)("git", ["add", "."], { cwd, stdio });
|
|
61
|
+
await (0, execa_1.default)("git", ["commit", "-m", "Initial commit from StackKit"], { cwd, stdio });
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
await run("pipe");
|
|
65
|
+
spinner.succeed("Git repository initialized");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const err = error;
|
|
70
|
+
spinner.fail(`Git init failed: ${err.message}`);
|
|
71
|
+
const isENOBUFS = (e) => {
|
|
72
|
+
if (!e || typeof e !== "object")
|
|
73
|
+
return false;
|
|
74
|
+
const obj = e;
|
|
75
|
+
return (obj.code === "ENOBUFS" ||
|
|
76
|
+
obj.errno === "ENOBUFS" ||
|
|
77
|
+
String(obj.message ?? "").includes("ENOBUFS"));
|
|
78
|
+
};
|
|
79
|
+
if (isENOBUFS(err)) {
|
|
80
|
+
logger_1.logger.warn("ENOBUFS detected; skipping git initialization.");
|
|
81
|
+
logger_1.logger.info("Skipped git initialization due to system resource limits.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
await run("inherit");
|
|
86
|
+
spinner.succeed("Git repository initialized (fallback)");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
catch (fallbackErr) {
|
|
90
|
+
const fe = fallbackErr;
|
|
91
|
+
logger_1.logger.warn(`Git init fallback failed: ${fe.message}`);
|
|
92
|
+
spinner.fail("Git initialization skipped");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
69
96
|
}
|
|
@@ -30,7 +30,9 @@ return betterAuth({
|
|
|
30
30
|
database: mongodbAdapter(db, { client }),
|
|
31
31
|
{{/case}}
|
|
32
32
|
{{/switch}}
|
|
33
|
-
|
|
33
|
+
baseURL: process.env.BETTER_AUTH_URL,
|
|
34
|
+
secret: process.env.BETTER_AUTH_SECRET,
|
|
35
|
+
trustedOrigins: [process.env.APP_URL],
|
|
34
36
|
user: {
|
|
35
37
|
additionalFields: {
|
|
36
38
|
role: {
|
|
@@ -84,9 +86,11 @@ return betterAuth({
|
|
|
84
86
|
session: {
|
|
85
87
|
cookieCache: {
|
|
86
88
|
enabled: true,
|
|
89
|
+
maxAge: 60 * 60 * 24 * 7,
|
|
87
90
|
},
|
|
88
91
|
expiresIn: 60 * 60 * 24 * 7,
|
|
89
92
|
updateAge: 60 * 60 * 24,
|
|
93
|
+
cookieName: "better-auth.session_token",
|
|
90
94
|
}
|
|
91
95
|
})
|
|
92
96
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Express Template
|
|
2
|
+
|
|
3
|
+
Production-ready Express (TypeScript) starter for building REST APIs and backend services.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 18+ (LTS recommended)
|
|
8
|
+
- pnpm or npm
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
Install dependencies and start the development server:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# using pnpm (recommended)
|
|
16
|
+
pnpm install
|
|
17
|
+
pnpm dev
|
|
18
|
+
|
|
19
|
+
# or using npm
|
|
20
|
+
npm install
|
|
21
|
+
npm run dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Scripts
|
|
25
|
+
|
|
26
|
+
- `npm run dev` - Start development server
|
|
27
|
+
- `npm run build` - Build TypeScript
|
|
28
|
+
- `npm start` - Start production server
|
|
29
|
+
|
|
30
|
+
## Environment
|
|
31
|
+
|
|
32
|
+
Use a `.env` file or environment variables for configuration. See `.env.example` for available keys.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Generated with StackKit
|
|
37
|
+
|
|
38
|
+
This project was scaffolded using **StackKit** — a CLI toolkit for building production-ready applications.
|
|
39
|
+
|
|
40
|
+
- Generated via: `npx stackkit@latest create`
|
|
41
|
+
|
|
42
|
+
Learn more about StackKit:
|
|
43
|
+
https://github.com/tariqul420/stackkit
|
|
@@ -7,7 +7,15 @@
|
|
|
7
7
|
"databases": ["prisma", "mongoose"],
|
|
8
8
|
"auth": ["better-auth"]
|
|
9
9
|
},
|
|
10
|
-
"files": [
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
".env.example",
|
|
13
|
+
".gitignore",
|
|
14
|
+
"eslint.config.cjs",
|
|
15
|
+
"package.json",
|
|
16
|
+
"README.md",
|
|
17
|
+
"tsconfig.json"
|
|
18
|
+
],
|
|
11
19
|
"scripts": {
|
|
12
20
|
"dev": "tsx watch src/server.ts",
|
|
13
21
|
"build": "tsc",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|