create-tulip-app 0.6.1 → 0.8.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.
Files changed (90) hide show
  1. package/dist/index.d.mts +1 -0
  2. package/dist/index.mjs +3095 -0
  3. package/dist/index.mjs.map +1 -0
  4. package/dist/templates/basic/README.md +1 -0
  5. package/dist/templates/basic/drizzle.config.ts +11 -0
  6. package/dist/templates/basic/next.config.ts +15 -0
  7. package/dist/templates/basic/package.json +80 -0
  8. package/dist/templates/basic/postcss.config.js +6 -0
  9. package/dist/templates/basic/public/fonts/Inter/Inter-Black.ttf +0 -0
  10. package/dist/templates/basic/public/fonts/Inter/Inter-Bold.ttf +0 -0
  11. package/dist/templates/basic/public/fonts/Inter/Inter-ExtraBold.ttf +0 -0
  12. package/dist/templates/basic/public/fonts/Inter/Inter-ExtraLight.ttf +0 -0
  13. package/dist/templates/basic/public/fonts/Inter/Inter-Italic.ttf +0 -0
  14. package/dist/templates/basic/public/fonts/Inter/Inter-Light.ttf +0 -0
  15. package/dist/templates/basic/public/fonts/Inter/Inter-Medium.ttf +0 -0
  16. package/dist/templates/basic/public/fonts/Inter/Inter-Regular.ttf +0 -0
  17. package/dist/templates/basic/public/fonts/Inter/Inter-SemiBold.ttf +0 -0
  18. package/dist/templates/basic/public/fonts/Inter/Inter-Thin.ttf +0 -0
  19. package/dist/templates/basic/public/icons/icon-x192.png +0 -0
  20. package/dist/templates/basic/public/icons/icon-x512.png +0 -0
  21. package/dist/templates/basic/public/images/auth-background.jpeg +0 -0
  22. package/dist/templates/basic/public/images/placeholder.jpeg +0 -0
  23. package/dist/templates/basic/src/app/admin/(dashboard)/_components/budget-bar-chart.client.tsx +135 -0
  24. package/dist/templates/basic/src/app/admin/(dashboard)/_components/date-year-picker.tsx +49 -0
  25. package/dist/templates/basic/src/app/admin/(dashboard)/layout.tsx +16 -0
  26. package/dist/templates/basic/src/app/admin/(dashboard)/loading.tsx +15 -0
  27. package/dist/templates/basic/src/app/admin/(dashboard)/page.tsx +12 -0
  28. package/dist/templates/basic/src/app/admin/drive/(root)/layout.tsx +16 -0
  29. package/dist/templates/basic/src/app/admin/drive/(root)/loading.tsx +5 -0
  30. package/dist/templates/basic/src/app/admin/drive/(root)/page.tsx +3 -0
  31. package/dist/templates/basic/src/app/admin/drive/[namespace]/layout.tsx +21 -0
  32. package/dist/templates/basic/src/app/admin/drive/[namespace]/loading.tsx +5 -0
  33. package/dist/templates/basic/src/app/admin/drive/[namespace]/page.tsx +5 -0
  34. package/dist/templates/basic/src/app/admin/drive/_components/command-create.tsx +104 -0
  35. package/dist/templates/basic/src/app/admin/drive/_components/command-upload.tsx +31 -0
  36. package/dist/templates/basic/src/app/admin/drive/_components/drive-context.client.tsx +175 -0
  37. package/dist/templates/basic/src/app/admin/drive/_components/drive-header.client.tsx +219 -0
  38. package/dist/templates/basic/src/app/admin/drive/_components/drive-sidebar.tsx +61 -0
  39. package/dist/templates/basic/src/app/admin/drive/_components/drive-view.client.tsx +49 -0
  40. package/dist/templates/basic/src/app/admin/drive/_components/grid.client.tsx +372 -0
  41. package/dist/templates/basic/src/app/admin/drive/_components/list.client.tsx +83 -0
  42. package/dist/templates/basic/src/app/admin/drive/_components/toolbars.tsx +74 -0
  43. package/dist/templates/basic/src/app/admin/drive/_config/columns-data.tsx +98 -0
  44. package/dist/templates/basic/src/app/admin/drive/_config/commands.tsx +197 -0
  45. package/dist/templates/basic/src/app/admin/drive/_config/types.tsx +90 -0
  46. package/dist/templates/basic/src/app/admin/drive/_lib/router.ts +72 -0
  47. package/dist/templates/basic/src/app/admin/drive/_lib/search-params.ts +21 -0
  48. package/dist/templates/basic/src/app/admin/drive/loading.tsx +10 -0
  49. package/dist/templates/basic/src/app/admin/error.tsx +5 -0
  50. package/dist/templates/basic/src/app/admin/layout.tsx +21 -0
  51. package/dist/templates/basic/src/app/admin/not-found.tsx +3 -0
  52. package/dist/templates/basic/src/app/api/auth/[...all]/route.ts +4 -0
  53. package/dist/templates/basic/src/app/api/rpc/[[...rest]]/route.ts +5 -0
  54. package/dist/templates/basic/src/app/api/storage/files/route.ts +4 -0
  55. package/dist/templates/basic/src/app/apple-icon.png +0 -0
  56. package/dist/templates/basic/src/app/auth/forget-password/loading.tsx +3 -0
  57. package/dist/templates/basic/src/app/auth/forget-password/page.tsx +5 -0
  58. package/dist/templates/basic/src/app/auth/layout.tsx +13 -0
  59. package/dist/templates/basic/src/app/auth/login/loading.tsx +3 -0
  60. package/dist/templates/basic/src/app/auth/login/page.tsx +5 -0
  61. package/dist/templates/basic/src/app/auth/reset-password/loading.tsx +3 -0
  62. package/dist/templates/basic/src/app/auth/reset-password/page.tsx +5 -0
  63. package/dist/templates/basic/src/app/favicon.ico +0 -0
  64. package/dist/templates/basic/src/app/globals.css +3 -0
  65. package/dist/templates/basic/src/app/layout.tsx +17 -0
  66. package/dist/templates/basic/src/app/loading.tsx +3 -0
  67. package/dist/templates/basic/src/app/manifest.ts +4 -0
  68. package/dist/templates/basic/src/app/not-found.tsx +3 -0
  69. package/dist/templates/basic/src/instrumentation.ts +5 -0
  70. package/dist/templates/basic/src/lib/config/base.ts +11 -0
  71. package/dist/templates/basic/src/lib/config/paths.tsx +33 -0
  72. package/dist/templates/basic/src/proxy.ts +8 -0
  73. package/dist/templates/basic/src/server/auth/client.ts +6 -0
  74. package/dist/templates/basic/src/server/auth/init.ts +7 -0
  75. package/dist/templates/basic/src/server/auth/permissions.ts +46 -0
  76. package/dist/templates/basic/src/server/context.ts +9 -0
  77. package/dist/templates/basic/src/server/db/init.ts +16 -0
  78. package/dist/templates/basic/src/server/db/schema.ts +22 -0
  79. package/dist/templates/basic/src/server/db/types.ts +3 -0
  80. package/dist/templates/basic/src/server/providers/email.ts +3 -0
  81. package/dist/templates/basic/src/server/router/caller.ts +10 -0
  82. package/dist/templates/basic/src/server/router/client.ts +9 -0
  83. package/dist/templates/basic/src/server/router/init.ts +7 -0
  84. package/dist/templates/basic/src/server/router/register.ts +4 -0
  85. package/dist/templates/basic/src/server/router/router.ts +11 -0
  86. package/dist/templates/basic/src/server/storage/client.ts +14 -0
  87. package/dist/templates/basic/src/server/storage/config.ts +9 -0
  88. package/dist/templates/basic/src/server/storage/init.ts +15 -0
  89. package/dist/templates/basic/tsconfig.json +12 -0
  90. package/package.json +2 -1
