This commit is contained in:
 Илья Шалонин 2025-10-29 13:43:43 +05:00
commit 8538ab969a
434 changed files with 44051 additions and 0 deletions

View file

@ -0,0 +1,3 @@
{
"extends": ["../../biome.json"]
}

View file

@ -0,0 +1,22 @@
{
"dependencies": {
"@repo/database": "workspace:*",
"@repo/logs": "workspace:*",
"@repo/auth": "workspace:*",
"@repo/utils": "workspace:*"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@repo/tsconfig": "workspace:*",
"@types/node": "^22.15.30",
"nanoid": "^5.1.5",
"tsx": "^4.19.4"
},
"name": "@repo/scripts",
"private": true,
"scripts": {
"create:user": "dotenv -c -e ../../.env -- tsx ./src/create-user.ts",
"type-check": "tsc --noEmit"
},
"version": "0.0.0"
}

View file

@ -0,0 +1,63 @@
import { auth } from "@repo/auth";
import { createUser, createUserAccount, getUserByEmail } from "@repo/database";
import { logger } from "@repo/logs";
import { nanoid } from "nanoid";
async function main() {
logger.info("Let's create a new user for your application!");
const email = await logger.prompt("Enter an email:", {
required: true,
placeholder: "admin@example.com",
type: "text",
});
const name = await logger.prompt("Enter a name:", {
required: true,
placeholder: "Adam Admin",
type: "text",
});
const isAdmin = await logger.prompt("Should user be an admin?", {
required: true,
type: "confirm",
default: false,
});
const authContext = await auth.$context;
const adminPassword = nanoid(16);
const hashedPassword = await authContext.password.hash(adminPassword);
// check if user exists
const user = await getUserByEmail(email);
if (user) {
logger.error("User with this email already exists!");
return;
}
const adminUser = await createUser({
email,
name,
role: isAdmin ? "admin" : "user",
emailVerified: true,
onboardingComplete: true,
});
if (!adminUser) {
logger.error("Failed to create user!");
return;
}
await createUserAccount({
userId: adminUser.id,
providerId: "credential",
accountId: adminUser.id,
hashedPassword,
});
logger.success("User created successfully!");
logger.info(`Here is the password for the new user: ${adminPassword}`);
}
main();

View file

@ -0,0 +1,5 @@
{
"extends": "@repo/tsconfig/base.json",
"include": ["**/*.ts"],
"exclude": ["dist", "build", "node_modules"]
}

View file

@ -0,0 +1,3 @@
{
"extends": ["../../biome.json"]
}

View file

@ -0,0 +1,13 @@
{
"devDependencies": {
"@biomejs/biome": "1.9.4",
"tailwindcss": "^4.1.8"
},
"main": "theme.css",
"name": "@repo/tailwind-config",
"private": true,
"scripts": {
"type-check": "tsc --noEmit"
},
"version": "0.0.0"
}

View file

