update: playwright and solid, tanstack-start exmaple
Run Tests / test (push) Successful in 6m46s

This commit is contained in:
2026-09-28 18:42:26 +05:30
parent dfa37b5244
commit a0454f82d6
10 changed files with 87 additions and 89 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
"type": "module",
"sideEffects": false,
"bin": "./dist/cli/index.js",
"version": "0.0.1",
"version": "0.0.2",
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
"homepage": "https://gitea.bsws.in/shishantbiswas/userbase",
"repository": {
@@ -88,7 +88,7 @@
"@libsql/client": "^0.15.15",
"@mantine/modals": "^7.17.1",
"@mantine/notifications": "^7.17.1",
"@playwright/test": "^1.56.1",
"@playwright/test": "^1.63.0",
"@rjsf/core": "5.22.2",
"@rjsf/utils": "5.22.0",
"@standard-schema/spec": "^1.0.0",
+4 -6
View File
@@ -59,7 +59,7 @@
"@libsql/client": "^0.15.15",
"@mantine/modals": "^7.17.1",
"@mantine/notifications": "^7.17.1",
"@playwright/test": "^1.56.1",
"@playwright/test": "^1.63.0",
"@rjsf/core": "5.22.2",
"@rjsf/utils": "5.22.0",
"@standard-schema/spec": "^1.0.0",
@@ -806,7 +806,7 @@
"@plasmicapp/watcher": ["@plasmicapp/watcher@1.0.83", "", { "dependencies": { "socket.io-client": "^4.1.2" } }, "sha512-0XTCsTydTBfOE5al9QOyW89kigjzU9az2JL4n7e3+fVlStEqbhYSB9PIa+Bhiv1iVN91V7xjUSyVJXloWJgwPg=="],
"@playwright/test": ["@playwright/test@1.56.1", "", { "dependencies": { "playwright": "1.56.1" }, "bin": { "playwright": "cli.js" } }, "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg=="],
"@playwright/test": ["@playwright/test@1.63.0", "", { "dependencies": { "playwright": "1.63.0" }, "bin": { "playwright": "cli.js" } }, "sha512-oxMK4vllB9RK5NQ2l1pq1IfOf2AvnEuj/vYGDj0H2nMtmtZpKtCwt/l00GEO6xjGfpBNAvjovvYdCm50dRQkpQ=="],
"@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="],
@@ -2744,9 +2744,9 @@
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
"playwright": ["playwright@1.56.1", "", { "dependencies": { "playwright-core": "1.56.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw=="],
"playwright": ["playwright@1.63.0", "", { "dependencies": { "playwright-core": "1.63.0" }, "bin": { "playwright": "cli.js" } }, "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg=="],
"playwright-core": ["playwright-core@1.56.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ=="],
"playwright-core": ["playwright-core@1.63.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg=="],
"plimit-lit": ["plimit-lit@1.6.1", "", { "dependencies": { "queue-lit": "^1.5.1" } }, "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA=="],
@@ -4168,8 +4168,6 @@
"pino/process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
"postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"pretty-format/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
-55
View File
@@ -1,55 +0,0 @@
import { em, entity, text, boolean } from "userbase";
import { registerLocalMediaAdapter } from "userbase/adapter/node";
import { TanstackStartConfig } from "userbase/adapter/tanstack-start";
const local = registerLocalMediaAdapter();
const schema = em({
todos: entity("todos", {
title: text(),
done: boolean(),
}),
});
// register your schema to get automatic type completion
type Database = (typeof schema)["DB"];
declare module "userbase" {
interface DB extends Database {}
}
export default {
connection: {
url: "file:data.db",
},
options: {
// the seed option is only executed if the database was empty
seed: async (ctx) => {
// create some entries
await ctx.em.mutator("todos").insertMany([
{ title: "Learn userbase", done: true },
{ title: "Build something cool", done: false },
]);
// and create a user
await ctx.app.module.auth.createUser({
email: "test@userbase.io",
password: "12345678",
});
},
},
config: {
data: schema.toJSON(),
auth: {
enabled: true,
jwt: {
secret: "random_gibberish_please_change_this",
},
},
media: {
enabled: true,
adapter: local({
path: "./public/uploads",
}),
},
},
} satisfies TanstackStartConfig;
+22 -22
View File
@@ -9,24 +9,19 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as SsrRouteImport } from './routes/ssr'
import { Route as IndexRouteImport } from './routes/index'
import { Route as ApiSplatRouteImport } from './routes/api.$'
import { Route as SsrRouteImport } from './routes/ssr'
import { Route as AdminSplatRouteImport } from './routes/admin.$'
import { Route as ApiSplatRouteImport } from './routes/api.$'
const SsrRoute = SsrRouteImport.update({
id: '/ssr',
path: '/ssr',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const ApiSplatRoute = ApiSplatRouteImport.update({
id: '/api/$',
path: '/api/$',
const SsrRoute = SsrRouteImport.update({
id: '/ssr',
path: '/ssr',
getParentRoute: () => rootRouteImport,
} as any)
const AdminSplatRoute = AdminSplatRouteImport.update({
@@ -34,6 +29,11 @@ const AdminSplatRoute = AdminSplatRouteImport.update({
path: '/admin/$',
getParentRoute: () => rootRouteImport,
} as any)
const ApiSplatRoute = ApiSplatRouteImport.update({
id: '/api/$',
path: '/api/$',
getParentRoute: () => rootRouteImport,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
@@ -71,13 +71,6 @@ export interface RootRouteChildren {
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/ssr': {
id: '/ssr'
path: '/ssr'
fullPath: '/ssr'
preLoaderRoute: typeof SsrRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
@@ -85,11 +78,11 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/api/$': {
id: '/api/$'
path: '/api/$'
fullPath: '/api/$'
preLoaderRoute: typeof ApiSplatRouteImport
'/ssr': {
id: '/ssr'
path: '/ssr'
fullPath: '/ssr'
preLoaderRoute: typeof SsrRouteImport
parentRoute: typeof rootRouteImport
}
'/admin/$': {
@@ -99,6 +92,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AdminSplatRouteImport
parentRoute: typeof rootRouteImport
}
'/api/$': {
id: '/api/$'
path: '/api/$'
fullPath: '/api/$'
preLoaderRoute: typeof ApiSplatRouteImport
parentRoute: typeof rootRouteImport
}
}
}
+3 -3
View File
@@ -8,7 +8,7 @@ import { Footer } from "@/components/Footer";
import { List } from "@/components/List";
export const completeTodo = createServerFn({ method: "POST" })
.inputValidator(
.validator(
(data) => data as { done: boolean; id: number; title: string },
)
.handler(async ({ data: todo }) => {
@@ -24,7 +24,7 @@ export const completeTodo = createServerFn({ method: "POST" })
});
export const deleteTodo = createServerFn({ method: "POST" })
.inputValidator((data) => data as { id: number })
.validator((data) => data as { id: number })
.handler(async ({ data }) => {
try {
const api = await getApi({});
@@ -36,7 +36,7 @@ export const deleteTodo = createServerFn({ method: "POST" })
});
export const createTodo = createServerFn({ method: "POST" })
.inputValidator((data) => data as { title: string })
.validator((data) => data as { title: string })
.handler(async ({ data }) => {
try {
const api = await getApi({});
@@ -0,0 +1,55 @@
import { em, entity, text, boolean } from "userbase";
import { registerLocalMediaAdapter } from "userbase/adapter/node";
import type { TanstackStartConfig } from "userbase/adapter/tanstack-start";
const local = registerLocalMediaAdapter();
const schema = em({
todos: entity("todos", {
title: text(),
done: boolean(),
}),
});
// register your schema to get automatic type completion
type Database = (typeof schema)["DB"];
declare module "userbase" {
interface DB extends Database {}
}
export default {
connection: {
url: "file:data.db",
},
options: {
// the seed option is only executed if the database was empty
seed: async (ctx) => {
// create some entries
await ctx.em.mutator("todos").insertMany([
{ title: "Learn userbase", done: true },
{ title: "Build something cool", done: false },
]);
// and create a user
await ctx.app.module.auth.createUser({
email: "test@userbase.io",
password: "12345678",
});
},
},
config: {
data: schema.toJSON(),
auth: {
enabled: true,
jwt: {
secret: "random_gibberish_please_change_this",
},
},
media: {
enabled: true,
adapter: local({
path: "./public/uploads",
}),
},
},
} satisfies TanstackStartConfig;
+1 -1
View File
@@ -3,7 +3,7 @@ import { devtools } from "@tanstack/devtools-vite";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import viteReact from "@vitejs/plugin-react";
import viteTsConfigPaths from "vite-tsconfig-paths";
import { fileURLToPath, URL } from "url";
import { fileURLToPath, URL } from "node:url";
import tailwindcss from "@tailwindcss/vite";
import { nitro } from "nitro/vite";