Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .docker/linux-vrt/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ COPY apps/zunpachi/package.json ./apps/zunpachi/
COPY packages/better-auth/package.json ./packages/better-auth/
COPY packages/better-auth-database/package.json ./packages/better-auth-database/
COPY packages/domain/package.json ./packages/domain/
COPY packages/domain-impl/package.json ./packages/domain-impl/
COPY packages/presentation-trpc/package.json ./packages/presentation-trpc/
COPY packages/shadcn/package.json ./packages/shadcn/

# Install dependencies
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ jobs:
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-bun-turbo
- run: bun run test:unit
- name: roppoh test
run: bun run test:unit
working-directory: apps/roppoh
- run: bun run test
- name: fujimatsu test
run: bun run test
working-directory: apps/fujimatsu
- name: domain-impl test
run: bun run test
working-directory: packages/domain-impl
20 changes: 4 additions & 16 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
{
"mcpServers": {
"cloudflare": {
"type": "http",
"url": "https://docs.mcp.cloudflare.com/mcp"
},
"context7": {
"args": ["-y", "@upstash/context7-mcp"],
"command": "bunx",
"type": "stdio"
},
"dev3000": {
"type": "http",
"url": "http://localhost:3684/mcp"
},
"git": {
"args": ["mcp-server-git"],
"command": "uvx"
},
"playwright": {
"args": ["@playwright/mcp@latest"],
"command": "bunx"
},
"sequential-thinking": {
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
"command": "bunx"
}
}
}
4 changes: 2 additions & 2 deletions apps/roppoh/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"workers-og": "^0.0.27"
},
"devDependencies": {
"@cloudflare/vite-plugin": "^1.17.1",
"@cloudflare/vite-plugin": "^1.19.0",
"@cloudflare/workers-types": "^4.20250922.0",
"@react-router/dev": "^7.8.0",
"@tailwindcss/vite": "^4.1.14",
Expand All @@ -63,7 +63,7 @@
"vite-tsconfig-paths": "^4.3.2",
"vitest": "4.0.3",
"vitest-browser-react": "^2.0.2",
"wrangler": "^4.40.1"
"wrangler": "^4.54.0"
},
"name": "@roppoh/roppoh",
"peerDependencies": {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions apps/roppoh/turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@
"extends": ["//"],
"tasks": {
"build": {
"inputs": ["src", "./*.ts"],
"outputs": ["build/**"]
},
"cf-typegen": {
"inputs": ["wrangler.jsonc"],
"outputs": ["worker-configuration.d.ts"]
},
"check:type": {
"inputs": [
"src",
"./*.ts",
"$TURBO_ROOT$/tsconfig.json",
"./tsconfig.json"
],
"outputs": [".react-router/types/**"]
}
}
Expand Down
18 changes: 18 additions & 0 deletions apps/zunpachi/src/middlewares/better-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Context } from "hono";
import { cors } from "hono/cors";
import type { HonoEnv } from "./dependency-injection";