@ -0,0 +1,275 @@
/**
* TailwindCSS v4.0 compatible replacement for `tailwindcss-animate`.
*
* WARNING: The asterisks are not supported by some formatters and linters. You
* might want to exclude this file from formatters and linters for now.
*
* @author Luca Bosin <https://github.com/Wombosvideo>
* @license MIT
*/
@theme inline {
--animation-delay-0: 0s;
--animation-delay-75: 75ms;
--animation-delay-100: 0.1s;
--animation-delay-150: 0.15s;
--animation-delay-200: 0.2s;
--animation-delay-300: 0.3s;
--animation-delay-500: 0.5s;
--animation-delay-700: 0.7s;
--animation-delay-1000: 1s;
--animation-repeat-0: 0;
--animation-repeat-1: 1;
--animation-repeat-infinite: infinite;
--animation-direction-normal: normal;
--animation-direction-reverse: reverse;
--animation-direction-alternate: alternate;
--animation-direction-alternate-reverse: alternate-reverse;
--animation-fill-mode-none: none;
--animation-fill-mode-forwards: forwards;
--animation-fill-mode-backwards: backwards;
--animation-fill-mode-both: both;
--animate-in: var(--tw-duration, 150ms) var(--tw-ease, ease) enter;
--animate-out: var(--tw-duration, 150ms) var(--tw-ease, ease) exit;
--percentage-0: 0;
--percentage-5: 0.05;
--percentage-10: 0.1;
--percentage-15: 0.15;
--percentage-20: 0.2;
--percentage-25: 0.25;
--percentage-30: 0.3;
--percentage-35: 0.35;
--percentage-40: 0.4;
--percentage-45: 0.45;
--percentage-50: 0.5;
--percentage-55: 0.55;
--percentage-60: 0.6;
--percentage-65: 0.65;
--percentage-70: 0.7;
--percentage-75: 0.75;
--percentage-80: 0.8;
--percentage-85: 0.85;
--percentage-90: 0.9;
--percentage-95: 0.95;
--percentage-100: 1;
--translate-1/2: 50%;
--translate-1/3: 33.333333%;
--translate-2/3: 66.666667%;
--translate-1/4: 25%;
--translate-2/4: 50%;
--translate-3/4: 75%;
--translate-full: 100%;
--translate-px: 1px;
--translate-0: 0px;
--translate-0.5: 0.125rem;
--translate-1: 0.25rem;
--translate-1.5: 0.375rem;
--translate-2: 0.5rem;
--translate-2.5: 0.625rem;
--translate-3: 0.75rem;
--translate-3.5: 0.875rem;
--translate-4: 1rem;
--translate-5: 1.25rem;
--translate-6: 1.5rem;
--translate-7: 1.75rem;
--translate-8: 2rem;
--translate-9: 2.25rem;
--translate-10: 2.5rem;
--translate-11: 2.75rem;
--translate-12: 3rem;
--translate-14: 3.5rem;
--translate-16: 4rem;
--translate-20: 5rem;
--translate-24: 6rem;
--translate-28: 7rem;
--translate-32: 8rem;
--translate-36: 9rem;
--translate-40: 10rem;
--translate-44: 11rem;
--translate-48: 12rem;
--translate-52: 13rem;
--translate-56: 14rem;
--translate-60: 15rem;
--translate-64: 16rem;
--translate-72: 18rem;
--translate-80: 20rem;
--translate-96: 24rem;
@keyframes enter {
from {
opacity: var(--tw-enter-opacity, 1);
transform: translate3d(
var(--tw-enter-translate-x, 0),
var(--tw-enter-translate-y, 0),
0
)
scale3d(
var(--tw-enter-scale, 1),
var(--tw-enter-scale, 1),
var(--tw-enter-scale, 1)
)
rotate(var(--tw-enter-rotate, 0));
}
}
@keyframes exit {
to {
opacity: var(--tw-exit-opacity, 1);
transform: translate3d(
var(--tw-exit-translate-x, 0),
var(--tw-exit-translate-y, 0),
0
)
scale3d(
var(--tw-exit-scale, 1),
var(--tw-exit-scale, 1),
var(--tw-exit-scale, 1)
)
rotate(var(--tw-exit-rotate, 0));
}
}
}
/*
* Tailwind's default `duration` utility sets the `--tw-duration` variable, so
* can set `animation-duration` directly in the animation definition in the
* `@theme` section above. Same goes for the `animation-timing-function`, set
* with `--tw-ease`.
*/
@utility delay-* {
animation-delay: calc(--value(number) * 1ms);
animation-delay: --value(--animation-delay-*, [duration], [*]);
}
@utility repeat-* {
animation-iteration-count: --value(--animation-repeat-*, integer);
}
@utility direction-* {
animation-direction: --value(--animation-direction-*);
}
@utility fill-mode-* {
animation-fill-mode: --value(--animation-fill-mode-*);
}
@utility running {
animation-play-state: running;
}
@utility paused {
animation-play-state: paused;
}
@utility fade-in {
--tw-enter-opacity: 0;
}
@utility fade-in-* {
--tw-enter-opacity: --value(--percentage-*, [*]);
}
@utility fade-out {
--tw-exit-opacity: 0;
}
@utility fade-out-* {
--tw-exit-opacity: --value(--percentage-*, [*]);
}
@utility zoom-in {
--tw-enter-scale: 0;
}
@utility zoom-in-* {
--tw-enter-scale: calc(--value([percentage]) / 100%);
--tw-enter-scale: calc(--value([ratio], [number]));
--tw-enter-scale: --value(--percentage-*);
}
@utility zoom-out {
--tw-exit-scale: 0;
}
@utility zoom-out-* {
--tw-exit-scale: calc(--value([percentage]) / 100%);
--tw-exit-scale: calc(--value([ratio], [number]));
--tw-exit-scale: --value(--percentage-*);
}
@utility spin-in {
--tw-enter-rotate: 30deg;
}
@utility spin-in-* {
--tw-enter-rotate: calc(--value(number) * 1deg);
--tw-enter-rotate: --value(--rotate-*, [angle]);
}
@utility spin-out {
--tw-exit-rotate: 30deg;
}
@utility spin-out-* {
--tw-exit-rotate: calc(--value(number) * 1deg);
--tw-exit-rotate: --value(--rotate-*, [angle]);
}
@utility slide-in-from-top {
--tw-enter-translate-y: -100%;
}
@utility slide-in-from-top-* {
--tw-enter-translate-y: calc(--value(integer) * var(--spacing) * -1);
--tw-enter-translate-y: calc(--value(--translate-*, [percentage], ratio, [length]) * -1);
}
@utility slide-in-from-bottom {
--tw-enter-translate-y: 100%;
}
@utility slide-in-from-bottom-* {
--tw-enter-translate-y: calc(--value(integer) * var(--spacing));
--tw-enter-translate-y: --value(--translate-*, [percentage], ratio, [length]);
}
@utility slide-in-from-left {
--tw-enter-translate-x: -100%;
}
@utility slide-in-from-left-* {
--tw-enter-translate-x: calc(--value(integer) * var(--spacing) * -1);
--tw-enter-translate-x: calc(--value(--translate-*, [percentage], ratio, [length]) * -1);
}
@utility slide-in-from-right {
--tw-enter-translate-x: 100%;
}
@utility slide-in-from-right-* {
--tw-enter-translate-x: calc(--value(integer) * var(--spacing));
--tw-enter-translate-x: --value(--translate-*, [percentage], ratio, [length]);
}
@utility slide-out-to-top {
--tw-exit-translate-y: -100%;
}
@utility slide-out-to-top-* {
--tw-exit-translate-y: calc(--value(integer) * var(--spacing) * -1);
--tw-exit-translate-y: calc(--value(--translate-*, [percentage], ratio, [length]) * -1);
}
@utility slide-out-to-bottom {
--tw-exit-translate-y: 100%;
}
@utility slide-out-to-bottom-* {
--tw-exit-translate-y: calc(--value(integer) * var(--spacing));
--tw-exit-translate-y: --value(--translate-*, [percentage], ratio, [length]);
}
@utility slide-out-to-left {
--tw-exit-translate-x: -100%;
}
@utility slide-out-to-left-* {
--tw-exit-translate-x: calc(--value(integer) * var(--spacing) * -1);
--tw-exit-translate-x: calc(--value(--translate-*, [percentage], ratio, [length]) * -1);
}
@utility slide-out-to-right {
--tw-exit-translate-x: 100%;
}
@utility slide-out-to-right-* {
--tw-exit-translate-x: calc(--value(integer) * var(--spacing));
--tw-exit-translate-x: --value(--translate-*, [percentage], ratio, [length]);
}

