mirror of
https://github.com/Lifeforge-app/lifeforge.git
synced 2026-06-28 06:46:24 +00:00
refactor(scripts): update schema generation logic to adapt to new project structure
Former-commit-id: e0345494d98e2a4f07601ad3f9db74ce4d55465f [formerly dfcbb2b70f9c685849b0d9902334f56cfa0dd303] [formerly e7107aef101ebe9720b1c9312aba5ec3976ff057 [formerly d848268dd6bbe95d792536073d3f7a49daf87b20]] Former-commit-id: eecb2c8c8f9b34fcb08dcc671477f991ff488f62 [formerly 9a670f559aa2ebfca6bdeed28077d59172f122ea] Former-commit-id: 544a60e83d23b531ba4597e37d8fb334ddacfea7
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { LoggingService } from '@server/core/functions/logging/loggingService'
|
||||
import chalk from 'chalk'
|
||||
import dotenv from 'dotenv'
|
||||
import fs from 'fs/promises'
|
||||
import fs from 'fs'
|
||||
import _ from 'lodash'
|
||||
import path from 'path'
|
||||
import PocketBase, { type CollectionModel } from 'pocketbase'
|
||||
@@ -39,7 +39,10 @@ interface FieldTypeMapping {
|
||||
// Constants
|
||||
const PATHS = {
|
||||
ENV_FILE: path.resolve(__dirname, '../env/.env.local'),
|
||||
MODULES_DIR: path.resolve(__dirname, '../server/src/lib'),
|
||||
MODULES_DIRS: [
|
||||
path.resolve(__dirname, '../server/src/lib/**/schema.ts'),
|
||||
path.resolve(__dirname, '../apps/**/server/schema.ts')
|
||||
],
|
||||
CORE_SCHEMA: path.resolve(__dirname, '../server/src/core/schema.ts')
|
||||
} as const
|
||||
|
||||
@@ -154,22 +157,29 @@ async function buildModuleCollectionsMap(
|
||||
): Promise<ModuleCollectionsMap> {
|
||||
const moduleCollectionsMap: ModuleCollectionsMap = {}
|
||||
|
||||
let allModules: Array<{ name: string; isDirectory(): boolean }>
|
||||
let allModules: string[] = []
|
||||
|
||||
try {
|
||||
const moduleEntries = await fs.readdir(PATHS.MODULES_DIR, {
|
||||
withFileTypes: true
|
||||
})
|
||||
|
||||
allModules = moduleEntries.filter(entry => entry.isDirectory())
|
||||
allModules = PATHS.MODULES_DIRS.map(dir => fs.globSync(dir))
|
||||
.flat()
|
||||
.map(entry => entry.split('/').slice(0, -1).join('/'))
|
||||
} catch (error) {
|
||||
LoggingService.error(`Failed to read modules directory: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(allModules)
|
||||
|
||||
for (const collection of collections) {
|
||||
const matchingModule = allModules.find(module =>
|
||||
collection.name.startsWith(_.snakeCase(module.name))
|
||||
collection.name.startsWith(
|
||||
_.snakeCase(
|
||||
module
|
||||
.replace(/\/server$/, '')
|
||||
.split('/')
|
||||
.pop() || ''
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if (!matchingModule) {
|
||||
@@ -179,10 +189,18 @@ async function buildModuleCollectionsMap(
|
||||
continue
|
||||
}
|
||||
|
||||
if (!moduleCollectionsMap[matchingModule.name]) {
|
||||
moduleCollectionsMap[matchingModule.name] = []
|
||||
const moduleName = matchingModule
|
||||
.replace(/\/server$/, '')
|
||||
.split('/')
|
||||
.pop()
|
||||
|
||||
const key = `${matchingModule}|${moduleName}`
|
||||
|
||||
if (!moduleCollectionsMap[key]) {
|
||||
moduleCollectionsMap[key] = []
|
||||
}
|
||||
moduleCollectionsMap[matchingModule.name].push(collection)
|
||||
|
||||
moduleCollectionsMap[key].push(collection)
|
||||
}
|
||||
|
||||
const totalCollections = Object.values(moduleCollectionsMap).flat().length
|
||||
@@ -242,12 +260,20 @@ export default ${_.camelCase(moduleName)}Schemas
|
||||
}
|
||||
|
||||
// Generate main schema content
|
||||
function generateMainSchemaContent(moduleNames: string[]): string {
|
||||
const imports = moduleNames
|
||||
.map(
|
||||
moduleName =>
|
||||
` ${moduleName}: (await import('@lib/${moduleName === 'users' ? 'user' : _.camelCase(moduleName)}/schema')).default,`
|
||||
)
|
||||
function generateMainSchemaContent(moduleDirs: string[]): string {
|
||||
const imports = moduleDirs
|
||||
.map(moduleDir => {
|
||||
const [moduleDirPath, moduleDirName] = moduleDir.split('|')
|
||||
|
||||
const targetPath = path.join(
|
||||
'@lib/',
|
||||
moduleDirName,
|
||||
moduleDirPath.split(moduleDirName).pop() || '',
|
||||
'schema'
|
||||
)
|
||||
|
||||
return ` ${_.snakeCase(moduleDirName)}: (await import('${targetPath}')).default,`
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
return `import flattenSchemas from '@functions/utils/flattenSchema'
|
||||
@@ -269,10 +295,15 @@ async function writeFormattedFile(
|
||||
): Promise<void> {
|
||||
try {
|
||||
const formattedContent = await prettier.format(content, {
|
||||
parser: 'typescript'
|
||||
parser: 'typescript',
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
arrowParens: 'avoid',
|
||||
endOfLine: 'auto'
|
||||
})
|
||||
|
||||
await fs.writeFile(filePath, formattedContent)
|
||||
fs.writeFileSync(filePath, formattedContent)
|
||||
} catch (error) {
|
||||
LoggingService.error(`Failed to write file ${filePath}: ${error}`)
|
||||
throw error
|
||||
@@ -285,11 +316,11 @@ async function generateSchemas(
|
||||
): Promise<SchemaGenerationResult> {
|
||||
const moduleSchemas: Record<string, string> = {}
|
||||
|
||||
const moduleNames: string[] = []
|
||||
const moduleDirs: string[] = []
|
||||
|
||||
for (const [moduleDir, collections] of Object.entries(moduleCollectionsMap)) {
|
||||
const [moduleDirPath, moduleDirName] = moduleDir.split('|')
|
||||
|
||||
for (const [moduleDirName, collections] of Object.entries(
|
||||
moduleCollectionsMap
|
||||
)) {
|
||||
if (!collections.length) {
|
||||
LoggingService.warn(
|
||||
`No collections found for module ${chalk.bold(moduleDirName)}`
|
||||
@@ -299,7 +330,7 @@ async function generateSchemas(
|
||||
|
||||
const moduleName = collections[0].name.split('__')[0]
|
||||
|
||||
moduleNames.push(moduleName)
|
||||
moduleDirs.push(moduleDir)
|
||||
|
||||
const moduleSchemaContent = generateModuleSchemaContent(
|
||||
moduleName,
|
||||
@@ -309,11 +340,7 @@ async function generateSchemas(
|
||||
moduleSchemas[moduleDirName] = moduleSchemaContent
|
||||
|
||||
// Write individual module schema file
|
||||
const moduleSchemaPath = path.join(
|
||||
PATHS.MODULES_DIR,
|
||||
moduleDirName,
|
||||
'schema.ts'
|
||||
)
|
||||
const moduleSchemaPath = path.join(moduleDirPath, 'schema.ts')
|
||||
|
||||
await writeFormattedFile(moduleSchemaPath, moduleSchemaContent)
|
||||
|
||||
@@ -322,7 +349,7 @@ async function generateSchemas(
|
||||
)
|
||||
}
|
||||
|
||||
const mainSchemaContent = generateMainSchemaContent(moduleNames)
|
||||
const mainSchemaContent = generateMainSchemaContent(moduleDirs)
|
||||
|
||||
return { moduleSchemas, mainSchemaContent }
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ export class Create<
|
||||
}
|
||||
|
||||
const result = await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.create(this._data, {
|
||||
expand: this._expand,
|
||||
fields: this._fields,
|
||||
|
||||
@@ -55,7 +55,7 @@ export class Delete<TCollectionKey extends CollectionKey>
|
||||
}
|
||||
|
||||
const result = await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.delete(this._recordId)
|
||||
|
||||
LoggingService.debug(
|
||||
|
||||
@@ -102,7 +102,7 @@ export class GetFirstListItem<
|
||||
: 'id != ""' // Default filter to ensure we get a valid response
|
||||
|
||||
const result = await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.getFirstListItem(filterString, {
|
||||
sort: this._sort,
|
||||
expand: this._expand,
|
||||
|
||||
@@ -140,7 +140,7 @@ export class GetFullList<
|
||||
: undefined
|
||||
|
||||
const result = (await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.getFullList({
|
||||
filter: filterString,
|
||||
sort: this._sort,
|
||||
|
||||
@@ -135,7 +135,7 @@ export class GetList<
|
||||
: undefined
|
||||
|
||||
const result = (await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.getList(this._page, this._perPage, {
|
||||
filter: filterString,
|
||||
sort: this._sort,
|
||||
|
||||
@@ -114,7 +114,7 @@ export class GetOne<
|
||||
}
|
||||
|
||||
const result = this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.getOne(this._itemId, {
|
||||
expand: this._expand,
|
||||
fields: this._fields
|
||||
|
||||
@@ -147,7 +147,7 @@ export class Update<
|
||||
}
|
||||
|
||||
const result = await this._pb
|
||||
.collection((this.collectionKey as string).replace(/^users__/, ''))
|
||||
.collection((this.collectionKey as string).replace(/^user__/, ''))
|
||||
.update(this._recordId, this._data, {
|
||||
expand: this._expand,
|
||||
fields: this._fields
|
||||
|
||||
@@ -96,7 +96,7 @@ export async function connectToPocketBase(
|
||||
* Handles special cases like users__users -> users
|
||||
*/
|
||||
function mapCollectionName(collectionName: string): string {
|
||||
return collectionName === 'users__users' ? 'users' : collectionName
|
||||
return collectionName === 'user__users' ? 'users' : collectionName
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -117,7 +117,6 @@ const coreRoutes = forgeRouter({
|
||||
apiKeys: (await import('../../lib/apiKeys')).default,
|
||||
pixabay: (await import('../../lib/pixabay')).default,
|
||||
locations: (await import('../../lib/locations')).default,
|
||||
modules: (await import('../../lib/modules')).default,
|
||||
backups: (await import('../../lib/backups')).default,
|
||||
database: (await import('../../lib/database')).default,
|
||||
ping,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import flattenSchemas from '@functions/utils/flattenSchema'
|
||||
|
||||
export const SCHEMAS = {
|
||||
users: (await import('@lib/user/schema')).default,
|
||||
user: (await import('@lib/user/schema')).default,
|
||||
todo_list: (await import('@lib/todoList/server/schema')).default,
|
||||
code_time: (await import('@lib/codeTime/server/schema')).default,
|
||||
idea_box: (await import('@lib/ideaBox/server/schema')).default,
|
||||
|
||||
@@ -28,7 +28,7 @@ const createOrUpdate = forgeController
|
||||
const id = pb.instance.authStore.record!.id
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(id)
|
||||
.data({
|
||||
APIKeysMasterPasswordHash
|
||||
@@ -49,7 +49,7 @@ const verify = forgeController
|
||||
|
||||
const decryptedMaster = decrypt2(password, challenge)
|
||||
|
||||
const user = await pb.getOne.collection('users__users').id(id).execute()
|
||||
const user = await pb.getOne.collection('user__users').id(id).execute()
|
||||
|
||||
const { APIKeysMasterPasswordHash } = user
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import z from 'zod'
|
||||
|
||||
const apiKeysSchemas = {
|
||||
entries: {
|
||||
@@ -9,129 +9,129 @@ const apiKeysSchemas = {
|
||||
icon: z.string(),
|
||||
key: z.string(),
|
||||
created: z.string(),
|
||||
updated: z.string(),
|
||||
updated: z.string()
|
||||
}),
|
||||
raw: {
|
||||
id: "zhm94t1hfoq97oa",
|
||||
id: 'zhm94t1hfoq97oa',
|
||||
listRule: '@request.auth.id != ""',
|
||||
viewRule: '@request.auth.id != ""',
|
||||
createRule: '@request.auth.id != ""',
|
||||
updateRule: '@request.auth.id != ""',
|
||||
deleteRule: '@request.auth.id != ""',
|
||||
name: "api_keys__entries",
|
||||
type: "base",
|
||||
name: 'api_keys__entries',
|
||||
type: 'base',
|
||||
fields: [
|
||||
{
|
||||
autogeneratePattern: "[a-z0-9]{15}",
|
||||
autogeneratePattern: '[a-z0-9]{15}',
|
||||
hidden: false,
|
||||
id: "text3208210256",
|
||||
id: 'text3208210256',
|
||||
max: 15,
|
||||
min: 15,
|
||||
name: "id",
|
||||
pattern: "^[a-z0-9]+$",
|
||||
name: 'id',
|
||||
pattern: '^[a-z0-9]+$',
|
||||
presentable: false,
|
||||
primaryKey: true,
|
||||
required: true,
|
||||
system: true,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "4k7c8zdb",
|
||||
id: '4k7c8zdb',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "keyId",
|
||||
pattern: "",
|
||||
name: 'keyId',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "tcnowiel",
|
||||
id: 'tcnowiel',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "name",
|
||||
pattern: "",
|
||||
name: 'name',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "l1a35cql",
|
||||
id: 'l1a35cql',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "description",
|
||||
pattern: "",
|
||||
name: 'description',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "vhho1bhf",
|
||||
id: 'vhho1bhf',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "icon",
|
||||
pattern: "",
|
||||
name: 'icon',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "ddcugsw3",
|
||||
id: 'ddcugsw3',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "key",
|
||||
pattern: "",
|
||||
name: 'key',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "autodate2990389176",
|
||||
name: "created",
|
||||
id: 'autodate2990389176',
|
||||
name: 'created',
|
||||
onCreate: true,
|
||||
onUpdate: false,
|
||||
presentable: false,
|
||||
system: false,
|
||||
type: "autodate",
|
||||
type: 'autodate'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "autodate3332085495",
|
||||
name: "updated",
|
||||
id: 'autodate3332085495',
|
||||
name: 'updated',
|
||||
onCreate: true,
|
||||
onUpdate: true,
|
||||
presentable: false,
|
||||
system: false,
|
||||
type: "autodate",
|
||||
},
|
||||
type: 'autodate'
|
||||
}
|
||||
],
|
||||
indexes: [
|
||||
"CREATE UNIQUE INDEX `idx_V6OVTl5FtN` ON `api_keys__entries` (`keyId`)",
|
||||
'CREATE UNIQUE INDEX `idx_V6OVTl5FtN` ON `api_keys__entries` (`keyId`)'
|
||||
],
|
||||
system: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
system: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default apiKeysSchemas;
|
||||
export default apiKeysSchemas
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { forgeController, forgeRouter } from '@functions/routes'
|
||||
import { ClientError } from '@functions/routes/utils/response'
|
||||
import z from 'zod'
|
||||
|
||||
const toggle = forgeController
|
||||
.mutation()
|
||||
.description('Toggle a module on/off')
|
||||
.input({
|
||||
query: z.object({
|
||||
id: z.string()
|
||||
})
|
||||
})
|
||||
.callback(async ({ pb, query: { id } }) => {
|
||||
const user = pb.instance.authStore.record
|
||||
|
||||
if (!user) {
|
||||
throw new ClientError('Unauthorized to toggle module')
|
||||
}
|
||||
|
||||
const modules = user.enabledModules || []
|
||||
|
||||
if (!modules.includes(id)) {
|
||||
modules.push(id)
|
||||
} else {
|
||||
const index = modules.indexOf(id)
|
||||
|
||||
if (index > -1) {
|
||||
modules.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.id(user.id)
|
||||
.data({
|
||||
enabledModules: modules
|
||||
})
|
||||
.execute()
|
||||
})
|
||||
|
||||
export default forgeRouter({
|
||||
toggle
|
||||
})
|
||||
@@ -122,7 +122,7 @@ const updateBgImage = forgeController
|
||||
})
|
||||
.callback(async ({ pb, media: { file } }) => {
|
||||
const newRecord = await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(pb.instance.authStore.record!.id)
|
||||
.data({
|
||||
...(await getMedia('bgImage', file)),
|
||||
@@ -150,7 +150,7 @@ const deleteBgImage = forgeController
|
||||
.statusCode(204)
|
||||
.callback(({ pb }) =>
|
||||
pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(pb.instance.authStore.record!.id)
|
||||
.data({
|
||||
bgImage: null
|
||||
@@ -199,7 +199,7 @@ const updatePersonalization = forgeController
|
||||
}
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(pb.instance.authStore.record!.id)
|
||||
.data(toBeUpdated)
|
||||
.execute()
|
||||
|
||||
@@ -18,7 +18,7 @@ const updateAvatar = forgeController
|
||||
const { id } = pb.instance.authStore.record!
|
||||
|
||||
const newRecord = await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(id)
|
||||
.data(fileResult)
|
||||
.execute()
|
||||
@@ -35,7 +35,7 @@ const deleteAvatar = forgeController
|
||||
const { id } = pb.instance.authStore.record!
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(id)
|
||||
.data({
|
||||
avatar: ''
|
||||
@@ -84,7 +84,7 @@ const updateProfile = forgeController
|
||||
|
||||
if (Object.keys(updateData).length > 0) {
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(id)
|
||||
.data(updateData)
|
||||
.execute()
|
||||
|
||||
@@ -144,7 +144,7 @@ const verifyAndEnable = forgeController
|
||||
}
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(pb.instance.authStore.record!.id)
|
||||
.data({
|
||||
twoFASecret: encrypt(
|
||||
@@ -169,7 +169,7 @@ const disable = forgeController
|
||||
}
|
||||
|
||||
await pb.update
|
||||
.collection('users__users')
|
||||
.collection('user__users')
|
||||
.id(pb.instance.authStore.record!.id)
|
||||
.data({
|
||||
twoFASecret: ''
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import z from 'zod'
|
||||
|
||||
const usersSchemas = {
|
||||
users: {
|
||||
@@ -12,15 +12,13 @@ const usersSchemas = {
|
||||
name: z.string(),
|
||||
avatar: z.string(),
|
||||
dateOfBirth: z.string(),
|
||||
theme: z.enum(["system", "light", "dark"]),
|
||||
theme: z.enum(['system', 'light', 'dark']),
|
||||
color: z.string(),
|
||||
bgTemp: z.string(),
|
||||
bgImage: z.string(),
|
||||
backdropFilters: z.any(),
|
||||
fontFamily: z.string(),
|
||||
language: z.enum(["zh-CN", "en", "ms", "zh-TW", ""]),
|
||||
moduleConfigs: z.any(),
|
||||
enabledModules: z.any(),
|
||||
language: z.enum(['zh-CN', 'en', 'ms', 'zh-TW', '']),
|
||||
dashboardLayout: z.any(),
|
||||
spotifyAccessToken: z.string(),
|
||||
spotifyRefreshToken: z.string(),
|
||||
@@ -31,487 +29,467 @@ const usersSchemas = {
|
||||
twoFASecret: z.string(),
|
||||
fontScale: z.number(),
|
||||
created: z.string(),
|
||||
updated: z.string(),
|
||||
updated: z.string()
|
||||
}),
|
||||
raw: {
|
||||
id: "_pb_users_auth_",
|
||||
listRule: "id = @request.auth.id",
|
||||
viewRule: "id = @request.auth.id",
|
||||
createRule: "",
|
||||
updateRule: "id = @request.auth.id",
|
||||
id: '_pb_users_auth_',
|
||||
listRule: 'id = @request.auth.id',
|
||||
viewRule: 'id = @request.auth.id',
|
||||
createRule: '',
|
||||
updateRule: 'id = @request.auth.id',
|
||||
deleteRule: null,
|
||||
name: "users",
|
||||
type: "auth",
|
||||
name: 'users',
|
||||
type: 'auth',
|
||||
fields: [
|
||||
{
|
||||
autogeneratePattern: "[a-z0-9]{15}",
|
||||
autogeneratePattern: '[a-z0-9]{15}',
|
||||
hidden: false,
|
||||
id: "text3208210256",
|
||||
id: 'text3208210256',
|
||||
max: 15,
|
||||
min: 15,
|
||||
name: "id",
|
||||
pattern: "^[a-z0-9]+$",
|
||||
name: 'id',
|
||||
pattern: '^[a-z0-9]+$',
|
||||
presentable: false,
|
||||
primaryKey: true,
|
||||
required: true,
|
||||
system: true,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
cost: 10,
|
||||
hidden: true,
|
||||
id: "password901924565",
|
||||
id: 'password901924565',
|
||||
max: 0,
|
||||
min: 8,
|
||||
name: "password",
|
||||
pattern: "",
|
||||
name: 'password',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
required: true,
|
||||
system: true,
|
||||
type: "password",
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "[a-zA-Z0-9_]{50}",
|
||||
autogeneratePattern: '[a-zA-Z0-9_]{50}',
|
||||
hidden: true,
|
||||
id: "text2504183744",
|
||||
id: 'text2504183744',
|
||||
max: 60,
|
||||
min: 30,
|
||||
name: "tokenKey",
|
||||
pattern: "",
|
||||
name: 'tokenKey',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: true,
|
||||
system: true,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
exceptDomains: null,
|
||||
hidden: false,
|
||||
id: "email3885137012",
|
||||
name: "email",
|
||||
id: 'email3885137012',
|
||||
name: 'email',
|
||||
onlyDomains: null,
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: true,
|
||||
type: "email",
|
||||
type: 'email'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "bool1547992806",
|
||||
name: "emailVisibility",
|
||||
id: 'bool1547992806',
|
||||
name: 'emailVisibility',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: true,
|
||||
type: "bool",
|
||||
type: 'bool'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "bool256245529",
|
||||
name: "verified",
|
||||
id: 'bool256245529',
|
||||
name: 'verified',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: true,
|
||||
type: "bool",
|
||||
type: 'bool'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "users[0-9]{6}",
|
||||
autogeneratePattern: 'users[0-9]{6}',
|
||||
hidden: false,
|
||||
id: "text4166911607",
|
||||
id: 'text4166911607',
|
||||
max: 150,
|
||||
min: 3,
|
||||
name: "username",
|
||||
pattern: "^[\\w][\\w\\.\\-]*$",
|
||||
name: 'username',
|
||||
pattern: '^[\\w][\\w\\.\\-]*$',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: true,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "users_name",
|
||||
id: 'users_name',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "name",
|
||||
pattern: "",
|
||||
name: 'name',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "users_avatar",
|
||||
id: 'users_avatar',
|
||||
maxSelect: 1,
|
||||
maxSize: 5242880,
|
||||
mimeTypes: [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/gif",
|
||||
"image/webp",
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/svg+xml',
|
||||
'image/gif',
|
||||
'image/webp'
|
||||
],
|
||||
name: "avatar",
|
||||
name: 'avatar',
|
||||
presentable: false,
|
||||
protected: false,
|
||||
required: false,
|
||||
system: false,
|
||||
thumbs: ["256x0"],
|
||||
type: "file",
|
||||
thumbs: ['256x0'],
|
||||
type: 'file'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "fsmwvydl",
|
||||
max: "",
|
||||
min: "",
|
||||
name: "dateOfBirth",
|
||||
id: 'fsmwvydl',
|
||||
max: '',
|
||||
min: '',
|
||||
name: 'dateOfBirth',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "date",
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "nppdhyft",
|
||||
id: 'nppdhyft',
|
||||
maxSelect: 1,
|
||||
name: "theme",
|
||||
name: 'theme',
|
||||
presentable: false,
|
||||
required: true,
|
||||
system: false,
|
||||
type: "select",
|
||||
values: ["system", "light", "dark"],
|
||||
type: 'select',
|
||||
values: ['system', 'light', 'dark']
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "1ik4v2wa",
|
||||
id: '1ik4v2wa',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "color",
|
||||
pattern: "",
|
||||
name: 'color',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "d0lgczhi",
|
||||
id: 'd0lgczhi',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "bgTemp",
|
||||
pattern: "",
|
||||
name: 'bgTemp',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "xjb7bo9y",
|
||||
id: 'xjb7bo9y',
|
||||
maxSelect: 1,
|
||||
maxSize: 5242880000,
|
||||
mimeTypes: null,
|
||||
name: "bgImage",
|
||||
name: 'bgImage',
|
||||
presentable: false,
|
||||
protected: false,
|
||||
required: false,
|
||||
system: false,
|
||||
thumbs: null,
|
||||
type: "file",
|
||||
type: 'file'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "apt6wrsc",
|
||||
id: 'apt6wrsc',
|
||||
maxSize: 2000000,
|
||||
name: "backdropFilters",
|
||||
name: 'backdropFilters',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "json",
|
||||
type: 'json'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "c34od4fd",
|
||||
id: 'c34od4fd',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "fontFamily",
|
||||
pattern: "",
|
||||
name: 'fontFamily',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "bv7hnazi",
|
||||
id: 'bv7hnazi',
|
||||
maxSelect: 1,
|
||||
name: "language",
|
||||
name: 'language',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "select",
|
||||
values: ["zh-CN", "en", "ms", "zh-TW"],
|
||||
type: 'select',
|
||||
values: ['zh-CN', 'en', 'ms', 'zh-TW']
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "wu4w5mks",
|
||||
id: 'wjxwozyv',
|
||||
maxSize: 2000000,
|
||||
name: "moduleConfigs",
|
||||
name: 'dashboardLayout',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "json",
|
||||
type: 'json'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "a7qz6gsx",
|
||||
maxSize: 2000000,
|
||||
name: "enabledModules",
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "wjxwozyv",
|
||||
maxSize: 2000000,
|
||||
name: "dashboardLayout",
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
hidden: false,
|
||||
id: "t4oem4rk",
|
||||
id: 't4oem4rk',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "spotifyAccessToken",
|
||||
pattern: "",
|
||||
name: 'spotifyAccessToken',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "pmtavvft",
|
||||
id: 'pmtavvft',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "spotifyRefreshToken",
|
||||
pattern: "",
|
||||
name: 'spotifyRefreshToken',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "n6afyo6x",
|
||||
max: "",
|
||||
min: "",
|
||||
name: "spotifyTokenExpires",
|
||||
id: 'n6afyo6x',
|
||||
max: '',
|
||||
min: '',
|
||||
name: 'spotifyTokenExpires',
|
||||
presentable: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "date",
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "ivwqhyvx",
|
||||
id: 'ivwqhyvx',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "masterPasswordHash",
|
||||
pattern: "",
|
||||
name: 'masterPasswordHash',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "bva2tmvh",
|
||||
id: 'bva2tmvh',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "journalMasterPasswordHash",
|
||||
pattern: "",
|
||||
name: 'journalMasterPasswordHash',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "afbxzben",
|
||||
id: 'afbxzben',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "APIKeysMasterPasswordHash",
|
||||
pattern: "",
|
||||
name: 'APIKeysMasterPasswordHash',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
autogeneratePattern: "",
|
||||
autogeneratePattern: '',
|
||||
hidden: false,
|
||||
id: "oi6j9b9d",
|
||||
id: 'oi6j9b9d',
|
||||
max: 0,
|
||||
min: 0,
|
||||
name: "twoFASecret",
|
||||
pattern: "",
|
||||
name: 'twoFASecret',
|
||||
pattern: '',
|
||||
presentable: false,
|
||||
primaryKey: false,
|
||||
required: false,
|
||||
system: false,
|
||||
type: "text",
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "number3058924606",
|
||||
id: 'number3058924606',
|
||||
max: null,
|
||||
min: 0.1,
|
||||
name: "fontScale",
|
||||
name: 'fontScale',
|
||||
onlyInt: false,
|
||||
presentable: false,
|
||||
required: true,
|
||||
system: false,
|
||||
type: "number",
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "autodate2990389176",
|
||||
name: "created",
|
||||
id: 'autodate2990389176',
|
||||
name: 'created',
|
||||
onCreate: true,
|
||||
onUpdate: false,
|
||||
presentable: false,
|
||||
system: false,
|
||||
type: "autodate",
|
||||
type: 'autodate'
|
||||
},
|
||||
{
|
||||
hidden: false,
|
||||
id: "autodate3332085495",
|
||||
name: "updated",
|
||||
id: 'autodate3332085495',
|
||||
name: 'updated',
|
||||
onCreate: true,
|
||||
onUpdate: true,
|
||||
presentable: false,
|
||||
system: false,
|
||||
type: "autodate",
|
||||
},
|
||||
type: 'autodate'
|
||||
}
|
||||
],
|
||||
indexes: [
|
||||
"CREATE UNIQUE INDEX `__pb_users_auth__username_idx` ON `users` (username COLLATE NOCASE)",
|
||||
'CREATE UNIQUE INDEX `__pb_users_auth__username_idx` ON `users` (username COLLATE NOCASE)',
|
||||
"CREATE UNIQUE INDEX `__pb_users_auth__email_idx` ON `users` (`email`) WHERE `email` != ''",
|
||||
"CREATE UNIQUE INDEX `__pb_users_auth__tokenKey_idx` ON `users` (`tokenKey`)",
|
||||
'CREATE UNIQUE INDEX `__pb_users_auth__tokenKey_idx` ON `users` (`tokenKey`)'
|
||||
],
|
||||
system: false,
|
||||
authRule: "verified=true",
|
||||
authRule: 'verified=true',
|
||||
manageRule: null,
|
||||
authAlert: {
|
||||
enabled: true,
|
||||
emailTemplate: {
|
||||
subject: "Login from a new location",
|
||||
body: "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
},
|
||||
subject: 'Login from a new location',
|
||||
body: "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
oauth2: {
|
||||
providers: [
|
||||
{
|
||||
pkce: null,
|
||||
name: "github",
|
||||
clientId: "3ffe0179e120fd734d1c",
|
||||
authURL: "",
|
||||
tokenURL: "",
|
||||
userInfoURL: "",
|
||||
displayName: "",
|
||||
extra: null,
|
||||
name: 'github',
|
||||
clientId: '3ffe0179e120fd734d1c',
|
||||
authURL: '',
|
||||
tokenURL: '',
|
||||
userInfoURL: '',
|
||||
displayName: '',
|
||||
extra: null
|
||||
},
|
||||
{
|
||||
pkce: null,
|
||||
name: "google",
|
||||
name: 'google',
|
||||
clientId:
|
||||
"667707161573-3t64t2s6g5qr6rve19qibkmr6fbiq9f7.apps.googleusercontent.com",
|
||||
authURL: "",
|
||||
tokenURL: "",
|
||||
userInfoURL: "",
|
||||
displayName: "",
|
||||
extra: null,
|
||||
},
|
||||
'667707161573-3t64t2s6g5qr6rve19qibkmr6fbiq9f7.apps.googleusercontent.com',
|
||||
authURL: '',
|
||||
tokenURL: '',
|
||||
userInfoURL: '',
|
||||
displayName: '',
|
||||
extra: null
|
||||
}
|
||||
],
|
||||
mappedFields: {
|
||||
id: "username",
|
||||
name: "name",
|
||||
username: "name",
|
||||
avatarURL: "avatar",
|
||||
id: 'username',
|
||||
name: 'name',
|
||||
username: 'name',
|
||||
avatarURL: 'avatar'
|
||||
},
|
||||
enabled: true,
|
||||
enabled: true
|
||||
},
|
||||
passwordAuth: {
|
||||
enabled: true,
|
||||
identityFields: ["email", "username"],
|
||||
identityFields: ['email', 'username']
|
||||
},
|
||||
mfa: {
|
||||
enabled: false,
|
||||
duration: 1800,
|
||||
rule: "",
|
||||
rule: ''
|
||||
},
|
||||
otp: {
|
||||
enabled: true,
|
||||
duration: 180,
|
||||
length: 6,
|
||||
emailTemplate: {
|
||||
subject: "OTP for {APP_NAME}",
|
||||
body: "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
},
|
||||
subject: 'OTP for {APP_NAME}',
|
||||
body: "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
||||
}
|
||||
},
|
||||
authToken: {
|
||||
duration: 1209600,
|
||||
duration: 1209600
|
||||
},
|
||||
passwordResetToken: {
|
||||
duration: 1800,
|
||||
duration: 1800
|
||||
},
|
||||
emailChangeToken: {
|
||||
duration: 1800,
|
||||
duration: 1800
|
||||
},
|
||||
verificationToken: {
|
||||
duration: 604800,
|
||||
duration: 604800
|
||||
},
|
||||
fileToken: {
|
||||
duration: 120,
|
||||
duration: 120
|
||||
},
|
||||
verificationTemplate: {
|
||||
subject: "Verify your {APP_NAME} email",
|
||||
body: '<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-verification/{TOKEN}" target="_blank" rel="noopener">Verify</a>\n</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>',
|
||||
subject: 'Verify your {APP_NAME} email',
|
||||
body: '<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-verification/{TOKEN}" target="_blank" rel="noopener">Verify</a>\n</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>'
|
||||
},
|
||||
resetPasswordTemplate: {
|
||||
subject: "Reset your {APP_NAME} password",
|
||||
body: '<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}" target="_blank" rel="noopener">Reset password</a>\n</p>\n<p><i>If you didn\'t ask to reset your password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>',
|
||||
subject: 'Reset your {APP_NAME} password',
|
||||
body: '<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}" target="_blank" rel="noopener">Reset password</a>\n</p>\n<p><i>If you didn\'t ask to reset your password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>'
|
||||
},
|
||||
confirmEmailChangeTemplate: {
|
||||
subject: "Confirm your {APP_NAME} new email address",
|
||||
body: '<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}" target="_blank" rel="noopener">Confirm new email</a>\n</p>\n<p><i>If you didn\'t ask to change your email address, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
subject: 'Confirm your {APP_NAME} new email address',
|
||||
body: '<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class="btn" href="{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}" target="_blank" rel="noopener">Confirm new email</a>\n</p>\n<p><i>If you didn\'t ask to change your email address, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default usersSchemas;
|
||||
export default usersSchemas
|
||||
|
||||
@@ -22,7 +22,7 @@ export function removeSensitiveData(userData: Record<string, any>) {
|
||||
|
||||
return newUserData as SchemaWithPB<
|
||||
Omit<
|
||||
z.infer<(typeof COLLECTION_SCHEMAS)['users__users']>,
|
||||
z.infer<(typeof COLLECTION_SCHEMAS)['user__users']>,
|
||||
| 'masterPasswordHash'
|
||||
| 'journalMasterPasswordHash'
|
||||
| 'APIKeysMasterPasswordHash'
|
||||
|
||||
Reference in New Issue
Block a user