export const betterAuthCorsMiddleware = cors({
allowHeaders: ["Content-Type", "Authorization"],
allowMethods: ["POST", "GET", "OPTIONS"],
credentials: true,
exposeHeaders: ["Content-Length"],
maxAge: 600,
origin: async (_, c: Context<HonoEnv>) => {
if (c.env.NODE_ENV !== "production") {
return "*";
}

return c.env.CORS_DOMAIN;
},
});
6 changes: 3 additions & 3 deletions apps/zunpachi/worker-configuration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9403,7 +9403,7 @@ interface IncomingRequestCfPropertiesTLSClientAuthPlaceholder {
certNotAfter: "";
}
/** Possible outcomes of TLS verification */
declare type CertVerificationStatus =
declare type CertVerificationStatus =
/** Authentication succeeded */
"SUCCESS"
/** No certificate was presented */
Expand Down Expand Up @@ -9467,7 +9467,7 @@ interface D1ExecResult {
count: number;
duration: number;
}
type D1SessionConstraint =
type D1SessionConstraint =
// Indicates that the first query should go to the primary, and the rest queries
// using the same D1DatabaseSession will go to any replica that is consistent with
// the bookmark maintained by the session (returned by the first query).
Expand Down Expand Up @@ -10048,7 +10048,7 @@ declare namespace Rpc {
// The reason for using a generic type here is to build a serializable subset of structured
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
type Serializable<T> =
type Serializable<T> =
// Structured cloneables
BaseType
// Structured cloneable composites
Expand Down
292 changes: 220 additions & 72 deletions bun.lock

Large diffs are not rendered by default.

204 changes: 204 additions & 0 deletions packages/better-auth-database/auth-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import { relations, sql } from "drizzle-orm";
import {
index,
integer,
sqliteTable,
text,
uniqueIndex,
} from "drizzle-orm/sqlite-core";

export const user = sqliteTable("user", {
banExpires: integer("ban_expires", { mode: "timestamp_ms" }),
banned: integer("banned", { mode: "boolean" }).default(false),
banReason: text("ban_reason"),
createdAt: integer("created_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
email: text("email").notNull().unique(),
emailVerified: integer("email_verified", { mode: "boolean" })
.default(false)
.notNull(),
id: text("id").primaryKey(),
image: text("image"),
name: text("name").notNull(),
role: text("role"),
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
});

export const session = sqliteTable(
"session",
{
activeOrganizationId: text("active_organization_id"),
createdAt: integer("created_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
id: text("id").primaryKey(),
impersonatedBy: text("impersonated_by"),
ipAddress: text("ip_address"),
token: text("token").notNull().unique(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
},
(table) => [index("session_userId_idx").on(table.userId)],
);

export const account = sqliteTable(
"account",
{
accessToken: text("access_token"),
accessTokenExpiresAt: integer("access_token_expires_at", {
mode: "timestamp_ms",
}),
accountId: text("account_id").notNull(),
createdAt: integer("created_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
id: text("id").primaryKey(),
idToken: text("id_token"),
password: text("password"),
providerId: text("provider_id").notNull(),
refreshToken: text("refresh_token"),
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
mode: "timestamp_ms",
}),
scope: text("scope"),
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
},
(table) => [index("account_userId_idx").on(table.userId)],
);

export const verification = sqliteTable(
"verification",
{
createdAt: integer("created_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
value: text("value").notNull(),
},
(table) => [index("verification_identifier_idx").on(table.identifier)],
);

export const organization = sqliteTable(
"organization",
{
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
id: text("id").primaryKey(),
logo: text("logo"),
metadata: text("metadata"),
name: text("name").notNull(),
slug: text("slug").notNull().unique(),
},
(table) => [uniqueIndex("organization_slug_uidx").on(table.slug)],
);

export const member = sqliteTable(
"member",
{
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
id: text("id").primaryKey(),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id, { onDelete: "cascade" }),
role: text("role").default("member").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
},
(table) => [
index("member_organizationId_idx").on(table.organizationId),
index("member_userId_idx").on(table.userId),
],
);

export const invitation = sqliteTable(
"invitation",
{
createdAt: integer("created_at", { mode: "timestamp_ms" })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
email: text("email").notNull(),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
id: text("id").primaryKey(),
inviterId: text("inviter_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id, { onDelete: "cascade" }),
role: text("role"),
status: text("status").default("pending").notNull(),
},
(table) => [
index("invitation_organizationId_idx").on(table.organizationId),
index("invitation_email_idx").on(table.email),
],
);

export const userRelations = relations(user, ({ many }) => ({
accounts: many(account),
invitations: many(invitation),
members: many(member),
sessions: many(session),
}));

export const sessionRelations = relations(session, ({ one }) => ({
user: one(user, {
fields: [session.userId],
references: [user.id],
}),
}));

export const accountRelations = relations(account, ({ one }) => ({
user: one(user, {
fields: [account.userId],
references: [user.id],
}),
}));

export const organizationRelations = relations(organization, ({ many }) => ({
invitations: many(invitation),
members: many(member),
}));

export const memberRelations = relations(member, ({ one }) => ({
organization: one(organization, {
fields: [member.organizationId],
references: [organization.id],
}),
user: one(user, {
fields: [member.userId],
references: [user.id],
}),
}));

export const invitationRelations = relations(invitation, ({ one }) => ({
organization: one(organization, {
fields: [invitation.organizationId],
references: [organization.id],
}),
user: one(user, {
fields: [invitation.inviterId],
references: [user.id],
}),
}));
4 changes: 1 addition & 3 deletions packages/better-auth-database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
},
"exports": {
".": {
"default": "./src/index.ts",
"import": "./src/index.ts",
"types": "./src/index.ts"
"default": "./src/index.ts"
}
},
"name": "@roppoh/better-auth-database",
Expand Down
7 changes: 6 additions & 1 deletion packages/better-auth-database/src/auth.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { admin, organization } from "better-auth/plugins";
import Database from "better-sqlite3";

type BetterAuth = ReturnType<typeof betterAuth>;

export const auth: BetterAuth = betterAuth({
database: new Database("database.sqlite"),
database: drizzleAdapter(new Database("database.sqlite"), {
provider: "sqlite",
}),
plugins: [organization(), admin()],
telemetry: {
enabled: false,
},
Expand Down
14 changes: 14 additions & 0 deletions packages/better-auth-database/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://turborepo.com/schema.json",
"extends": ["//"],
"tasks": {
"check:type": {
"inputs": [
"src",
"$TURBO_ROOT$/tsconfig.json",
"./*.ts",
"./tsconfig.json"
]
}
}
}
Loading
Loading