stackkit 0.1.5 → 0.1.7
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/dist/cli/add.js +113 -83
- package/dist/cli/create.js +4 -2
- package/dist/cli/doctor.js +17 -4
- package/dist/index.js +4 -1
- package/dist/lib/generation/code-generator.js +3 -3
- package/dist/lib/generation/generator-utils.js +14 -9
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +2 -6
- package/modules/auth/authjs/files/lib/auth.ts +15 -29
- package/modules/auth/authjs/files/{schemas/prisma-schema.prisma → prisma/schema.prisma} +17 -11
- package/modules/auth/authjs/generator.json +48 -4
- package/modules/auth/better-auth/files/prisma/schema.prisma +3 -3
- package/modules/database/prisma/files/lib/prisma.ts +4 -4
- package/modules/database/prisma/files/prisma.config.ts +2 -2
- package/package.json +3 -1
- package/modules/auth/authjs/files/lib/auth-client.ts +0 -11
package/dist/cli/add.js
CHANGED
|
@@ -17,7 +17,6 @@ const logger_1 = require("../lib/ui/logger");
|
|
|
17
17
|
const package_manager_1 = require("../lib/pm/package-manager");
|
|
18
18
|
const package_root_1 = require("../lib/utils/package-root");
|
|
19
19
|
const framework_utils_1 = require("../lib/framework/framework-utils");
|
|
20
|
-
const generator_utils_1 = require("../lib/generation/generator-utils");
|
|
21
20
|
async function addCommand(module, options) {
|
|
22
21
|
try {
|
|
23
22
|
const projectRoot = process.cwd();
|
|
@@ -29,10 +28,6 @@ async function addCommand(module, options) {
|
|
|
29
28
|
logger_1.logger.newLine();
|
|
30
29
|
logger_1.logger.success(`Added ${chalk_1.default.bold(config.displayName)}`);
|
|
31
30
|
logger_1.logger.newLine();
|
|
32
|
-
if (config.metadata.envVars && config.metadata.envVars.length > 0) {
|
|
33
|
-
logger_1.logger.log("Next: Fill in environment variables in .env");
|
|
34
|
-
}
|
|
35
|
-
logger_1.logger.newLine();
|
|
36
31
|
}
|
|
37
32
|
catch (error) {
|
|
38
33
|
logger_1.logger.error(`Failed to add module: ${error.message}`);
|
|
@@ -44,88 +39,59 @@ async function addCommand(module, options) {
|
|
|
44
39
|
}
|
|
45
40
|
async function getAddConfig(module, options, projectInfo) {
|
|
46
41
|
const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
if (module === "database" || module === "auth") {
|
|
42
|
+
// If no module provided, go interactive
|
|
43
|
+
if (!module) {
|
|
44
|
+
return await getInteractiveConfig(modulesDir, projectInfo);
|
|
45
|
+
}
|
|
46
|
+
// Only allow: no-arg interactive, or explicit category + --provider.
|
|
47
|
+
// Disallow positional provider names like `npx stackkit add better-auth` or
|
|
48
|
+
// `npx stackkit add auth prisma-postgresql` — require `--provider` flag.
|
|
49
|
+
if (module === "database" || module === "auth") {
|
|
50
|
+
if (!options?.provider) {
|
|
58
51
|
if (module === "database") {
|
|
59
|
-
|
|
60
|
-
throw new Error("Provider is required for database. Use --provider <provider>");
|
|
61
|
-
}
|
|
62
|
-
let baseProvider = options.provider;
|
|
63
|
-
let adapterProvider = options.provider;
|
|
64
|
-
if (options.provider.includes("-")) {
|
|
65
|
-
const parts = options.provider.split("-");
|
|
66
|
-
baseProvider = parts[0]; // e.g., "prisma"
|
|
67
|
-
adapterProvider = options.provider; // e.g., "prisma-postgresql"
|
|
68
|
-
}
|
|
69
|
-
const moduleMetadata = await loadModuleMetadata(modulesDir, baseProvider, baseProvider);
|
|
70
|
-
if (!moduleMetadata) {
|
|
71
|
-
throw new Error(`Database provider "${baseProvider}" not found`);
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
module: "database",
|
|
75
|
-
provider: adapterProvider,
|
|
76
|
-
displayName: `${moduleMetadata.displayName} (${adapterProvider.split("-")[1] || adapterProvider})`,
|
|
77
|
-
metadata: moduleMetadata,
|
|
78
|
-
};
|
|
52
|
+
throw new Error("Provider is required for database. Use: `npx stackkit add database --provider <provider>`");
|
|
79
53
|
}
|
|
80
|
-
else
|
|
81
|
-
|
|
82
|
-
const moduleMetadata = await loadModuleMetadata(modulesDir, provider, provider);
|
|
83
|
-
if (!moduleMetadata) {
|
|
84
|
-
throw new Error(`Auth provider "${provider}" not found`);
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
module: "auth",
|
|
88
|
-
provider,
|
|
89
|
-
displayName: moduleMetadata.displayName,
|
|
90
|
-
metadata: moduleMetadata,
|
|
91
|
-
};
|
|
54
|
+
else {
|
|
55
|
+
throw new Error("Provider is required for auth. Use: `npx stackkit add auth --provider <provider>`");
|
|
92
56
|
}
|
|
93
57
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
"
|
|
105
|
-
const providers = Object.keys(moduleMetadata.dependencies.providers || {});
|
|
106
|
-
if (providers.length > 0) {
|
|
107
|
-
const { provider } = await inquirer_1.default.prompt([
|
|
108
|
-
{
|
|
109
|
-
type: "list",
|
|
110
|
-
name: "provider",
|
|
111
|
-
message: "Select database provider:",
|
|
112
|
-
choices: providers.map((p) => ({ name: p, value: p })),
|
|
113
|
-
},
|
|
114
|
-
]);
|
|
115
|
-
selectedProvider = provider;
|
|
116
|
-
}
|
|
58
|
+
if (module === "database") {
|
|
59
|
+
let baseProvider = options.provider;
|
|
60
|
+
let adapterProvider = options.provider;
|
|
61
|
+
if (options.provider.includes("-")) {
|
|
62
|
+
const parts = options.provider.split("-");
|
|
63
|
+
baseProvider = parts[0]; // e.g., "prisma"
|
|
64
|
+
adapterProvider = options.provider; // e.g., "prisma-postgresql"
|
|
65
|
+
}
|
|
66
|
+
const moduleMetadata = await loadModuleMetadata(modulesDir, baseProvider, baseProvider);
|
|
67
|
+
if (!moduleMetadata) {
|
|
68
|
+
throw new Error(`Database provider "${baseProvider}" not found`);
|
|
117
69
|
}
|
|
70
|
+
return {
|
|
71
|
+
module: "database",
|
|
72
|
+
provider: adapterProvider,
|
|
73
|
+
displayName: `${moduleMetadata.displayName} (${adapterProvider.split("-")[1] || adapterProvider})`,
|
|
74
|
+
metadata: moduleMetadata,
|
|
75
|
+
};
|
|
118
76
|
}
|
|
119
|
-
if (
|
|
120
|
-
|
|
77
|
+
else if (module === "auth") {
|
|
78
|
+
const provider = options.provider;
|
|
79
|
+
const moduleMetadata = await loadModuleMetadata(modulesDir, provider, provider);
|
|
80
|
+
if (!moduleMetadata) {
|
|
81
|
+
throw new Error(`Auth provider "${provider}" not found`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
module: "auth",
|
|
85
|
+
provider,
|
|
86
|
+
displayName: moduleMetadata.displayName,
|
|
87
|
+
metadata: moduleMetadata,
|
|
88
|
+
};
|
|
121
89
|
}
|
|
122
|
-
return {
|
|
123
|
-
module,
|
|
124
|
-
provider: selectedProvider,
|
|
125
|
-
displayName: moduleMetadata.displayName,
|
|
126
|
-
metadata: moduleMetadata,
|
|
127
|
-
};
|
|
128
90
|
}
|
|
91
|
+
// Unknown module type
|
|
92
|
+
throw new Error(`Unknown module type "${module}". Use "database" or "auth", or specify a provider directly.`);
|
|
93
|
+
}
|
|
94
|
+
async function getInteractiveConfig(modulesDir, projectInfo) {
|
|
129
95
|
const answers = await inquirer_1.default.prompt([
|
|
130
96
|
{
|
|
131
97
|
type: "list",
|
|
@@ -133,7 +99,7 @@ async function getAddConfig(module, options, projectInfo) {
|
|
|
133
99
|
message: "What would you like to add?",
|
|
134
100
|
choices: [
|
|
135
101
|
{ name: "Database", value: "database" },
|
|
136
|
-
{ name: "
|
|
102
|
+
{ name: "Auth", value: "auth" },
|
|
137
103
|
],
|
|
138
104
|
},
|
|
139
105
|
]);
|
|
@@ -167,7 +133,7 @@ async function getAddConfig(module, options, projectInfo) {
|
|
|
167
133
|
]);
|
|
168
134
|
return {
|
|
169
135
|
module: "database",
|
|
170
|
-
provider:
|
|
136
|
+
provider: `prisma-${providerAnswers.provider}`,
|
|
171
137
|
displayName: `Prisma (${providerAnswers.provider})`,
|
|
172
138
|
metadata: (await loadModuleMetadata(modulesDir, "prisma", "prisma")),
|
|
173
139
|
};
|
|
@@ -210,6 +176,55 @@ async function getAddConfig(module, options, projectInfo) {
|
|
|
210
176
|
}
|
|
211
177
|
throw new Error("Invalid selection");
|
|
212
178
|
}
|
|
179
|
+
async function getProviderConfig(modulesDir, provider, projectInfo) {
|
|
180
|
+
if (provider.includes("-")) {
|
|
181
|
+
const parts = provider.split("-");
|
|
182
|
+
const baseProvider = parts[0];
|
|
183
|
+
const specificProvider = provider;
|
|
184
|
+
if (baseProvider === "prisma") {
|
|
185
|
+
const metadata = await loadModuleMetadata(modulesDir, "database", baseProvider);
|
|
186
|
+
if (!metadata) {
|
|
187
|
+
throw new Error(`Database provider "${baseProvider}" not found`);
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
module: "database",
|
|
191
|
+
provider: specificProvider,
|
|
192
|
+
displayName: `Prisma (${parts[1]})`,
|
|
193
|
+
metadata,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
if (provider === "mongoose") {
|
|
199
|
+
const metadata = await loadModuleMetadata(modulesDir, "database", "mongoose");
|
|
200
|
+
if (!metadata) {
|
|
201
|
+
throw new Error(`Database provider "${provider}" not found`);
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
module: "database",
|
|
205
|
+
provider: "mongoose",
|
|
206
|
+
displayName: "Mongoose",
|
|
207
|
+
metadata,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
else if (provider === "better-auth" || provider === "authjs") {
|
|
211
|
+
const metadata = await loadModuleMetadata(modulesDir, provider, provider);
|
|
212
|
+
if (!metadata) {
|
|
213
|
+
throw new Error(`Auth provider "${provider}" not found`);
|
|
214
|
+
}
|
|
215
|
+
if (projectInfo && !metadata.supportedFrameworks.includes(projectInfo.framework)) {
|
|
216
|
+
throw new Error(`Auth provider "${provider}" does not support ${projectInfo.framework}`);
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
module: "auth",
|
|
220
|
+
provider,
|
|
221
|
+
displayName: provider === "better-auth" ? "Better Auth" : "Auth.js",
|
|
222
|
+
metadata,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
throw new Error(`Unknown provider "${provider}". Available providers: better-auth, authjs, mongoose, prisma-postgresql, prisma-mongodb, prisma-mysql, prisma-sqlite`);
|
|
227
|
+
}
|
|
213
228
|
async function addModuleToProject(projectRoot, projectInfo, config, options) {
|
|
214
229
|
const moduleMetadata = config.metadata;
|
|
215
230
|
const selectedProvider = config.provider;
|
|
@@ -228,6 +243,21 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
|
|
|
228
243
|
return;
|
|
229
244
|
}
|
|
230
245
|
}
|
|
246
|
+
if (config.module === "database" && projectInfo.hasDatabase && !options?.force) {
|
|
247
|
+
logger_1.logger.warn("Database library already detected in this project");
|
|
248
|
+
const { proceed } = await inquirer_1.default.prompt([
|
|
249
|
+
{
|
|
250
|
+
type: "confirm",
|
|
251
|
+
name: "proceed",
|
|
252
|
+
message: "Continue anyway? (use --force to skip this prompt)",
|
|
253
|
+
default: false,
|
|
254
|
+
},
|
|
255
|
+
]);
|
|
256
|
+
if (!proceed) {
|
|
257
|
+
logger_1.logger.info("Cancelled");
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
231
261
|
if (options?.dryRun) {
|
|
232
262
|
logger_1.logger.warn("Dry run mode - no changes will be made");
|
|
233
263
|
logger_1.logger.newLine();
|
|
@@ -413,10 +443,10 @@ async function loadModuleMetadata(modulesDir, moduleName, provider) {
|
|
|
413
443
|
if (await fs_extra_1.default.pathExists(metadataPath)) {
|
|
414
444
|
const metadata = await fs_extra_1.default.readJSON(metadataPath);
|
|
415
445
|
if (provider && moduleDir === provider) {
|
|
416
|
-
return
|
|
446
|
+
return metadata;
|
|
417
447
|
}
|
|
418
448
|
if (!provider && (metadata.category === moduleName || moduleDir === moduleName)) {
|
|
419
|
-
return
|
|
449
|
+
return metadata;
|
|
420
450
|
}
|
|
421
451
|
}
|
|
422
452
|
}
|
package/dist/cli/create.js
CHANGED
|
@@ -306,7 +306,8 @@ async function processGeneratorEnvVars(config, targetDir) {
|
|
|
306
306
|
const generator = await fs_extra_1.default.readJson(dbGeneratorPath);
|
|
307
307
|
if (generator.operations) {
|
|
308
308
|
for (const operation of generator.operations) {
|
|
309
|
-
if (operation.type === "add-env" &&
|
|
309
|
+
if (operation.type === "add-env" &&
|
|
310
|
+
(!operation.condition || checkCondition(operation.condition, config))) {
|
|
310
311
|
for (const [key, value] of Object.entries(operation.envVars)) {
|
|
311
312
|
envVars.push({
|
|
312
313
|
key,
|
|
@@ -326,7 +327,8 @@ async function processGeneratorEnvVars(config, targetDir) {
|
|
|
326
327
|
const generator = await fs_extra_1.default.readJson(authGeneratorPath);
|
|
327
328
|
if (generator.operations) {
|
|
328
329
|
for (const operation of generator.operations) {
|
|
329
|
-
if (operation.type === "add-env" &&
|
|
330
|
+
if (operation.type === "add-env" &&
|
|
331
|
+
(!operation.condition || checkCondition(operation.condition, config))) {
|
|
330
332
|
for (const [key, value] of Object.entries(operation.envVars)) {
|
|
331
333
|
envVars.push({
|
|
332
334
|
key,
|
package/dist/cli/doctor.js
CHANGED
|
@@ -137,7 +137,7 @@ async function runDoctorChecks() {
|
|
|
137
137
|
summary: {
|
|
138
138
|
errors: checks.filter((c) => c.status === "error").length,
|
|
139
139
|
warnings: checks.filter((c) => c.status === "warning").length,
|
|
140
|
-
suggestions: generateSuggestions(),
|
|
140
|
+
suggestions: generateSuggestions(authModules, databaseModules),
|
|
141
141
|
},
|
|
142
142
|
};
|
|
143
143
|
return report;
|
|
@@ -261,6 +261,7 @@ async function checkAuthRoutesExist(projectRoot, projectType) {
|
|
|
261
261
|
if (projectType !== "nextjs")
|
|
262
262
|
return true; // Skip for non-Next.js
|
|
263
263
|
const possiblePaths = [
|
|
264
|
+
// NextAuth routes
|
|
264
265
|
"app/api/auth/[...nextauth]/route.ts",
|
|
265
266
|
"app/api/auth/[...nextauth]/route.js",
|
|
266
267
|
"src/app/api/auth/[...nextauth]/route.ts",
|
|
@@ -269,6 +270,11 @@ async function checkAuthRoutesExist(projectRoot, projectType) {
|
|
|
269
270
|
"pages/api/auth/[...nextauth].js",
|
|
270
271
|
"src/pages/api/auth/[...nextauth].ts",
|
|
271
272
|
"src/pages/api/auth/[...nextauth].js",
|
|
273
|
+
// Better Auth routes
|
|
274
|
+
"app/api/auth/[...all]/route.ts",
|
|
275
|
+
"app/api/auth/[...all]/route.js",
|
|
276
|
+
"src/app/api/auth/[...all]/route.ts",
|
|
277
|
+
"src/app/api/auth/[...all]/route.js",
|
|
272
278
|
];
|
|
273
279
|
for (const routePath of possiblePaths) {
|
|
274
280
|
if (await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, routePath))) {
|
|
@@ -372,8 +378,10 @@ async function checkDependencies(packageJson) {
|
|
|
372
378
|
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
373
379
|
for (const [name, version] of Object.entries(deps || {})) {
|
|
374
380
|
if (typeof version === "string" && (version.startsWith("^") || version.startsWith("~"))) {
|
|
381
|
+
// Assume up to date if using flexible versioning
|
|
375
382
|
}
|
|
376
383
|
else {
|
|
384
|
+
// Assume outdated if using exact versions (simplified check)
|
|
377
385
|
outdated.push(name);
|
|
378
386
|
}
|
|
379
387
|
}
|
|
@@ -406,11 +414,16 @@ async function checkEslintConfigExists(projectRoot) {
|
|
|
406
414
|
}
|
|
407
415
|
return false;
|
|
408
416
|
}
|
|
409
|
-
function generateSuggestions() {
|
|
417
|
+
function generateSuggestions(authModules, databaseModules) {
|
|
410
418
|
const suggestions = [];
|
|
419
|
+
// Show suggestions based on what's missing
|
|
420
|
+
if (authModules.length === 0) {
|
|
421
|
+
suggestions.push("stackkit add auth - Add authentication module");
|
|
422
|
+
}
|
|
423
|
+
if (databaseModules.length === 0) {
|
|
424
|
+
suggestions.push("stackkit add db - Add database module");
|
|
425
|
+
}
|
|
411
426
|
// Always show available commands
|
|
412
|
-
suggestions.push("stackkit add auth - Add authentication module");
|
|
413
|
-
suggestions.push("stackkit add db - Add database module");
|
|
414
427
|
suggestions.push("stackkit list - View available modules");
|
|
415
428
|
return suggestions;
|
|
416
429
|
}
|
package/dist/index.js
CHANGED
|
@@ -7,11 +7,14 @@ const add_1 = require("./cli/add");
|
|
|
7
7
|
const doctor_1 = require("./cli/doctor");
|
|
8
8
|
const list_1 = require("./cli/list");
|
|
9
9
|
const logger_1 = require("./lib/ui/logger");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
|
|
10
13
|
const program = new commander_1.Command();
|
|
11
14
|
program
|
|
12
15
|
.name("stackkit")
|
|
13
16
|
.description("CLI for creating and managing StackKit projects")
|
|
14
|
-
.version(
|
|
17
|
+
.version(packageJson.version)
|
|
15
18
|
.configureHelp({
|
|
16
19
|
subcommandTerm: (cmd) => {
|
|
17
20
|
const name = cmd.name();
|
|
@@ -175,7 +175,7 @@ class AdvancedCodeGenerator {
|
|
|
175
175
|
conditionMet = typeof actualVal === "string" && actualVal.endsWith(cleanExpectedVal);
|
|
176
176
|
break;
|
|
177
177
|
}
|
|
178
|
-
const contentToProcess = conditionMet ? blockContent :
|
|
178
|
+
const contentToProcess = conditionMet ? blockContent : elseContent || "";
|
|
179
179
|
return this.processTemplateRecursive(contentToProcess, context)
|
|
180
180
|
.replace(/^\n+/, "")
|
|
181
181
|
.replace(/\n+$/, "");
|
|
@@ -185,7 +185,7 @@ class AdvancedCodeGenerator {
|
|
|
185
185
|
const conditionParts = condition.split("==");
|
|
186
186
|
if (conditionParts.length === 2) {
|
|
187
187
|
const [varName, expectedValue] = conditionParts.map((s) => s.trim().replace(/['"]/g, ""));
|
|
188
|
-
const contentToProcess = context[varName] === expectedValue ? blockContent :
|
|
188
|
+
const contentToProcess = context[varName] === expectedValue ? blockContent : elseContent || "";
|
|
189
189
|
return this.processTemplateRecursive(contentToProcess, context)
|
|
190
190
|
.replace(/^\n+/, "")
|
|
191
191
|
.replace(/\n+$/, "");
|
|
@@ -195,7 +195,7 @@ class AdvancedCodeGenerator {
|
|
|
195
195
|
const [arrayName, item] = conditionFunc[0].split("(");
|
|
196
196
|
const itemValue = item.replace(")", "").replace(/['"]/g, "");
|
|
197
197
|
const array = context[arrayName] || [];
|
|
198
|
-
const contentToProcess = Array.isArray(array) && array.includes(itemValue) ? blockContent :
|
|
198
|
+
const contentToProcess = Array.isArray(array) && array.includes(itemValue) ? blockContent : elseContent || "";
|
|
199
199
|
return this.processTemplateRecursive(contentToProcess, context)
|
|
200
200
|
.replace(/^\n+/, "")
|
|
201
201
|
.replace(/\n+$/, "");
|
|
@@ -74,15 +74,20 @@ async function mergeGeneratorIntoModuleMetadata(metadata, modulePath) {
|
|
|
74
74
|
if (await fs.pathExists(generatorPath)) {
|
|
75
75
|
try {
|
|
76
76
|
const generator = await fs.readJson(generatorPath);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
for (const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
value
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
// Process add-env operations to extract envVars
|
|
78
|
+
if (generator.operations && Array.isArray(generator.operations)) {
|
|
79
|
+
for (const operation of generator.operations) {
|
|
80
|
+
if (operation.type === "add-env" && operation.envVars) {
|
|
81
|
+
metadata.envVars = metadata.envVars || [];
|
|
82
|
+
for (const [key, value] of Object.entries(operation.envVars)) {
|
|
83
|
+
metadata.envVars.push({
|
|
84
|
+
key,
|
|
85
|
+
value: value,
|
|
86
|
+
description: `Environment variable for ${key}`,
|
|
87
|
+
required: true,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
93
|
if (generator.dependencies) {
|
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { PrismaAdapter } from "@auth/prisma-adapter"
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import NextAuth from "next-auth"
|
|
2
|
+
import { PrismaAdapter } from "@auth/prisma-adapter"
|
|
3
|
+
import prisma from "@/lib/prisma"
|
|
4
|
+
import Google from "next-auth/providers/google"
|
|
5
|
+
import { encode, decode } from 'next-auth/jwt';
|
|
5
6
|
|
|
6
|
-
export const
|
|
7
|
+
export const { handlers, signIn, signOut, auth } = NextAuth({
|
|
7
8
|
adapter: PrismaAdapter(prisma),
|
|
8
9
|
providers: [
|
|
9
|
-
|
|
10
|
-
clientId: process.env.
|
|
11
|
-
clientSecret: process.env.
|
|
10
|
+
Google({
|
|
11
|
+
clientId: process.env.AUTH_GOOGLE_ID,
|
|
12
|
+
clientSecret: process.env.AUTH_GOOGLE_SECRET,
|
|
12
13
|
}),
|
|
13
14
|
],
|
|
14
|
-
session: {
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
callbacks: {
|
|
18
|
-
async jwt({ token, user }) {
|
|
19
|
-
if (user) {
|
|
20
|
-
token.id = user.id;
|
|
21
|
-
}
|
|
22
|
-
return token;
|
|
23
|
-
},
|
|
24
|
-
async session({ session, token }) {
|
|
25
|
-
if (token) {
|
|
26
|
-
session.user.id = token.id as string;
|
|
27
|
-
}
|
|
28
|
-
return session;
|
|
29
|
-
},
|
|
30
|
-
},
|
|
15
|
+
session: { strategy: "jwt" },
|
|
16
|
+
secret: process.env.AUTH_SECRET,
|
|
17
|
+
jwt: { encode, decode },
|
|
31
18
|
pages: {
|
|
32
|
-
signIn:
|
|
33
|
-
|
|
34
|
-
error: "/auth/error",
|
|
19
|
+
signIn: '/sign-in',
|
|
20
|
+
error: '/error',
|
|
35
21
|
},
|
|
36
|
-
}
|
|
22
|
+
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
{{#var defaultId = {{#if prismaProvider == "mongodb"}}@default(auto()) @map("_id") @db.ObjectId{{else}}@default(cuid()){{/if}}}}
|
|
2
2
|
model Account {
|
|
3
|
-
id String @id {{
|
|
4
|
-
userId String
|
|
3
|
+
id String @id {{defaultId}}
|
|
4
|
+
userId String @map("user_id")
|
|
5
5
|
type String
|
|
6
6
|
provider String
|
|
7
|
-
providerAccountId String
|
|
7
|
+
providerAccountId String @map("provider_account_id")
|
|
8
8
|
refresh_token String? @db.Text
|
|
9
9
|
access_token String? @db.Text
|
|
10
10
|
expires_at Int?
|
|
@@ -16,30 +16,36 @@ model Account {
|
|
|
16
16
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
17
17
|
|
|
18
18
|
@@unique([provider, providerAccountId])
|
|
19
|
+
@@map("accounts")
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
model Session {
|
|
22
|
-
id String @id {{
|
|
23
|
-
sessionToken String @unique
|
|
24
|
-
userId String {{
|
|
23
|
+
id String @id {{defaultId}}
|
|
24
|
+
sessionToken String @unique @map("session_token")
|
|
25
|
+
userId String {{#if prismaProvider == "mongodb"}} @db.ObjectId{{/if}} @map("user_id")
|
|
25
26
|
expires DateTime
|
|
26
27
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
28
|
+
|
|
29
|
+
@@map("sessions")
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
model User {
|
|
30
|
-
id String @id {{
|
|
33
|
+
id String @id {{defaultId}}
|
|
31
34
|
name String?
|
|
32
|
-
email String
|
|
33
|
-
emailVerified DateTime?
|
|
35
|
+
email String? @unique
|
|
36
|
+
emailVerified DateTime? @map("email_verified")
|
|
34
37
|
image String?
|
|
35
38
|
accounts Account[]
|
|
36
39
|
sessions Session[]
|
|
40
|
+
|
|
41
|
+
@@map("users")
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
model VerificationToken {
|
|
40
45
|
identifier String
|
|
41
|
-
token String
|
|
46
|
+
token String
|
|
42
47
|
expires DateTime
|
|
43
48
|
|
|
44
49
|
@@unique([identifier, token])
|
|
50
|
+
@@map("verification_tokens")
|
|
45
51
|
}
|
|
@@ -2,9 +2,53 @@
|
|
|
2
2
|
"name": "authjs",
|
|
3
3
|
"type": "auth",
|
|
4
4
|
"priority": 10,
|
|
5
|
-
"operations": [
|
|
6
|
-
|
|
5
|
+
"operations": [
|
|
6
|
+
{
|
|
7
|
+
"type": "create-file",
|
|
8
|
+
"source": "lib/auth.ts",
|
|
9
|
+
"destination": "lib/auth.ts"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "create-file",
|
|
13
|
+
"source": "api/auth/[...nextauth]/route.ts",
|
|
14
|
+
"destination": "app/api/auth/[...nextauth]/route.ts"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "create-file",
|
|
18
|
+
"destination": "proxy.ts",
|
|
19
|
+
"content": "export { auth as middleware } from \"@/auth\""
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": "patch-file",
|
|
23
|
+
"destination": "prisma/schema.prisma",
|
|
24
|
+
"condition": { "database": "prisma" },
|
|
25
|
+
"operations": [
|
|
26
|
+
{
|
|
27
|
+
"type": "add-to-bottom",
|
|
28
|
+
"source": "prisma/schema.prisma"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "add-dependency",
|
|
34
|
+
"condition": { "database": "prisma" },
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@auth/prisma-adapter": "^0.5.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "add-env",
|
|
42
|
+
"envVars": {
|
|
43
|
+
"AUTH_SECRET": "",
|
|
44
|
+
"AUTH_GOOGLE_ID": "",
|
|
45
|
+
"AUTH_GOOGLE_SECRET": ""
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"next-auth": "^5.0.0-beta.30"
|
|
51
|
+
},
|
|
7
52
|
"devDependencies": {},
|
|
8
|
-
"scripts": {}
|
|
9
|
-
"envVars": {}
|
|
53
|
+
"scripts": {}
|
|
10
54
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{{#var defaultId = {{#if prismaProvider == mongodb}}@default(auto()) @map("_id") @db.ObjectId{{else}}@default(cuid()){{/if}}}}
|
|
1
|
+
{{#var defaultId = {{#if prismaProvider == "mongodb"}}@default(auto()) @map("_id") @db.ObjectId{{else}}@default(cuid()){{/if}}}}
|
|
2
2
|
model User {
|
|
3
3
|
id String @id {{defaultId}}
|
|
4
4
|
name String
|
|
@@ -23,7 +23,7 @@ model Session {
|
|
|
23
23
|
updatedAt DateTime @updatedAt
|
|
24
24
|
ipAddress String?
|
|
25
25
|
userAgent String?
|
|
26
|
-
userId String {{#if prismaProvider == mongodb}} @db.ObjectId{{/if}}
|
|
26
|
+
userId String {{#if prismaProvider == "mongodb"}} @db.ObjectId{{/if}}
|
|
27
27
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
28
28
|
|
|
29
29
|
@@index([userId])
|
|
@@ -34,7 +34,7 @@ model Account {
|
|
|
34
34
|
id String @id {{defaultId}}
|
|
35
35
|
accountId String
|
|
36
36
|
providerId String
|
|
37
|
-
userId String {{#if prismaProvider == mongodb}} @db.ObjectId{{/if}}
|
|
37
|
+
userId String {{#if prismaProvider == "mongodb"}} @db.ObjectId{{/if}}
|
|
38
38
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
39
39
|
accessToken String?
|
|
40
40
|
refreshToken String?
|
|
@@ -6,7 +6,7 @@ const globalForPrisma = globalThis as unknown as {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
{{#switch prismaProvider}}
|
|
9
|
-
{{#case postgresql}}
|
|
9
|
+
{{#case "postgresql"}}
|
|
10
10
|
import { PrismaPg } from '@prisma/adapter-pg'
|
|
11
11
|
|
|
12
12
|
const connectionString = `${process.env.DATABASE_URL}`
|
|
@@ -16,13 +16,13 @@ const prisma = new PrismaClient({ adapter })
|
|
|
16
16
|
|
|
17
17
|
export { prisma }
|
|
18
18
|
{{/case}}
|
|
19
|
-
{{#case mongodb}}
|
|
19
|
+
{{#case "mongodb"}}
|
|
20
20
|
|
|
21
21
|
const prisma = new PrismaClient()
|
|
22
22
|
|
|
23
23
|
export { prisma }
|
|
24
24
|
{{/case}}
|
|
25
|
-
{{#case mysql}}
|
|
25
|
+
{{#case "mysql"}}
|
|
26
26
|
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
|
|
27
27
|
|
|
28
28
|
const adapter = new PrismaMariaDb({
|
|
@@ -36,7 +36,7 @@ const prisma = new PrismaClient({ adapter });
|
|
|
36
36
|
|
|
37
37
|
export { prisma }
|
|
38
38
|
{{/case}}
|
|
39
|
-
{{#case sqlite}}
|
|
39
|
+
{{#case "sqlite"}}
|
|
40
40
|
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
|
41
41
|
|
|
42
42
|
const connectionString = `${process.env.DATABASE_URL}`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
2
|
{{#switch prismaProvider}}
|
|
3
|
-
{{#case mongodb}}
|
|
3
|
+
{{#case "mongodb"}}
|
|
4
4
|
import { defineConfig, env } from "prisma/config";
|
|
5
5
|
{{/case}}
|
|
6
6
|
{{#case default}}
|
|
@@ -14,7 +14,7 @@ export default defineConfig({
|
|
|
14
14
|
path: "prisma/migrations",
|
|
15
15
|
},
|
|
16
16
|
{{#switch prismaProvider}}
|
|
17
|
-
{{#case mongodb}}
|
|
17
|
+
{{#case "mongodb"}}
|
|
18
18
|
engine: "classic",
|
|
19
19
|
datasource: {
|
|
20
20
|
url: env('DATABASE_URL'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stackkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Production-ready CLI to create and extend JavaScript or TypeScript apps with modular stacks.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
"copy-assets": "cp -r ../../templates . && cp -r ../../modules .",
|
|
29
29
|
"clean": "rm -rf dist templates modules",
|
|
30
30
|
"typecheck": "tsc --noEmit",
|
|
31
|
+
"lint": "eslint src --ext .ts",
|
|
32
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
31
33
|
"prepublishOnly": "npm run build"
|
|
32
34
|
},
|
|
33
35
|
"keywords": [
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { getServerSession } from "next-auth/next";
|
|
2
|
-
import { authOptions } from "@/lib/auth";
|
|
3
|
-
|
|
4
|
-
export async function getSession() {
|
|
5
|
-
return await getServerSession(authOptions);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export async function getCurrentUser() {
|
|
9
|
-
const session = await getSession();
|
|
10
|
-
return session?.user;
|
|
11
|
-
}
|