@@ -0,0 +1,5 @@
1
+ import { handleRPCRoute } from "@tulip-systems/core/router/server";
2
+ import { context } from "@/server/context";
3
+ import { appRouter } from "@/server/router/router";
4
+
5
+ export const { HEAD, GET, POST, PUT, PATCH, DELETE } = handleRPCRoute({ appRouter, context });
@@ -0,0 +1,4 @@
1
+ import { createDriveProxyRoute } from "@tulip-systems/core/storage/server";
2
+ import { context } from "@/server/context";
3
+
4
+ export const { GET } = createDriveProxyRoute({ context });
@@ -0,0 +1,3 @@
1
+ import { AuthLoading } from "@tulip-systems/core/auth";
2
+
3
+ export default AuthLoading;
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import { ForgetPasswordPage } from "@tulip-systems/core/auth/client";
4
+
5
+ export default ForgetPasswordPage;
@@ -0,0 +1,13 @@
1
+ import { AuthProvider } from "@tulip-systems/core/auth/client";
2
+ import { AuthLayout } from "@tulip-systems/core/auth/server";
3
+ import type { PropsWithChildren } from "react";
4
+ import { config } from "@/lib/config/base";
5
+ import { authClient } from "@/server/auth/client";
6
+
7
+ export default function Layout(props: PropsWithChildren) {
8
+ return (
9
+ <AuthProvider authClient={authClient}>
10
+ <AuthLayout name={config.general.name}>{props.children}</AuthLayout>
11
+ </AuthProvider>
12
+ );
13
+ }
@@ -0,0 +1,3 @@
1
+ import { AuthLoading } from "@tulip-systems/core/auth";
2
+
3
+ export default AuthLoading;
@@ -0,0 +1,5 @@
1
+ import { LoginPage } from "@tulip-systems/core/auth/client";
2
+
3
+ export default function Page() {
4
+ return <LoginPage options={{ enablePasskey: true }} />;
5
+ }
@@ -0,0 +1,3 @@
1
+ import { AuthLoading } from "@tulip-systems/core/auth";
2
+
3
+ export default AuthLoading;
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import { ResetPasswordPage } from "@tulip-systems/core/auth/client";
4
+
5
+ export default ResetPasswordPage;
@@ -0,0 +1,3 @@
1
+ @import "tailwindcss";
2
+ @import "@tulip-systems/core/styles.css";
3
+ @plugin "@tailwindcss/typography";
@@ -0,0 +1,17 @@
1
+ import "./globals.css";
2
+ import "../server/router/register.js";
3
+
4
+ import { Providers } from "@tulip-systems/core/components/client";
5
+ import { generateRootLayoutMetadata, RootLayout } from "@tulip-systems/core/components/server";
6
+ import type { PropsWithChildren } from "react";
7
+ import { config } from "@/lib/config/base";
8
+
9
+ export const { metadata, viewport } = generateRootLayoutMetadata(config);
10
+
11
+ export default function Layout({ children }: PropsWithChildren) {
12
+ return (
13
+ <RootLayout>
14
+ <Providers>{children}</Providers>
15
+ </RootLayout>
16
+ );
17
+ }
@@ -0,0 +1,3 @@
1
+ import { RootLoading } from "@tulip-systems/core/components";
2
+
3
+ export default RootLoading;
@@ -0,0 +1,4 @@
1
+ import { generateManifest } from "@tulip-systems/core/lib";
2
+ import { config } from "@/lib/config/base";
3
+
4
+ export default generateManifest(config);
@@ -0,0 +1,3 @@
1
+ import { RootNotFoundPage } from "@tulip-systems/core/components";
2
+
3
+ export default RootNotFoundPage;
@@ -0,0 +1,5 @@
1
+ export async function register() {
2
+ if (process.env.NEXT_RUNTIME === "nodejs") {
3
+ await import("./server/router/register.js");
4
+ }
5
+ }
@@ -0,0 +1,11 @@
1
+ import { defineTulipConfig } from "@tulip-systems/core/config";
2
+
3
+ export const config = defineTulipConfig({
4
+ general: {
5
+ name: "Tulip Demo",
6
+ shortName: "Tulip Demo",
7
+ },
8
+ email: {
9
+ defaultFrom: "Tulip Demo <noreply@tulip.systems>",
10
+ },
11
+ });
@@ -0,0 +1,33 @@
1
+ import { Icons } from "@tulip-systems/core/components";
2
+ import {
3
+ Path,
4
+ PathGroup,
5
+ PathGroupItems,
6
+ PathLink,
7
+ Paths,
8
+ } from "@tulip-systems/core/components/client";
9
+ import { FoldersIcon } from "lucide-react";
10
+
11
+ export function AdminSidebar() {
12
+ return (
13
+ <Paths>
14
+ <PathGroup>
15
+ <PathGroupItems>
16
+ <Path segment="(dashboard)">
17
+ <PathLink href="/admin">
18
+ <Icons.dashboard />
19
+ Dashboard
20
+ </PathLink>
21
+ </Path>
22
+
23
+ <Path permission={{ drive: ["view"] }} segment="drive">
24
+ <PathLink href="/admin/drive">
25
+ <FoldersIcon />
26
+ Drive
27
+ </PathLink>
28
+ </Path>
29
+ </PathGroupItems>
30
+ </PathGroup>
31
+ </Paths>
32
+ );
33
+ }
@@ -0,0 +1,8 @@
1
+ import { createAuthProxy } from "@tulip-systems/core/auth/server";
2
+ import type { ProxyConfig } from "next/server";
3
+
4
+ export default createAuthProxy({ publicRoutes: ["/auth/*"] });
5
+
6
+ export const config: ProxyConfig = {
7
+ matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
8
+ };
@@ -0,0 +1,6 @@
1
+ "use client";
2
+
3
+ import { type ClientAuth, createAuthClient } from "@tulip-systems/core/auth/client";
4
+ import { type AccessControl, ac, type Roles, roles } from "./permissions.js";
5
+
6
+ export const authClient: ClientAuth<AccessControl, Roles> = createAuthClient({ ac, roles });
@@ -0,0 +1,7 @@
1
+ import { Auth } from "@tulip-systems/core/auth/server";
2
+ import { config } from "@/lib/config/base";
3
+ import { db } from "../db/init.js";
4
+ import { email } from "../providers/email.js";
5
+ import { ac, roles } from "./permissions.js";
6
+
7
+ export const auth = Auth.init({ db, email, config, ac, roles });
@@ -0,0 +1,46 @@
1
+ import { adminAc, createAccessControl, createStatements } from "@tulip-systems/core/auth";
2
+
3
+ /**
4
+ * Statements
5
+ */
6
+ const statement = createStatements({
7
+ developer: ["debug"],
8
+ dashboard: ["view"],
9
+ } as const);
10
+
11
+ /**
12
+ * Access control
13
+ */
14
+ export const ac = createAccessControl(statement);
15
+
16
+ /**
17
+ * Admin role
18
+ */
19
+ const developer = ac.newRole({
20
+ developer: ["debug"],
21
+ dashboard: ["view"],
22
+ ...adminAc.statements,
23
+ });
24
+
25
+ /**
26
+ * Owner role
27
+ */
28
+ const admin = ac.newRole({
29
+ dashboard: ["view"],
30
+ ...adminAc.statements,
31
+ });
32
+
33
+ /**
34
+ * Worker role
35
+ */
36
+ const worker = ac.newRole({});
37
+
38
+ /**
39
+ * Roles config
40
+ */
41
+ export const roles = { admin, developer, worker };
42
+
43
+ export type AccessControl = typeof ac;
44
+ export type Roles = typeof roles;
45
+
46
+ export type Role = keyof typeof roles;
@@ -0,0 +1,9 @@
1
+ import { createContext } from "@tulip-systems/core/config";
2
+ import { auth } from "./auth/init.js";
3
+ import { db } from "./db/init.js";
4
+ import * as schema from "./db/schema.js";
5
+ import type { DatabaseSchema } from "./db/types.js";
6
+ import { email } from "./providers/email.js";
7
+ import { storage } from "./storage/init.js";
8
+
9
+ export const context = createContext<DatabaseSchema>({ db, schema, auth, email, storage });
@@ -0,0 +1,16 @@
1
+ import { Database } from "@tulip-systems/core/database/server";
2
+ import { attachDatabasePool } from "@vercel/functions";
3
+ import { Pool } from "pg";
4
+ import * as schema from "./schema.js";
5
+ import type { DatabaseSchema } from "./types.js";
6
+
7
+ const pool = new Pool({
8
+ connectionString: process.env.DATABASE_URL ?? "",
9
+ max: 15,
10
+ idleTimeoutMillis: 5000,
11
+ connectionTimeoutMillis: 2000,
12
+ });
13
+
14
+ attachDatabasePool(pool);
15
+
16
+ export const db = Database.init<DatabaseSchema>({ schema, pool });
@@ -0,0 +1,22 @@
1
+ export {
2
+ accounts,
3
+ accountsRelations,
4
+ passkeys,
5
+ passkeysRelations,
6
+ sessions,
7
+ sessionsRelations,
8
+ users,
9
+ usersRelations,
10
+ verifications,
11
+ verificationsRelations,
12
+ } from "@tulip-systems/core/auth";
13
+ export {
14
+ nodeModeEnum,
15
+ nodePresignedUrls,
16
+ nodePresignedUrlsRelations,
17
+ nodes,
18
+ nodesRelations,
19
+ nodeTypeEnum,
20
+ nodeVariants,
21
+ nodeVariantsRelations,
22
+ } from "@tulip-systems/core/storage";
@@ -0,0 +1,3 @@
1
+ import type * as schema from "./schema.js";
2
+
3
+ export type DatabaseSchema = typeof schema;
@@ -0,0 +1,3 @@
1
+ import { Email } from "@tulip-systems/core/emails/server";
2
+
3
+ export const email = Email.init({ key: process.env.RESEND_API_KEY ?? "" });
@@ -0,0 +1,10 @@
1
+ import "server-cli-only";
2
+
3
+ import { createRouterClient } from "@orpc/server";
4
+ import { createRPCContext } from "@tulip-systems/core/router/server";
5
+ import { context } from "../context.js";
6
+ import { appRouter } from "./router.js";
7
+
8
+ export const caller = createRouterClient(appRouter, {
9
+ context: async () => createRPCContext({ context }),
10
+ });
@@ -0,0 +1,9 @@
1
+ import { createRPCClient } from "@tulip-systems/core/router/client";
2
+ import type { RouterClient } from "@tulip-systems/core/router/server";
3
+ import type { AppRouter } from "./router.js";
4
+
5
+ declare global {
6
+ var $client: RouterClient<AppRouter>;
7
+ }
8
+
9
+ export const orpc = globalThis.$client ?? createRPCClient<AppRouter>();
@@ -0,0 +1,7 @@
1
+ import "server-cli-only";
2
+
3
+ import { initRPC } from "@tulip-systems/core/router/server";
4
+ import type { DatabaseSchema } from "@/server/db/types";
5
+
6
+ export const { publicProcedure, protectedProcedure, authMiddleware, permissionMiddleware } =
7
+ initRPC<DatabaseSchema>();
@@ -0,0 +1,4 @@
1
+ import { registerRouterClient } from "@tulip-systems/core/router/server";
2
+ import { caller } from "./caller.js";
3
+
4
+ registerRouterClient(caller);
@@ -0,0 +1,11 @@
1
+ import type { InferRouterInputs, InferRouterOutputs } from "@orpc/server";
2
+ import { driveRouter } from "@/app/admin/drive/_lib/router";
3
+
4
+ export const appRouter = {
5
+ drive: driveRouter,
6
+ };
7
+
8
+ // export type definition of API
9
+ export type AppRouter = typeof appRouter;
10
+ export type RouterOutputs = InferRouterOutputs<AppRouter>;
11
+ export type RouterInputs = InferRouterInputs<AppRouter>;
@@ -0,0 +1,14 @@
1
+ import { createUploadClient } from "@tulip-systems/core/storage/client";
2
+ import { orpc } from "../router/client.js";
3
+
4
+ /**
5
+ * Uplaod client
6
+ */
7
+ export const uploadClient = createUploadClient({
8
+ endpoints: {
9
+ presign: (input) => orpc.drive.presign.call(input),
10
+ confirm: (input) => orpc.drive.confirm.call(input),
11
+ deleteNodes: (input) => orpc.drive.deleteNodes.call(input),
12
+ updateNode: (input) => orpc.drive.updateNode.call(input),
13
+ },
14
+ });
@@ -0,0 +1,9 @@
1
+ import type { Permission } from "@tulip-systems/core/auth";
2
+
3
+ export const DRIVE_NAMESPACES = {
4
+ global: {
5
+ namespace: "global",
6
+ label: "Global",
7
+ permission: { drive: ["view"] } as Permission,
8
+ },
9
+ };
@@ -0,0 +1,15 @@
1
+ import { Storage, storageS3Adapter } from "@tulip-systems/core/storage/server";
2
+ import { db } from "../db/init.js";
3
+
4
+ export const storage = Storage.init({
5
+ db,
6
+ adapter: storageS3Adapter({
7
+ bucketName: process.env.S3_BUCKET ?? "",
8
+ region: "auto",
9
+ endpoint: process.env.S3_ENDPOINT ?? "",
10
+ credentials: {
11
+ accessKeyId: process.env.S3_ACCESS_KEY_ID ?? "",
12
+ secretAccessKey: process.env.S3_SECRET_ACCESS_KEY ?? "",
13
+ },
14
+ }),
15
+ });
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "@tulip-systems/typescript-config/nextjs.json",
3
+ "compilerOptions": {
4
+ "plugins": [{ "name": "next" }],
5
+ "paths": {
6
+ "@/*": ["./src/*"],
7
+ "@tulip-config": ["./src/tulip.config.ts"]
8
+ }
9
+ },
10
+ "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "next.config.ts", ".next/types/**/*.ts"],
11
+ "exclude": ["node_modules"]
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tulip-app",
3
- "version": "0.6.1",
3
+ "version": "0.8.2",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "AGPL-3.0",
@@ -27,6 +27,7 @@
27
27
  "scripts": {
28
28
  "dev": "tsdown --config-loader tsdown.config.ts --watch",
29
29
  "build": "tsdown --config-loader tsdown.config.ts",
30
+ "release:build": "pnpm run build",
30
31
  "lint": "biome check",
31
32
  "format": "biome format --write"
32
33
  }