better-ts-stack 2.0.1 → 2.0.2
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/output/nextSteps.js +4 -2
- package/dist/types/index.js +1 -1
- package/package.json +1 -1
- package/templates/frontend/tanstack/config.json +45 -45
- package/templates/modules/auth/nextjs/lib/auth-schema.ts +1 -1
- package/templates/modules/auth/tanstack/src/lib/auth-schema.ts +38 -38
- package/templates/modules/drizzle/express/src/lib/schema.ts +3 -1
- package/templates/modules/drizzle/nestjs/src/database/schema.ts +3 -1
- package/templates/modules/drizzle/nextjs/lib/schema.ts.hbs +11 -5
- package/templates/modules/drizzle/tanstack/src/lib/schema.ts.hbs +90 -84
package/dist/output/nextSteps.js
CHANGED
|
@@ -21,9 +21,11 @@ function generateNextSteps(config, targetDir, depsInstalled) {
|
|
|
21
21
|
const steps = [];
|
|
22
22
|
const isFullstack = config.applicationType === "fullstack";
|
|
23
23
|
// Step 1: cd into project directory, unless it was created in place
|
|
24
|
+
// Quoted when it has spaces, so the command can be pasted as it is
|
|
24
25
|
const relativeDir = node_path_1.default.relative((0, node_process_1.cwd)(), targetDir);
|
|
25
|
-
if (relativeDir)
|
|
26
|
-
steps.push(`cd ${relativeDir}`);
|
|
26
|
+
if (relativeDir) {
|
|
27
|
+
steps.push(/\s/.test(relativeDir) ? `cd "${relativeDir}"` : `cd ${relativeDir}`);
|
|
28
|
+
}
|
|
27
29
|
// Step 2: Set environment variables
|
|
28
30
|
if (config.database !== "none") {
|
|
29
31
|
steps.push("Review the generated .env and set your database connection details");
|
package/dist/types/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "tanstack",
|
|
3
|
-
"name": "TanStack Start",
|
|
4
|
-
"description": "TanStack Start with TanStack Router, React 19, and Tailwind CSS v4",
|
|
5
|
-
"type": "base",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"build": "vite build",
|
|
9
|
-
"start": "srvx --prod -s ../client dist/server/server.js",
|
|
10
|
-
"preview": "vite preview",
|
|
11
|
-
"type:check": "tsc --noEmit",
|
|
12
|
-
"lint": "eslint src"
|
|
13
|
-
},
|
|
14
|
-
"dependencies": {
|
|
15
|
-
"@tanstack/react-query": "^5.
|
|
16
|
-
"@tanstack/react-query-devtools": "^5.
|
|
17
|
-
"@tanstack/react-router": "^1.170.
|
|
18
|
-
"@tanstack/react-router-devtools": "^1.167.2",
|
|
19
|
-
"@tanstack/react-router-ssr-query": "^1.167.
|
|
20
|
-
"@tanstack/react-start": "^1.
|
|
21
|
-
"class-variance-authority": "^0.7.1",
|
|
22
|
-
"clsx": "^2.1.1",
|
|
23
|
-
"lucide-react": "^1.41.0",
|
|
24
|
-
"react": "^19.2.8",
|
|
25
|
-
"react-dom": "^19.2.8",
|
|
26
|
-
"srvx": "^1.0.
|
|
27
|
-
"tailwind-merge": "^3.6.0"
|
|
28
|
-
},
|
|
29
|
-
"devDependencies": {
|
|
30
|
-
"@eslint/js": "^10.0.1",
|
|
31
|
-
"@tailwindcss/vite": "^4.3.3",
|
|
32
|
-
"@types/node": "^24.13.3",
|
|
33
|
-
"@types/react": "^19.2.18",
|
|
34
|
-
"@types/react-dom": "^19.2.7",
|
|
35
|
-
"@vitejs/plugin-react": "^6.1.
|
|
36
|
-
"eslint": "^10.10.0",
|
|
37
|
-
"tailwindcss": "^4.3.3",
|
|
38
|
-
"typescript": "^6.0.3",
|
|
39
|
-
"typescript-eslint": "^8.69.0",
|
|
40
|
-
"vite": "^8.3.
|
|
41
|
-
},
|
|
42
|
-
"envVars": {
|
|
43
|
-
"PORT": "3000"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "tanstack",
|
|
3
|
+
"name": "TanStack Start",
|
|
4
|
+
"description": "TanStack Start with TanStack Router, React 19, and Tailwind CSS v4",
|
|
5
|
+
"type": "base",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite dev",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"start": "srvx --prod -s ../client dist/server/server.js",
|
|
10
|
+
"preview": "vite preview",
|
|
11
|
+
"type:check": "tsc --noEmit",
|
|
12
|
+
"lint": "eslint src"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@tanstack/react-query": "^5.104.3",
|
|
16
|
+
"@tanstack/react-query-devtools": "^5.104.3",
|
|
17
|
+
"@tanstack/react-router": "^1.170.45",
|
|
18
|
+
"@tanstack/react-router-devtools": "^1.167.2",
|
|
19
|
+
"@tanstack/react-router-ssr-query": "^1.167.3",
|
|
20
|
+
"@tanstack/react-start": "^1.169.3",
|
|
21
|
+
"class-variance-authority": "^0.7.1",
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
|
+
"lucide-react": "^1.41.0",
|
|
24
|
+
"react": "^19.2.8",
|
|
25
|
+
"react-dom": "^19.2.8",
|
|
26
|
+
"srvx": "^1.0.5",
|
|
27
|
+
"tailwind-merge": "^3.6.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@eslint/js": "^10.0.1",
|
|
31
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
32
|
+
"@types/node": "^24.13.3",
|
|
33
|
+
"@types/react": "^19.2.18",
|
|
34
|
+
"@types/react-dom": "^19.2.7",
|
|
35
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
36
|
+
"eslint": "^10.10.0",
|
|
37
|
+
"tailwindcss": "^4.3.3",
|
|
38
|
+
"typescript": "^6.0.3",
|
|
39
|
+
"typescript-eslint": "^8.69.0",
|
|
40
|
+
"vite": "^8.3.4"
|
|
41
|
+
},
|
|
42
|
+
"envVars": {
|
|
43
|
+
"PORT": "3000"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
export const signInSchema = z.object({
|
|
4
|
-
email: z.
|
|
5
|
-
password: z.string().min(8, "Password must be at least 8 characters."),
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export const signUpSchema = signInSchema.extend({
|
|
9
|
-
name: z
|
|
10
|
-
.string()
|
|
11
|
-
.trim()
|
|
12
|
-
.min(2, "Name must be at least 2 characters.")
|
|
13
|
-
.max(50, "Name must be 50 characters or fewer."),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export type SignInValues = z.infer<typeof signInSchema>;
|
|
17
|
-
export type SignUpValues = z.infer<typeof signUpSchema>;
|
|
18
|
-
|
|
19
|
-
export function getAuthErrorMessage(error: unknown) {
|
|
20
|
-
if (!error) {
|
|
21
|
-
return "Something went wrong. Please try again.";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (typeof error === "string") {
|
|
25
|
-
return error;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (typeof error === "object") {
|
|
29
|
-
if ("message" in error && typeof error.message === "string") {
|
|
30
|
-
return error.message;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if ("statusText" in error && typeof error.statusText === "string") {
|
|
34
|
-
return error.statusText;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return "Something went wrong. Please try again.";
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const signInSchema = z.object({
|
|
4
|
+
email: z.email("Enter a valid email address."),
|
|
5
|
+
password: z.string().min(8, "Password must be at least 8 characters."),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const signUpSchema = signInSchema.extend({
|
|
9
|
+
name: z
|
|
10
|
+
.string()
|
|
11
|
+
.trim()
|
|
12
|
+
.min(2, "Name must be at least 2 characters.")
|
|
13
|
+
.max(50, "Name must be 50 characters or fewer."),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type SignInValues = z.infer<typeof signInSchema>;
|
|
17
|
+
export type SignUpValues = z.infer<typeof signUpSchema>;
|
|
18
|
+
|
|
19
|
+
export function getAuthErrorMessage(error: unknown) {
|
|
20
|
+
if (!error) {
|
|
21
|
+
return "Something went wrong. Please try again.";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (typeof error === "string") {
|
|
25
|
+
return error;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof error === "object") {
|
|
29
|
+
if ("message" in error && typeof error.message === "string") {
|
|
30
|
+
return error.message;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if ("statusText" in error && typeof error.statusText === "string") {
|
|
34
|
+
return error.statusText;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return "Something went wrong. Please try again.";
|
|
39
39
|
}
|
|
@@ -6,5 +6,7 @@ export const users = pgTable("users", {
|
|
|
6
6
|
name: text("name"),
|
|
7
7
|
password: text("password").notNull(),
|
|
8
8
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
9
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
9
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
10
|
+
.defaultNow()
|
|
11
|
+
.$onUpdate(() => new Date()),
|
|
10
12
|
});
|
|
@@ -6,5 +6,7 @@ export const users = pgTable("users", {
|
|
|
6
6
|
name: text("name"),
|
|
7
7
|
password: text("password").notNull(),
|
|
8
8
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
9
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
9
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
10
|
+
.defaultNow()
|
|
11
|
+
.$onUpdate(() => new Date()),
|
|
10
12
|
});
|
|
@@ -12,7 +12,8 @@ export const user = pgTable("user", {
|
|
|
12
12
|
.defaultNow(),
|
|
13
13
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
14
14
|
.notNull()
|
|
15
|
-
.defaultNow()
|
|
15
|
+
.defaultNow()
|
|
16
|
+
.$onUpdate(() => new Date()),
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
export const session = pgTable("session", {
|
|
@@ -24,7 +25,8 @@ export const session = pgTable("session", {
|
|
|
24
25
|
.defaultNow(),
|
|
25
26
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
26
27
|
.notNull()
|
|
27
|
-
.defaultNow()
|
|
28
|
+
.defaultNow()
|
|
29
|
+
.$onUpdate(() => new Date()),
|
|
28
30
|
ipAddress: text("ip_address"),
|
|
29
31
|
userAgent: text("user_agent"),
|
|
30
32
|
userId: text("user_id")
|
|
@@ -55,7 +57,8 @@ export const account = pgTable("account", {
|
|
|
55
57
|
.defaultNow(),
|
|
56
58
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
57
59
|
.notNull()
|
|
58
|
-
.defaultNow()
|
|
60
|
+
.defaultNow()
|
|
61
|
+
.$onUpdate(() => new Date()),
|
|
59
62
|
}, (table) => [uniqueIndex("account_provider_account_id_unique").on(table.providerId, table.accountId)]);
|
|
60
63
|
|
|
61
64
|
export const verification = pgTable("verification", {
|
|
@@ -68,7 +71,8 @@ export const verification = pgTable("verification", {
|
|
|
68
71
|
.defaultNow(),
|
|
69
72
|
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
70
73
|
.notNull()
|
|
71
|
-
.defaultNow()
|
|
74
|
+
.defaultNow()
|
|
75
|
+
.$onUpdate(() => new Date()),
|
|
72
76
|
});
|
|
73
77
|
{{else}}
|
|
74
78
|
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
|
@@ -79,6 +83,8 @@ export const users = pgTable("users", {
|
|
|
79
83
|
name: text("name"),
|
|
80
84
|
password: text("password").notNull(),
|
|
81
85
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
82
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
86
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
87
|
+
.defaultNow()
|
|
88
|
+
.$onUpdate(() => new Date()),
|
|
83
89
|
});
|
|
84
90
|
{{/if}}
|
|
@@ -1,84 +1,90 @@
|
|
|
1
|
-
{{#if useAuth}}
|
|
2
|
-
import { boolean, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
|
|
3
|
-
|
|
4
|
-
export const user = pgTable("user", {
|
|
5
|
-
id: text("id").primaryKey(),
|
|
6
|
-
name: text("name").notNull(),
|
|
7
|
-
email: text("email").notNull().unique(),
|
|
8
|
-
emailVerified: boolean("email_verified").notNull().default(false),
|
|
9
|
-
image: text("image"),
|
|
10
|
-
createdAt: timestamp("created_at", { withTimezone: true })
|
|
11
|
-
.notNull()
|
|
12
|
-
.defaultNow(),
|
|
13
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
14
|
-
.notNull()
|
|
15
|
-
.defaultNow()
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
.notNull()
|
|
71
|
-
.defaultNow(),
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
{{#if useAuth}}
|
|
2
|
+
import { boolean, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
|
|
3
|
+
|
|
4
|
+
export const user = pgTable("user", {
|
|
5
|
+
id: text("id").primaryKey(),
|
|
6
|
+
name: text("name").notNull(),
|
|
7
|
+
email: text("email").notNull().unique(),
|
|
8
|
+
emailVerified: boolean("email_verified").notNull().default(false),
|
|
9
|
+
image: text("image"),
|
|
10
|
+
createdAt: timestamp("created_at", { withTimezone: true })
|
|
11
|
+
.notNull()
|
|
12
|
+
.defaultNow(),
|
|
13
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
14
|
+
.notNull()
|
|
15
|
+
.defaultNow()
|
|
16
|
+
.$onUpdate(() => new Date()),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const session = pgTable("session", {
|
|
20
|
+
id: text("id").primaryKey(),
|
|
21
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
22
|
+
token: text("token").notNull().unique(),
|
|
23
|
+
createdAt: timestamp("created_at", { withTimezone: true })
|
|
24
|
+
.notNull()
|
|
25
|
+
.defaultNow(),
|
|
26
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
27
|
+
.notNull()
|
|
28
|
+
.defaultNow()
|
|
29
|
+
.$onUpdate(() => new Date()),
|
|
30
|
+
ipAddress: text("ip_address"),
|
|
31
|
+
userAgent: text("user_agent"),
|
|
32
|
+
userId: text("user_id")
|
|
33
|
+
.notNull()
|
|
34
|
+
.references(() => user.id, { onDelete: "cascade" }),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const account = pgTable("account", {
|
|
38
|
+
id: text("id").primaryKey(),
|
|
39
|
+
accountId: text("account_id").notNull(),
|
|
40
|
+
providerId: text("provider_id").notNull(),
|
|
41
|
+
userId: text("user_id")
|
|
42
|
+
.notNull()
|
|
43
|
+
.references(() => user.id, { onDelete: "cascade" }),
|
|
44
|
+
accessToken: text("access_token"),
|
|
45
|
+
refreshToken: text("refresh_token"),
|
|
46
|
+
idToken: text("id_token"),
|
|
47
|
+
accessTokenExpiresAt: timestamp("access_token_expires_at", {
|
|
48
|
+
withTimezone: true,
|
|
49
|
+
}),
|
|
50
|
+
refreshTokenExpiresAt: timestamp("refresh_token_expires_at", {
|
|
51
|
+
withTimezone: true,
|
|
52
|
+
}),
|
|
53
|
+
scope: text("scope"),
|
|
54
|
+
password: text("password"),
|
|
55
|
+
createdAt: timestamp("created_at", { withTimezone: true })
|
|
56
|
+
.notNull()
|
|
57
|
+
.defaultNow(),
|
|
58
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
59
|
+
.notNull()
|
|
60
|
+
.defaultNow()
|
|
61
|
+
.$onUpdate(() => new Date()),
|
|
62
|
+
}, (table) => [uniqueIndex("account_provider_account_id_unique").on(table.providerId, table.accountId)]);
|
|
63
|
+
|
|
64
|
+
export const verification = pgTable("verification", {
|
|
65
|
+
id: text("id").primaryKey(),
|
|
66
|
+
identifier: text("identifier").notNull(),
|
|
67
|
+
value: text("value").notNull(),
|
|
68
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
69
|
+
createdAt: timestamp("created_at", { withTimezone: true })
|
|
70
|
+
.notNull()
|
|
71
|
+
.defaultNow(),
|
|
72
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
73
|
+
.notNull()
|
|
74
|
+
.defaultNow()
|
|
75
|
+
.$onUpdate(() => new Date()),
|
|
76
|
+
});
|
|
77
|
+
{{else}}
|
|
78
|
+
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
|
79
|
+
|
|
80
|
+
export const users = pgTable("users", {
|
|
81
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
82
|
+
email: text("email").notNull().unique(),
|
|
83
|
+
name: text("name"),
|
|
84
|
+
password: text("password").notNull(),
|
|
85
|
+
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
|
|
86
|
+
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
87
|
+
.defaultNow()
|
|
88
|
+
.$onUpdate(() => new Date()),
|
|
89
|
+
});
|
|
90
|
+
{{/if}}
|