startx 0.7.2 → 0.9.0
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/.prettierrc.js +2 -2
- package/.vscode/settings.json +2 -1
- package/apps/core-server/package.json +1 -1
- package/apps/core-server/src/index.ts +0 -1
- package/apps/startx-cli/dist/index.mjs +2 -2
- package/apps/startx-cli/src/commands/init.ts +179 -257
- package/apps/startx-cli/src/configs/deps.ts +6 -1
- package/apps/startx-cli/src/configs/files.ts +3 -4
- package/apps/startx-cli/src/configs/scripts.ts +25 -7
- package/apps/startx-cli/src/types.ts +18 -6
- package/apps/startx-cli/src/utils/cli-utils.ts +60 -49
- package/apps/startx-cli/src/utils/file-handler.ts +14 -5
- package/biome.json +1 -1
- package/configs/eslint-config/eslint.config.ts +0 -0
- package/configs/eslint-config/src/configs/base.ts +32 -79
- package/configs/eslint-config/src/configs/extend.ts +2 -2
- package/configs/eslint-config/src/configs/frontend.ts +29 -19
- package/configs/eslint-config/src/configs/node.ts +46 -6
- package/configs/vitest-config/package.json +3 -2
- package/package.json +3 -2
- package/packages/@repo/db/drizzle.config.ts +14 -0
- package/packages/@repo/db/package.json +5 -1
- package/packages/@repo/db/src/index.ts +1 -1
- package/packages/@repo/lib/src/otp-module/index.ts +6 -13
- package/packages/@repo/lib/tsconfig.json +2 -1
- package/packages/@repo/mail/eslint.config.ts +2 -2
- package/packages/@repo/mail/src/emails/admin/OtpEmail.tsx +3 -9
- package/packages/@repo/mail/src/emails/emails.ts +1 -0
- package/packages/@repo/mail/src/index.ts +10 -9
- package/packages/@repo/mail/tsconfig.json +4 -2
- package/packages/ui/package.json +1 -0
- package/packages/ui/src/components/ui/command.tsx +5 -15
- package/pnpm-workspace.yaml +1 -0
- package/turbo.json +9 -0
- package/apps/startx-cli/src/utils/config.ts +0 -104
|
@@ -1,10 +1,50 @@
|
|
|
1
|
-
import { defineConfig } from "eslint/config";
|
|
2
1
|
import globals from "globals";
|
|
2
|
+
import tseslint from "typescript-eslint";
|
|
3
|
+
|
|
3
4
|
import { baseConfig } from "./base.js";
|
|
4
5
|
|
|
5
|
-
export const nodeConfig =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export const nodeConfig = tseslint.config(
|
|
7
|
+
...baseConfig,
|
|
8
|
+
|
|
9
|
+
// 1. Backend/Node Specific Globals & Environments
|
|
10
|
+
{
|
|
11
|
+
files: ["**/*.ts", "**/*.js", "**/*.cjs", "**/*.mjs"],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
// "latest" perfectly aligns with Node 20+ (ES2023/ES2024 features)
|
|
14
|
+
ecmaVersion: "latest",
|
|
15
|
+
sourceType: "module",
|
|
16
|
+
globals: {
|
|
17
|
+
...globals.node,
|
|
18
|
+
...globals.nodeBuiltin, // Explicitly adds modern Node built-ins (like fetch, structuredClone)
|
|
19
|
+
},
|
|
20
|
+
},
|
|
9
21
|
},
|
|
10
|
-
|
|
22
|
+
|
|
23
|
+
// 2. Node-Specific Overrides & Best Practices
|
|
24
|
+
{
|
|
25
|
+
files: ["**/*.ts", "**/*.js"],
|
|
26
|
+
rules: {
|
|
27
|
+
// Enforce the 'node:' protocol for built-ins (e.g., `import fs from 'node:fs'`)
|
|
28
|
+
// This is a modern Node.js standard that improves performance and security
|
|
29
|
+
"unicorn/prefer-node-protocol": "error",
|
|
30
|
+
|
|
31
|
+
// Prevent accidental use of obscure browser globals that sometimes slip through
|
|
32
|
+
"no-restricted-globals": [
|
|
33
|
+
"error",
|
|
34
|
+
{
|
|
35
|
+
name: "name",
|
|
36
|
+
message: "Global 'name' is deprecated. Did you mean to declare a local variable?",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "event",
|
|
40
|
+
message: "Global 'event' is a browser feature. Do not use it in Node.js.",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
// In Node apps, developers often accidentally leave floating promises
|
|
45
|
+
// which can cause unhandled promise rejections crashing the server.
|
|
46
|
+
// (This inherits from baseConfig, but I am noting it here as a critical backend safeguard).
|
|
47
|
+
// "@typescript-eslint/no-floating-promises": "error",
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
);
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"
|
|
6
|
+
"jsdom": "^29.0.1",
|
|
7
7
|
"typescript-config": "workspace:*",
|
|
8
|
-
"vite": "catalog:"
|
|
8
|
+
"vite": "catalog:",
|
|
9
|
+
"vitest": "catalog:"
|
|
9
10
|
},
|
|
10
11
|
"exports": {
|
|
11
12
|
".": "./src/index.ts",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "startx",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/avinashid/startx.git"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"typecheck": "turbo typecheck",
|
|
32
32
|
"clean": "turbo clean",
|
|
33
33
|
"test": "turbo test",
|
|
34
|
-
"format": "turbo format"
|
|
34
|
+
"format": "turbo format",
|
|
35
|
+
"db:push": "turbo db:push"
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from "drizzle-kit";
|
|
2
|
+
import { defineEnv } from "@repo/env";
|
|
3
|
+
import z from "zod";
|
|
4
|
+
const env = defineEnv({
|
|
5
|
+
DATABASE_URL: z.string(),
|
|
6
|
+
});
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
out: "./drizzle",
|
|
9
|
+
schema: "./src/schema/index.ts",
|
|
10
|
+
dialect: "postgresql",
|
|
11
|
+
dbCredentials: {
|
|
12
|
+
url: env.DATABASE_URL!,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
"format:check": "biome ci .",
|
|
12
12
|
"lint": "eslint .",
|
|
13
13
|
"lint:fix": "eslint . --fix",
|
|
14
|
+
"db:push": "drizzle-kit push",
|
|
14
15
|
"watch": "tsc -p tsconfig.build.json --watch"
|
|
15
16
|
},
|
|
16
17
|
"exports": "./src/index.ts",
|
|
17
18
|
"devDependencies": {
|
|
18
19
|
"@types/pg": "catalog:",
|
|
20
|
+
"drizzle-kit": "catalog:",
|
|
19
21
|
"eslint-config": "workspace:*",
|
|
20
22
|
"vitest-config": "workspace:*",
|
|
21
23
|
"typescript-config": "workspace:*"
|
|
@@ -30,8 +32,10 @@
|
|
|
30
32
|
"node",
|
|
31
33
|
"backend"
|
|
32
34
|
],
|
|
35
|
+
"gTags": [
|
|
36
|
+
"db"
|
|
37
|
+
],
|
|
33
38
|
"tags": [
|
|
34
|
-
"db",
|
|
35
39
|
"drizzle"
|
|
36
40
|
],
|
|
37
41
|
"requiredDeps": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ENV } from "@repo/env";
|
|
2
2
|
import { logger } from "@repo/logger";
|
|
3
|
-
import {
|
|
3
|
+
import { EmailTemplate } from "@repo/mail";
|
|
4
4
|
import { RedisStore } from "@repo/redis";
|
|
5
5
|
|
|
6
6
|
import { HashingModule } from "../hashing-module/index.js";
|
|
@@ -41,13 +41,10 @@ export class OTPModule {
|
|
|
41
41
|
logger?.info("otp: test-mode - OTP generated", { email: normalizedEmail, otp: otpStr });
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
const html = await
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`Your OTP is ${otpStr}`,
|
|
49
|
-
html
|
|
50
|
-
);
|
|
44
|
+
const html = await EmailTemplate("VerifyEmailOtp", {
|
|
45
|
+
verificationCode: otpStr,
|
|
46
|
+
});
|
|
47
|
+
await SMTPMailService.sendMail(normalizedEmail, `OTP for ${normalizedEmail}`, `Your OTP is ${otpStr}`, html);
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
static async verifyMailOTP(email: string, otp: string, deleteOtp = false): Promise<boolean> {
|
|
@@ -67,11 +64,7 @@ export class OTPModule {
|
|
|
67
64
|
if (deleteOtp) {
|
|
68
65
|
await redisOtpStore.del(normalizedEmail);
|
|
69
66
|
} else {
|
|
70
|
-
await redisOtpStore.set(
|
|
71
|
-
normalizedEmail,
|
|
72
|
-
{ ...rows, status: "verified" },
|
|
73
|
-
this.otpExpirationMs
|
|
74
|
-
);
|
|
67
|
+
await redisOtpStore.set(normalizedEmail, { ...rows, status: "verified" }, this.otpExpirationMs);
|
|
75
68
|
}
|
|
76
69
|
return true;
|
|
77
70
|
}
|
|
@@ -13,12 +13,7 @@ import {
|
|
|
13
13
|
Text,
|
|
14
14
|
} from "@react-email/components";
|
|
15
15
|
import React from "react";
|
|
16
|
-
|
|
17
|
-
export default function VerifyEmailOtp({
|
|
18
|
-
verificationCode = "596853",
|
|
19
|
-
}: {
|
|
20
|
-
verificationCode: string;
|
|
21
|
-
}) {
|
|
16
|
+
export function VerifyEmailOtp({ verificationCode = "596853" }: { verificationCode: string }) {
|
|
22
17
|
return (
|
|
23
18
|
<Html>
|
|
24
19
|
<Head>
|
|
@@ -57,9 +52,8 @@ export default function VerifyEmailOtp({
|
|
|
57
52
|
<Hr />
|
|
58
53
|
<Section style={lowerSection}>
|
|
59
54
|
<Text style={cautionText}>
|
|
60
|
-
This OTP is valid for 10 minutes. Please do not share this code with anyone for
|
|
61
|
-
|
|
62
|
-
our support team immediately.
|
|
55
|
+
This OTP is valid for 10 minutes. Please do not share this code with anyone for security reasons. If you
|
|
56
|
+
did not request this, please ignore this email or contact our support team immediately.
|
|
63
57
|
</Text>
|
|
64
58
|
</Section>
|
|
65
59
|
</Section>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./admin/OtpEmail.js";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { render } from "@react-email/render";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
import React, { createElement } from "react";
|
|
3
|
+
import * as emails from "./emails/emails.js";
|
|
4
|
+
export type AvailableEmails = keyof typeof emails;
|
|
5
|
+
export type EmailProps<T extends AvailableEmails> = React.ComponentProps<(typeof emails)[T]>;
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8
|
+
export function EmailTemplate<T extends AvailableEmails>(name: T, props: EmailProps<T>) {
|
|
9
|
+
// eslint-disable-next-line import-x/namespace
|
|
10
|
+
const Component = emails[name] as React.ElementType;
|
|
11
|
+
return render(createElement(Component, props));
|
|
11
12
|
}
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
"extends": "typescript-config/tsconfig.frontend.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"rootDir": ".",
|
|
5
|
-
"types": ["node"],
|
|
5
|
+
"types": ["node", "react"],
|
|
6
6
|
"baseUrl": "src",
|
|
7
7
|
"jsx": "react",
|
|
8
8
|
"tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
|
|
9
9
|
"experimentalDecorators": true,
|
|
10
|
-
"emitDecoratorMetadata": true
|
|
10
|
+
"emitDecoratorMetadata": true,
|
|
11
|
+
"moduleResolution": "nodenext",
|
|
12
|
+
"module": "nodenext"
|
|
11
13
|
},
|
|
12
14
|
"include": ["src/**/*.ts", "src/**/*.tsx"]
|
|
13
15
|
}
|
package/packages/ui/package.json
CHANGED
|
@@ -4,8 +4,9 @@ import type { DialogProps } from "@radix-ui/react-dialog";
|
|
|
4
4
|
import { Command as CommandPrimitive } from "cmdk";
|
|
5
5
|
import { Search } from "lucide-react";
|
|
6
6
|
import * as React from "react";
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
import { Dialog, DialogContent } from "./dialog";
|
|
9
|
+
import { cn } from "../lib/utils";
|
|
9
10
|
|
|
10
11
|
const Command = React.forwardRef<
|
|
11
12
|
React.ElementRef<typeof CommandPrimitive>,
|
|
@@ -70,9 +71,7 @@ CommandList.displayName = CommandPrimitive.List.displayName;
|
|
|
70
71
|
const CommandEmpty = React.forwardRef<
|
|
71
72
|
React.ElementRef<typeof CommandPrimitive.Empty>,
|
|
72
73
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
73
|
-
>((props, ref) =>
|
|
74
|
-
<CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
|
|
75
|
-
));
|
|
74
|
+
>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />);
|
|
76
75
|
|
|
77
76
|
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
78
77
|
|
|
@@ -96,11 +95,7 @@ const CommandSeparator = React.forwardRef<
|
|
|
96
95
|
React.ElementRef<typeof CommandPrimitive.Separator>,
|
|
97
96
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
98
97
|
>(({ className, ...props }, ref) => (
|
|
99
|
-
<CommandPrimitive.Separator
|
|
100
|
-
ref={ref}
|
|
101
|
-
className={cn("-mx-1 h-px bg-border", className)}
|
|
102
|
-
{...props}
|
|
103
|
-
/>
|
|
98
|
+
<CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
|
|
104
99
|
));
|
|
105
100
|
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
106
101
|
|
|
@@ -122,12 +117,7 @@ const CommandItem = React.forwardRef<
|
|
|
122
117
|
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
123
118
|
|
|
124
119
|
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
125
|
-
return (
|
|
126
|
-
<span
|
|
127
|
-
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
|
|
128
|
-
{...props}
|
|
129
|
-
/>
|
|
130
|
-
);
|
|
120
|
+
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
|
|
131
121
|
};
|
|
132
122
|
CommandShortcut.displayName = "CommandShortcut";
|
|
133
123
|
|
package/pnpm-workspace.yaml
CHANGED
package/turbo.json
CHANGED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
-
|
|
3
|
-
import { Packages } from "../types";
|
|
4
|
-
|
|
5
|
-
export const packages = Packages({
|
|
6
|
-
"eslint-config": {
|
|
7
|
-
source: "./configs/eslint-config",
|
|
8
|
-
dependencies: [],
|
|
9
|
-
devDependencies: ["typescript-config"],
|
|
10
|
-
optional: ["vitest-config"],
|
|
11
|
-
dir: ["src"],
|
|
12
|
-
file: ["plugins.d.ts"],
|
|
13
|
-
tags: ["common"],
|
|
14
|
-
},
|
|
15
|
-
"typescript-config": {
|
|
16
|
-
source: "./configs/typescript-config",
|
|
17
|
-
dependencies: [],
|
|
18
|
-
devDependencies: [],
|
|
19
|
-
dir: [],
|
|
20
|
-
files: ["tsconfig.common.json", "tsconfig.frontend.json", "tsconfig.node.json"],
|
|
21
|
-
tags: ["required"],
|
|
22
|
-
},
|
|
23
|
-
"vitest-config": {
|
|
24
|
-
source: "./configs/vitest-config",
|
|
25
|
-
dependencies: ["typescript-config"],
|
|
26
|
-
devDependencies: ["eslint-config"],
|
|
27
|
-
dir: [],
|
|
28
|
-
tags: ["required"],
|
|
29
|
-
},
|
|
30
|
-
"@repo/ui": {
|
|
31
|
-
source: "./packages/ui",
|
|
32
|
-
dependencies: [],
|
|
33
|
-
devDependencies: ["typescript-config"],
|
|
34
|
-
optional: ["eslint-config"],
|
|
35
|
-
dir: [
|
|
36
|
-
"src/components/lib",
|
|
37
|
-
"src/components/util",
|
|
38
|
-
"src/components/ilb",
|
|
39
|
-
"src/components/util",
|
|
40
|
-
"src/components/custom",
|
|
41
|
-
"src/components/extensions",
|
|
42
|
-
"src/components/hooks",
|
|
43
|
-
"src/components/ui",
|
|
44
|
-
],
|
|
45
|
-
files: [
|
|
46
|
-
"components.json",
|
|
47
|
-
"tailwind.config.ts",
|
|
48
|
-
"postcss.config.ts",
|
|
49
|
-
"src/globals.css",
|
|
50
|
-
"src/lucide.ts",
|
|
51
|
-
],
|
|
52
|
-
tags: ["common", "react"],
|
|
53
|
-
},
|
|
54
|
-
"@repo/constants": {
|
|
55
|
-
source: "./packages/@repo/constants",
|
|
56
|
-
dependencies: [],
|
|
57
|
-
devDependencies: ["typescript-config"],
|
|
58
|
-
optional: ["eslint-config"],
|
|
59
|
-
dir: ["src"],
|
|
60
|
-
tags: ["common"],
|
|
61
|
-
},
|
|
62
|
-
"@repo/env": {
|
|
63
|
-
source: "./packages/@repo/env",
|
|
64
|
-
dependencies: [],
|
|
65
|
-
devDependencies: ["typescript-config"],
|
|
66
|
-
optional: ["eslint-config", "vitest-config"],
|
|
67
|
-
dir: ["src"],
|
|
68
|
-
tags: ["common", "node"],
|
|
69
|
-
},
|
|
70
|
-
"@repo/db": {
|
|
71
|
-
source: "./packages/@repo/db",
|
|
72
|
-
dependencies: ["@repo/env"],
|
|
73
|
-
devDependencies: ["typescript-config"],
|
|
74
|
-
optional: ["eslint-config"],
|
|
75
|
-
dir: ["src"],
|
|
76
|
-
tags: ["common", "node"],
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
"@repo/lib": {
|
|
80
|
-
source: "./packages/@repo/lib",
|
|
81
|
-
dependencies: ["@repo/env", "@repo/mail", "@repo/db"],
|
|
82
|
-
devDependencies: ["typescript-config"],
|
|
83
|
-
optional: ["eslint-config", "vitest-config"],
|
|
84
|
-
dir: ["src"],
|
|
85
|
-
tags: ["common", "node"],
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
"@repo/mail": {
|
|
89
|
-
source: "./packages/@repo/mail",
|
|
90
|
-
dependencies: [],
|
|
91
|
-
devDependencies: ["typescript-config"],
|
|
92
|
-
optional: ["eslint-config"],
|
|
93
|
-
dir: ["src"],
|
|
94
|
-
tags: ["common", "node"],
|
|
95
|
-
},
|
|
96
|
-
"@repo/redis": {
|
|
97
|
-
source: "./packages/@repo/redis",
|
|
98
|
-
dependencies: [],
|
|
99
|
-
devDependencies: ["typescript-config"],
|
|
100
|
-
optional: ["eslint-config"],
|
|
101
|
-
dir: ["src"],
|
|
102
|
-
tags: ["common", "node", "extra"],
|
|
103
|
-
},
|
|
104
|
-
});
|