create-ej-app 12.0.0 → 15.0.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.
Files changed (141) hide show
  1. package/cli.js +5 -4
  2. package/cli.ts +9 -4
  3. package/package.json +3 -3
  4. package/template/base/package.json +23 -29
  5. package/template/base/src/lib/auth.ts +15 -6
  6. package/template/base/terraform/artifact-registry.tf +5 -0
  7. package/template/base/terraform/backend-service.tf +13 -0
  8. package/template/base/terraform/cleanup.sh +9 -0
  9. package/template/base/terraform/cloudbuild.tf +70 -0
  10. package/template/base/terraform/cloudrun.tf +68 -0
  11. package/template/base/terraform/database.tf +60 -0
  12. package/template/base/terraform/forwarding-rule.tf +43 -0
  13. package/template/base/terraform/ip-address.tf +11 -0
  14. package/template/base/terraform/network-endpoint-group.tf +11 -0
  15. package/template/base/terraform/network.tf +21 -0
  16. package/template/base/terraform/pre.sh +3 -0
  17. package/template/base/terraform/providers.tf +18 -0
  18. package/template/base/terraform/secret.txt +11 -0
  19. package/template/base/terraform/setup.sh +25 -0
  20. package/template/base/terraform/ssl-certs.tf +32 -0
  21. package/template/base/terraform/target-https-proxy copy.tf +14 -0
  22. package/template/base/terraform/target-https-proxy.tf +14 -0
  23. package/template/base/terraform/terraform.tfvars +4 -0
  24. package/template/base/terraform/url-map.tf +23 -0
  25. package/template/base/terraform/variables.tf +21 -0
  26. package/template/old/.env.example +0 -17
  27. package/template/old/.eslintrc.cjs +0 -26
  28. package/template/old/components.json +0 -17
  29. package/template/old/drizzle.config.ts +0 -11
  30. package/template/old/next.config.mjs +0 -4
  31. package/template/old/package.json +0 -87
  32. package/template/old/postcss.config.mjs +0 -8
  33. package/template/old/prettier.config.mjs +0 -11
  34. package/template/old/public/next.svg +0 -1
  35. package/template/old/public/vercel.svg +0 -1
  36. package/template/old/src/app/(app)/dashboard/layout.tsx +0 -14
  37. package/template/old/src/app/(app)/dashboard/page.tsx +0 -12
  38. package/template/old/src/app/(app)/layout.tsx +0 -125
  39. package/template/old/src/app/(app)/roles/[id]/actions.ts +0 -59
  40. package/template/old/src/app/(app)/roles/[id]/page.tsx +0 -46
  41. package/template/old/src/app/(app)/roles/[id]/render.tsx +0 -264
  42. package/template/old/src/app/(app)/roles/[id]/validation.ts +0 -22
  43. package/template/old/src/app/(app)/roles/actions.ts +0 -33
  44. package/template/old/src/app/(app)/roles/page.tsx +0 -52
  45. package/template/old/src/app/(app)/roles/render.tsx +0 -80
  46. package/template/old/src/app/(app)/settings/actions.ts +0 -17
  47. package/template/old/src/app/(app)/settings/layout.tsx +0 -14
  48. package/template/old/src/app/(app)/settings/loading.tsx +0 -28
  49. package/template/old/src/app/(app)/settings/page.tsx +0 -19
  50. package/template/old/src/app/(app)/settings/render.tsx +0 -107
  51. package/template/old/src/app/(app)/settings/validation.ts +0 -5
  52. package/template/old/src/app/(app)/tasks/[id]/actions.ts +0 -92
  53. package/template/old/src/app/(app)/tasks/[id]/page.tsx +0 -59
  54. package/template/old/src/app/(app)/tasks/[id]/render.tsx +0 -482
  55. package/template/old/src/app/(app)/tasks/[id]/validation.ts +0 -18
  56. package/template/old/src/app/(app)/tasks/actions.ts +0 -39
  57. package/template/old/src/app/(app)/tasks/page.tsx +0 -59
  58. package/template/old/src/app/(app)/tasks/render.tsx +0 -129
  59. package/template/old/src/app/(app)/tasks/statusEnum.ts +0 -3
  60. package/template/old/src/app/(app)/users/[id]/actions.ts +0 -68
  61. package/template/old/src/app/(app)/users/[id]/page.tsx +0 -39
  62. package/template/old/src/app/(app)/users/[id]/render.tsx +0 -325
  63. package/template/old/src/app/(app)/users/[id]/validation.ts +0 -18
  64. package/template/old/src/app/(app)/users/actions.ts +0 -34
  65. package/template/old/src/app/(app)/users/page.tsx +0 -62
  66. package/template/old/src/app/(app)/users/render.tsx +0 -124
  67. package/template/old/src/app/(auth)/layout.tsx +0 -27
  68. package/template/old/src/app/(auth)/login/page.tsx +0 -49
  69. package/template/old/src/app/(auth)/login/render.tsx +0 -146
  70. package/template/old/src/app/(marketing)/layout.tsx +0 -42
  71. package/template/old/src/app/(marketing)/page.tsx +0 -97
  72. package/template/old/src/app/api/auth/[...nextauth]/route.ts +0 -7
  73. package/template/old/src/app/favicon.ico +0 -0
  74. package/template/old/src/app/globals.css +0 -76
  75. package/template/old/src/app/layout.tsx +0 -31
  76. package/template/old/src/components/app-nav-command.tsx +0 -178
  77. package/template/old/src/components/dark-mode-toggle.tsx +0 -43
  78. package/template/old/src/components/data-table/data-table-column-header.tsx +0 -91
  79. package/template/old/src/components/data-table/data-table-faceted-filter.tsx +0 -149
  80. package/template/old/src/components/data-table/data-table-loading.tsx +0 -77
  81. package/template/old/src/components/data-table/data-table-pagination.tsx +0 -94
  82. package/template/old/src/components/data-table/data-table-toolbar.tsx +0 -78
  83. package/template/old/src/components/data-table/data-table-types.ts +0 -17
  84. package/template/old/src/components/data-table/data-table-view-options.tsx +0 -59
  85. package/template/old/src/components/data-table/data-table.tsx +0 -301
  86. package/template/old/src/components/data-table/simple-data-table.tsx +0 -109
  87. package/template/old/src/components/empty-placeholder.tsx +0 -78
  88. package/template/old/src/components/heading.tsx +0 -17
  89. package/template/old/src/components/icons.tsx +0 -101
  90. package/template/old/src/components/main-nav.tsx +0 -64
  91. package/template/old/src/components/mobile-nav.tsx +0 -50
  92. package/template/old/src/components/shell.tsx +0 -13
  93. package/template/old/src/components/side-nav.tsx +0 -51
  94. package/template/old/src/components/site-footer.tsx +0 -31
  95. package/template/old/src/components/system-info.tsx +0 -36
  96. package/template/old/src/components/ui/alert-dialog.tsx +0 -141
  97. package/template/old/src/components/ui/avatar.tsx +0 -50
  98. package/template/old/src/components/ui/badge.tsx +0 -36
  99. package/template/old/src/components/ui/button.tsx +0 -56
  100. package/template/old/src/components/ui/card.tsx +0 -79
  101. package/template/old/src/components/ui/checkbox.tsx +0 -30
  102. package/template/old/src/components/ui/command.tsx +0 -155
  103. package/template/old/src/components/ui/dialog.tsx +0 -122
  104. package/template/old/src/components/ui/dropdown-menu.tsx +0 -200
  105. package/template/old/src/components/ui/form.tsx +0 -176
  106. package/template/old/src/components/ui/input.tsx +0 -25
  107. package/template/old/src/components/ui/label.tsx +0 -26
  108. package/template/old/src/components/ui/popover.tsx +0 -31
  109. package/template/old/src/components/ui/select.tsx +0 -160
  110. package/template/old/src/components/ui/separator.tsx +0 -31
  111. package/template/old/src/components/ui/skeleton.tsx +0 -15
  112. package/template/old/src/components/ui/sonner.tsx +0 -31
  113. package/template/old/src/components/ui/table.tsx +0 -117
  114. package/template/old/src/components/user-account-nav.tsx +0 -60
  115. package/template/old/src/components/user-avatar.tsx +0 -27
  116. package/template/old/src/data-access/resource.ts +0 -85
  117. package/template/old/src/data-access/role-permission.ts +0 -45
  118. package/template/old/src/data-access/role.ts +0 -105
  119. package/template/old/src/data-access/task.ts +0 -141
  120. package/template/old/src/data-access/user.ts +0 -141
  121. package/template/old/src/db/index.ts +0 -14
  122. package/template/old/src/db/schema.ts +0 -287
  123. package/template/old/src/env.mjs +0 -58
  124. package/template/old/src/hooks/use-debounce.tsx +0 -17
  125. package/template/old/src/hooks/use-lock-body.tsx +0 -13
  126. package/template/old/src/lib/auth.ts +0 -89
  127. package/template/old/src/lib/cn.ts +0 -4
  128. package/template/old/src/lib/currentUser.ts +0 -8
  129. package/template/old/src/lib/delay.ts +0 -2
  130. package/template/old/src/lib/formatDate.ts +0 -11
  131. package/template/old/src/lib/generateLabel.ts +0 -5
  132. package/template/old/src/lib/s3Client.ts +0 -156
  133. package/template/old/src/lib/safe-action.ts +0 -19
  134. package/template/old/src/lib/siteConfig.ts +0 -4
  135. package/template/old/src/lib/sortOrderEnum.ts +0 -2
  136. package/template/old/src/use-case/role-permission.ts +0 -19
  137. package/template/old/src/use-case/role.ts +0 -110
  138. package/template/old/src/use-case/task.ts +0 -166
  139. package/template/old/src/use-case/user.ts +0 -121
  140. package/template/old/tailwind.config.ts +0 -81
  141. package/template/old/tsconfig.json +0 -47