131
tooling/tailwind/theme.css Normal file
View file

@ -0,0 +1,131 @@
@theme {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-highlight: var(--highlight);
--color-highlight-foreground: var(--highlight-foreground);
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
--font-sans: var(--font-geist-sans);
--animation-accordion-down: accordion-down 0.2s ease-out;
--animation-accordion-up: accordion-up 0.2s ease-out;
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
}
@layer base {
:root {
--border: #e3ebf6;
--input: #c7ced8;
--ring: #4e6df5;
--background: #fafafe;
--foreground: #292b35;
--primary: #4e6df5;
--primary-foreground: #f6f7f9;
--secondary: #292b35;
--secondary-foreground: #ffffff;
--destructive: #ef4444;
--destructive-foreground: #ffffff;
--success: #39a561;
--success-foreground: #ffffff;
--muted: #f8fafc;
--muted-foreground: #64748b;
--accent: #ddddea;
--accent-foreground: #292b35;
--popover: #ffffff;
--popover-foreground: #292b35;
--card: #ffffff;
--card-foreground: #292b35;
--highlight: #e5a158;
--highlight-foreground: #ffffff;
--radius: 0.75rem;
/* fumadocs */
--fd-banner-height: 4.5rem;
}
.dark {
--border: #2b303d;
--input: #4c5362;
--ring: #5581f7;
--background: #070d12;
--foreground: #e9eef3;
--primary: #5581f7;
--primary-foreground: #091521;
--secondary: #e9eef3;
--secondary-foreground: #091521;
--destructive: #ef4444;
--destructive-foreground: #ffffff;
--success: #39a561;
--success-foreground: #ffffff;
--muted: #020817;
--muted-foreground: #94a3b8;
--accent: #1e293b;
--accent-foreground: #f8fafc;
--popover: #0d1116;
--popover-foreground: #e9eef3;
--card: #0d1116;
--card-foreground: #e9eef3;
--highlight: #e5a158;
--highlight-foreground: #ffffff;
}
*,
::after,
::before,
::backdrop,
::file-selector-button {
@apply border-border;
}
}
@utility container {
margin-inline: auto;
padding-inline: 1.5rem;
width: 100%;
max-width: var(--container-7xl);
}
@utility no-scrollbar {
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none;
scrollbar-width: none;
}

View file

@ -0,0 +1,24 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"allowJs": true,
"composite": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"incremental": true,
"inlineSources": false,
"isolatedModules": true,
"module": "Preserve",
"target": "ES2021",
"moduleResolution": "bundler",
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"strictNullChecks": true
},
"display": "Default",
"exclude": ["node_modules", "dist", ".next", "build"]
}

View file

@ -0,0 +1,3 @@
{
"extends": ["../../biome.json"]
}

View file

@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"jsx": "preserve",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"noEmit": true,
"plugins": [
{
"name": "next"
}
],
"target": "es5"
},
"display": "Next.js",
"exclude": ["node_modules"],
"extends": "./base.json",
"include": ["next-env.d.ts"]
}

View file

@ -0,0 +1,11 @@
{
"devDependencies": {
"@biomejs/biome": "1.9.4"
},
"name": "@repo/tsconfig",
"private": true,
"publishConfig": {
"access": "public"
},
"version": "0.0.0"
}

View file

@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"jsx": "preserve",
"lib": ["ES2021", "DOM"],
"module": "ESNext",
"target": "ES6"
},
"display": "React Library",
"extends": "./base.json"
}