@@ -1,287 +0,0 @@
1
- import { createId } from '@paralleldrive/cuid2'
2
- import { relations, sql } from 'drizzle-orm'
3
- import {
4
- bigint,
5
- boolean,
6
- index,
7
- integer,
8
- pgEnum,
9
- pgTable,
10
- primaryKey,
11
- text,
12
- timestamp,
13
- unique,
14
- varchar
15
- } from 'drizzle-orm/pg-core'
16
-
17
- export const Account = pgTable(
18
- 'Accounts',
19
- {
20
- id: text('id')
21
- .notNull()
22
- .primaryKey()
23
- .$defaultFn(() => createId()),
24
- userId: text('userId')
25
- .notNull()
26
- .references(() => User.id),
27
- type: varchar('type', { length: 255 }).notNull(),
28
- provider: varchar('provider', { length: 255 }).notNull(),
29
- providerAccountId: varchar('providerAccountId', { length: 255 }).notNull(),
30
- refresh_token: text('refresh_token'),
31
- access_token: text('access_token'),
32
- expires_at: integer('expires_at'),
33
- token_type: varchar('token_type', { length: 255 }),
34
- scope: varchar('scope', { length: 255 }),
35
- id_token: text('id_token'),
36
- session_state: varchar('session_state', { length: 255 })
37
- },
38
- account => ({
39
- userIdIdx: index('Accounts_idx_userId').on(account.userId),
40
- uniqueProviderAccount: unique('Accounts_uq_provider_providerAccountId').on(
41
- account.provider,
42
- account.providerAccountId
43
- )
44
- })
45
- )
46
-
47
- export const AccountRelations = relations(Account, ({ one }) => ({
48
- user: one(User, { fields: [Account.userId], references: [User.id] })
49
- }))
50
-
51
- export const Session = pgTable(
52
- 'Sessions',
53
- {
54
- id: text('id')
55
- .notNull()
56
- .primaryKey()
57
- .$defaultFn(() => createId()),
58
- sessionToken: varchar('sessionToken', { length: 255 }).notNull().unique(),
59
- userId: text('userId')
60
- .notNull()
61
- .references(() => User.id),
62
- expires: timestamp('expires', {
63
- mode: 'date',
64
- withTimezone: true
65
- }).notNull(),
66
- createdAt: timestamp('createdAt', {
67
- mode: 'date',
68
- withTimezone: true
69
- })
70
- .default(sql`CURRENT_TIMESTAMP`)
71
- .notNull(),
72
- updatedAt: timestamp('updatedAt', {
73
- mode: 'date',
74
- withTimezone: true
75
- })
76
- },
77
- session => ({
78
- userIdIdx: index('Sessions_idx_userId').on(session.userId)
79
- })
80
- )
81
-
82
- export const SessionRelations = relations(Session, ({ one }) => ({
83
- user: one(User, { fields: [Session.userId], references: [User.id] })
84
- }))
85
-
86
- export const Role = pgTable('Roles', {
87
- id: text('id')
88
- .notNull()
89
- .primaryKey()
90
- .$defaultFn(() => createId()),
91
- name: varchar('name', { length: 255 }).notNull().unique(),
92
- createdAt: timestamp('createdAt', {
93
- mode: 'date',
94
- withTimezone: true
95
- })
96
- .default(sql`CURRENT_TIMESTAMP`)
97
- .notNull(),
98
- updatedAt: timestamp('updatedAt', {
99
- mode: 'date',
100
- withTimezone: true
101
- })
102
- })
103
-
104
- export const RoleRelations = relations(Role, ({ many }) => ({
105
- permissions: many(RolePermission),
106
- users: many(User)
107
- }))
108
-
109
- export const PermissionEnum = pgEnum('PermissionEnum', [
110
- 'TaskList',
111
- 'TaskView',
112
- 'TaskCreate',
113
- 'TaskUpdate',
114
- 'TaskDelete'
115
- ])
116
-
117
- export const RolePermission = pgTable(
118
- 'RolePermissions',
119
- {
120
- id: text('id')
121
- .notNull()
122
- .primaryKey()
123
- .$defaultFn(() => createId()),
124
- roleId: text('roleId')
125
- .notNull()
126
- .references(() => Role.id, {
127
- onDelete: 'cascade'
128
- }),
129
- permission: PermissionEnum('permission').notNull()
130
- },
131
- rp => ({
132
- roleIdIdx: index('RolePermissions_idx_roleId').on(rp.roleId),
133
- uniqueRolePermission: unique('RolePermissions_uq_roleId_permission').on(
134
- rp.roleId,
135
- rp.permission
136
- )
137
- })
138
- )
139
-
140
- export const RolePermissionRelations = relations(RolePermission, ({ one }) => ({
141
- role: one(Role, { fields: [RolePermission.roleId], references: [Role.id] })
142
- }))
143
-
144
- export const UserTypeEnum = pgEnum('UserTypeEnum', ['Root', 'Normal'])
145
-
146
- export const User = pgTable('Users', {
147
- id: text('id')
148
- .notNull()
149
- .primaryKey()
150
- .$defaultFn(() => createId()),
151
- name: varchar('name', { length: 255 }),
152
- email: varchar('email', { length: 255 }).notNull().unique(),
153
- emailVerified: timestamp('emailVerified', {
154
- mode: 'date',
155
- withTimezone: true
156
- }),
157
- image: varchar('image', { length: 255 }),
158
- type: UserTypeEnum('type').notNull().default('Normal'),
159
- roleId: text('roleId').references(() => Role.id),
160
- createdAt: timestamp('createdAt', {
161
- mode: 'date',
162
- withTimezone: true
163
- })
164
- .default(sql`CURRENT_TIMESTAMP`)
165
- .notNull(),
166
- updatedAt: timestamp('updatedAt', {
167
- mode: 'date',
168
- withTimezone: true
169
- })
170
- })
171
-
172
- export const UserRelations = relations(User, ({ many, one }) => ({
173
- accounts: many(Account),
174
- sessions: many(Session),
175
- role: one(Role, {
176
- fields: [User.roleId],
177
- references: [Role.id]
178
- })
179
- }))
180
-
181
- export const VerificationToken = pgTable(
182
- 'VerificationTokens',
183
- {
184
- identifier: varchar('identifier', { length: 255 }).notNull(),
185
- token: varchar('token', { length: 255 }).notNull(),
186
- expires: timestamp('expires', {
187
- mode: 'date',
188
- withTimezone: true
189
- }).notNull()
190
- },
191
- vt => ({
192
- pk: primaryKey({ columns: [vt.identifier, vt.token] })
193
- })
194
- )
195
-
196
- export const TaskStatusEnum = pgEnum('TaskStatusEnum', [
197
- 'Backlog',
198
- 'Todo',
199
- 'In Progress',
200
- 'Done',
201
- 'Cancelled'
202
- ])
203
-
204
- export const Task = pgTable('Tasks', {
205
- id: text('id')
206
- .notNull()
207
- .primaryKey()
208
- .$defaultFn(() => createId()),
209
- title: varchar('title', { length: 255 }).notNull(),
210
- status: TaskStatusEnum('status').notNull().default('Todo'),
211
- description: text('description'),
212
- createdAt: timestamp('createdAt', {
213
- mode: 'date',
214
- withTimezone: true
215
- })
216
- .default(sql`CURRENT_TIMESTAMP`)
217
- .notNull(),
218
- updatedAt: timestamp('updatedAt', {
219
- mode: 'date',
220
- withTimezone: true
221
- }),
222
- createdById: text('createdById')
223
- .notNull()
224
- .references(() => User.id),
225
- updatedById: text('updatedById').references(() => User.id)
226
- })
227
-
228
- export const TaskRelations = relations(Task, ({ one, many }) => ({
229
- createdBy: one(User, {
230
- fields: [Task.createdById],
231
- references: [User.id]
232
- }),
233
- updatedBy: one(User, {
234
- fields: [Task.updatedById],
235
- references: [User.id]
236
- }),
237
- images: many(Resource)
238
- }))
239
-
240
- export const Resource = pgTable(
241
- 'Resources',
242
- {
243
- id: text('id')
244
- .notNull()
245
- .primaryKey()
246
- .$defaultFn(() => createId()),
247
- filename: varchar('filename', { length: 255 }).notNull(),
248
- key: varchar('key', { length: 255 }).notNull().unique(),
249
- isTemp: boolean('isTemp').notNull().default(false),
250
- url: varchar('url', { length: 255 }).notNull().unique(),
251
- size: bigint('size', { mode: 'number' }).notNull(),
252
- contentType: varchar('contentType', { length: 255 }).notNull(),
253
-
254
- taskId: text('taskId').references(() => Task.id),
255
-
256
- createdAt: timestamp('createdAt', {
257
- mode: 'date',
258
- withTimezone: true
259
- })
260
- .default(sql`CURRENT_TIMESTAMP`)
261
- .notNull(),
262
- updatedAt: timestamp('updatedAt', {
263
- mode: 'date',
264
- withTimezone: true
265
- }),
266
- createdById: text('createdById').references(() => User.id),
267
- updatedById: text('updatedById').references(() => User.id)
268
- },
269
- resource => ({
270
- taskIdIdx: index('Resources_idx_taskId').on(resource.taskId)
271
- })
272
- )
273
-
274
- export const ResourceRelations = relations(Resource, ({ one }) => ({
275
- task: one(Task, {
276
- fields: [Resource.taskId],
277
- references: [Task.id]
278
- }),
279
- createdBy: one(User, {
280
- fields: [Resource.createdById],
281
- references: [User.id]
282
- }),
283
- updatedBy: one(User, {
284
- fields: [Resource.updatedById],
285
- references: [User.id]
286
- })
287
- }))
@@ -1,58 +0,0 @@
1
- import { createEnv } from '@t3-oss/env-nextjs'
2
- import { z } from 'zod'
3
-
4
- export const env = createEnv({
5
- server: {
6
- NODE_ENV: z.enum(['development', 'production']),
7
- DATABASE_URL: z.string().url(),
8
- NEXTAUTH_SECRET:
9
- process.env.NODE_ENV === 'production'
10
- ? z.string().min(1)
11
- : z.string().min(1).optional(),
12
- NEXTAUTH_URL: z.preprocess(
13
- str => process.env.VERCEL_URL ?? str,
14
- process.env.VERCEL ? z.string().min(1) : z.string().url()
15
- ),
16
- EMAIL_SERVER_HOST: z.string().min(1),
17
- EMAIL_SERVER_PORT: z.number(),
18
- EMAIL_SERVER_USER: z.string().min(1),
19
- EMAIL_SERVER_PASSWORD: z.string().min(1),
20
- EMAIL_FROM: z.string().email(),
21
- GOOGLE_ID: z.string().min(1),
22
- GOOGLE_SECRET: z.string().min(1),
23
- GITHUB_ID: z.string().min(1),
24
- GITHUB_SECRET: z.string().min(1),
25
- S3_REGION: z.string().min(1),
26
- S3_BUCKET: z.string().min(1),
27
- S3_ACCESS_KEY: z.string().min(1),
28
- S3_SECRET_KEY: z.string().min(1)
29
- },
30
-
31
- client: {
32
- // NEXT_PUBLIC_CLIENTVAR: z.string().min(1),
33
- },
34
-
35
- runtimeEnv: {
36
- NODE_ENV: process.env.NODE_ENV,
37
- DATABASE_URL: process.env.DATABASE_URL,
38
- NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
39
- NEXTAUTH_URL: process.env.NEXTAUTH_URL,
40
- EMAIL_SERVER_HOST: process.env.EMAIL_SERVER_HOST,
41
- EMAIL_SERVER_PORT: parseInt(process.env.EMAIL_SERVER_PORT || ''),
42
- EMAIL_SERVER_USER: process.env.EMAIL_SERVER_USER,
43
- EMAIL_SERVER_PASSWORD: process.env.EMAIL_SERVER_PASSWORD,
44
- EMAIL_FROM: process.env.EMAIL_FROM,
45
- GOOGLE_ID: process.env.GOOGLE_ID,
46
- GOOGLE_SECRET: process.env.GOOGLE_SECRET,
47
- GITHUB_ID: process.env.GITHUB_ID,
48
- GITHUB_SECRET: process.env.GITHUB_SECRET,
49
- S3_REGION: process.env.S3_REGION,
50
- S3_BUCKET: process.env.S3_BUCKET,
51
- S3_ACCESS_KEY: process.env.S3_ACCESS_KEY,
52
- S3_SECRET_KEY: process.env.S3_SECRET_KEY
53
- },
54
-
55
- skipValidation: !!process.env.SKIP_ENV_VALIDATION,
56
-
57
- emptyStringAsUndefined: true
58
- })
@@ -1,17 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState } from 'react'
4
-
5
- export function useDebounce<T>(value: T, delay?: number): T {
6
- const [debouncedValue, setDebouncedValue] = useState<T>(value)
7
-
8
- useEffect(() => {
9
- const timer = setTimeout(() => setDebouncedValue(value), delay || 500)
10
-
11
- return () => {
12
- clearTimeout(timer)
13
- }
14
- }, [value, delay])
15
-
16
- return debouncedValue
17
- }
@@ -1,13 +0,0 @@
1
- 'use client'
2
-
3
- import { useLayoutEffect } from 'react'
4
-
5
- export function useLockBody() {
6
- useLayoutEffect((): (() => void) => {
7
- const originalStyle: string = window.getComputedStyle(
8
- document.body
9
- ).overflow
10
- document.body.style.overflow = 'hidden'
11
- return () => (document.body.style.overflow = originalStyle)
12
- }, [])
13
- }
@@ -1,89 +0,0 @@
1
- import { DrizzleAdapter } from '@auth/drizzle-adapter'
2
- import { InferSelectModel } from 'drizzle-orm'
3
- import {
4
- Session as NextAuthSession,
5
- getServerSession,
6
- type DefaultSession,
7
- type NextAuthOptions
8
- } from 'next-auth'
9
- import { Adapter } from 'next-auth/adapters'
10
- import EmailProvider from 'next-auth/providers/email'
11
- import GitHubProvider from 'next-auth/providers/github'
12
- import GoogleProvider from 'next-auth/providers/google'
13
- import { cache } from 'react'
14
-
15
- import type { RolePermissionType } from '@/data-access/role-permission'
16
- import type { UserType } from '@/data-access/user'
17
- import { db } from '@/db'
18
- import { Account, Session, User, VerificationToken } from '@/db/schema'
19
- import { env } from '@/env.mjs'
20
- import { checkForRolePermissionUseCase } from '@/use-case/role-permission'
21
-
22
- declare module 'next-auth' {
23
- interface Session extends DefaultSession {
24
- user: {
25
- id: string
26
- type: UserType['type']
27
- roleId?: string | null
28
- } & DefaultSession['user']
29
- }
30
-
31
- interface User extends InferSelectModel<typeof User> {}
32
- }
33
-
34
- export const authOptions: NextAuthOptions = {
35
- pages: {
36
- signIn: '/login'
37
- },
38
- callbacks: {
39
- session({ session, user }) {
40
- return {
41
- ...session,
42
- user: {
43
- ...session.user,
44
- id: user.id,
45
- type: user.type,
46
- roleId: user.roleId
47
- }
48
- }
49
- }
50
- },
51
- adapter: DrizzleAdapter(db, {
52
- usersTable: User,
53
- accountsTable: Account,
54
- sessionsTable: Session,
55
- verificationTokensTable: VerificationToken
56
- }) as Adapter,
57
- providers: [
58
- EmailProvider({
59
- server: {
60
- host: env.EMAIL_SERVER_HOST,
61
- port: env.EMAIL_SERVER_PORT,
62
- auth: {
63
- user: env.EMAIL_SERVER_USER,
64
- pass: env.EMAIL_SERVER_PASSWORD
65
- }
66
- },
67
- from: env.EMAIL_FROM
68
- }),
69
- GoogleProvider({
70
- clientId: env.GOOGLE_ID,
71
- clientSecret: env.GOOGLE_SECRET
72
- }),
73
- GitHubProvider({
74
- clientId: env.GITHUB_ID,
75
- clientSecret: env.GITHUB_SECRET
76
- })
77
- ]
78
- }
79
-
80
- export const getAuthSession = cache(() => getServerSession(authOptions))
81
-
82
- export const authGuard = cache(
83
- (session: NextAuthSession, permission?: RolePermissionType['permission']) =>
84
- checkForRolePermissionUseCase(
85
- session.user.type,
86
- session.user.roleId,
87
- permission
88
- )
89
- )
@@ -1,4 +0,0 @@
1
- import { clsx, type ClassValue } from 'clsx'
2
- import { twMerge } from 'tailwind-merge'
3
-
4
- export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs))
@@ -1,8 +0,0 @@
1
- import { User } from '@/db/schema'
2
- import { InferSelectModel } from 'drizzle-orm'
3
-
4
- export type CurrentUser = {
5
- id: string
6
- type: InferSelectModel<typeof User>['type']
7
- roleId?: string | null
8
- }
@@ -1,2 +0,0 @@
1
- export const delay = (ms: number) =>
2
- new Promise(resolve => setTimeout(resolve, ms))
@@ -1,11 +0,0 @@
1
- import dayjs from 'dayjs'
2
- import relativeTime from 'dayjs/plugin/relativeTime'
3
-
4
- dayjs.extend(relativeTime)
5
-
6
- export const formatDate = (date: Date) => dayjs(date).format('DD/MM/YYYY')
7
-
8
- export const formatDateTime = (date: Date) =>
9
- dayjs(date).format('DD/MM/YYYY hh:mm:ss A')
10
-
11
- export const timesAgo = (date: Date) => dayjs(date).fromNow()
@@ -1,5 +0,0 @@
1
- export const generateLabel = (str: string) =>
2
- str
3
- .replaceAll('_', ' ')
4
- .replaceAll(/([A-Z])/g, ' $1')
5
- .trim()
@@ -1,156 +0,0 @@
1
- import {
2
- DeleteObjectCommand,
3
- HeadObjectCommand,
4
- HeadObjectCommandOutput,
5
- S3Client
6
- } from '@aws-sdk/client-s3'
7
- import { createPresignedPost } from '@aws-sdk/s3-presigned-post'
8
- import { createId } from '@paralleldrive/cuid2'
9
- import { extname } from 'path'
10
-
11
- import {
12
- createResource,
13
- deleteResource,
14
- getResourceById,
15
- updateResourceById
16
- } from '@/data-access/resource'
17
- import { env } from '@/env.mjs'
18
- import { CurrentUser } from './currentUser'
19
-
20
- export const S3_HOST = `https://${env.S3_BUCKET}.s3.${env.S3_REGION}.amazonaws.com`
21
-
22
- export const s3Client = new S3Client({
23
- region: env.S3_REGION,
24
- credentials: {
25
- accessKeyId: env.S3_ACCESS_KEY,
26
- secretAccessKey: env.S3_SECRET_KEY
27
- }
28
- })
29
-
30
- export const getUrl = (key: string) => `${S3_HOST}/${key}`
31
-
32
- const uploadLimit = 1024 * 1024 * 10 // 10 MB
33
-
34
- export const getPresignedUrl = async ({
35
- filename,
36
- contentType,
37
- contentTypeStartsWith,
38
- isPublic,
39
- createdById
40
- }: {
41
- filename: string
42
- contentType: string
43
- contentTypeStartsWith?: string
44
- isPublic?: boolean
45
- createdById?: string | null
46
- }) => {
47
- const id = createId()
48
-
49
- const extension = extname(filename)
50
-
51
- const key = `${id}${extension}`
52
-
53
- const url = getUrl(key)
54
-
55
- await createResource({
56
- id,
57
- filename,
58
- key,
59
- isTemp: true,
60
- url,
61
- createdById,
62
- size: 0,
63
- contentType
64
- })
65
-
66
- const Conditions: any[] = [
67
- ['content-length-range', 1024, uploadLimit],
68
- { bucket: env.S3_BUCKET },
69
- { key },
70
- ['eq', '$Content-Type', contentType],
71
- ['eq', '$x-amz-meta-filename', filename],
72
- ['eq', '$x-amz-meta-extension', extension]
73
- ]
74
-
75
- if (isPublic) Conditions.push({ acl: 'public-read' })
76
- if (contentTypeStartsWith)
77
- Conditions.push(['starts-with', '$Content-Type', contentTypeStartsWith])
78
- if (createdById)
79
- Conditions.push(['eq', '$x-amz-meta-createdById', createdById])
80
-
81
- const presigned = await createPresignedPost(s3Client, {
82
- Bucket: env.S3_BUCKET,
83
- Key: key,
84
- Expires: 300,
85
- Conditions,
86
- Fields: {
87
- ...(isPublic
88
- ? {
89
- acl: 'public-read'
90
- }
91
- : {}),
92
-
93
- ...(createdById
94
- ? {
95
- 'X-Amz-Meta-createdById': createdById
96
- }
97
- : {}),
98
-
99
- 'X-Amz-Meta-filename': filename,
100
- 'X-Amz-Meta-extension': extension,
101
- 'Content-Type': contentType,
102
- 'Content-Disposition': `inline; filename="${encodeURIComponent(filename)}"`
103
- }
104
- })
105
-
106
- return {
107
- id,
108
- key,
109
- url,
110
- presigned
111
- }
112
- }
113
-
114
- export const markFileUploaded = async (
115
- currentUser: CurrentUser,
116
- id: string
117
- ) => {
118
- const resource = await getResourceById(id)
119
-
120
- if (!resource) throw new Error('Resource not found')
121
-
122
- let response: HeadObjectCommandOutput
123
- try {
124
- response = await s3Client.send(
125
- new HeadObjectCommand({
126
- Bucket: env.S3_BUCKET,
127
- Key: resource.key
128
- })
129
- )
130
- } catch (err) {
131
- throw new Error('File not found')
132
- }
133
-
134
- await updateResourceById({
135
- id: resource.id,
136
- isTemp: false,
137
- contentType: response.ContentType,
138
- size: response.ContentLength,
139
- updatedById: currentUser.id
140
- })
141
- }
142
-
143
- export const deleteFile = async (id: string) => {
144
- const resource = await getResourceById(id)
145
-
146
- if (!resource) throw new Error('Resource not found')
147
-
148
- await s3Client.send(
149
- new DeleteObjectCommand({
150
- Bucket: env.S3_BUCKET,
151
- Key: resource.key
152
- })
153
- )
154
-
155
- await deleteResource(id)
156
- }
@@ -1,19 +0,0 @@
1
- import { createSafeActionClient } from 'next-safe-action'
2
-
3
- import { getAuthSession } from './auth'
4
-
5
- const actionClient = createSafeActionClient()
6
-
7
- export const authActionClient = actionClient.use(async ({ next }) => {
8
- const session = await getAuthSession()
9
-
10
- if (!session?.user) {
11
- throw new Error('Unauthorized')
12
- }
13
-
14
- return next({
15
- ctx: {
16
- user: session.user
17
- }
18
- })
19
- })
@@ -1,4 +0,0 @@
1
- export const siteConfig = {
2
- name: 'Project Name',
3
- description: 'Project Description'
4
- }
@@ -1,2 +0,0 @@
1
- export const SortOrderEnum = ['asc', 'desc'] as const
2
- export type SortOrderEnum = (typeof SortOrderEnum)[number]