diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 305cad7da5b..eb1dd03c923 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.28.1" + ".": "7.29.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 450d6bbe1ad..5a371bdd6e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows conventions [outlined here](http://keepachangelog.com/). +## [7.29.0](https://github.com/ParabolInc/parabol/compare/v7.28.1...v7.29.0) (2024-04-29) + + +### Added + +* initial avatars on the fly ([#9675](https://github.com/ParabolInc/parabol/issues/9675)) ([e783662](https://github.com/ParabolInc/parabol/commit/e7836627f9a36315af9b8bbd262e60f46b680920)) + ## [7.28.1](https://github.com/ParabolInc/parabol/compare/v7.28.0...v7.28.1) (2024-04-29) diff --git a/package.json b/package.json index b7e73fedc17..3fbf527e7da 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "7.28.1", + "version": "7.29.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/chronos/package.json b/packages/chronos/package.json index 4ff73c7de84..9bf2a082ebc 100644 --- a/packages/chronos/package.json +++ b/packages/chronos/package.json @@ -1,6 +1,6 @@ { "name": "chronos", - "version": "7.28.1", + "version": "7.29.0", "description": "A cron job scheduler", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/chronos#readme", @@ -25,6 +25,6 @@ }, "dependencies": { "cron": "^2.3.1", - "parabol-server": "7.28.1" + "parabol-server": "7.29.0" } } diff --git a/packages/client/package.json b/packages/client/package.json index b6d347b27f4..38222274f35 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "7.28.1", + "version": "7.29.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" diff --git a/packages/embedder/package.json b/packages/embedder/package.json index 1ab680c8bcf..cba142fb90e 100644 --- a/packages/embedder/package.json +++ b/packages/embedder/package.json @@ -1,6 +1,6 @@ { "name": "parabol-embedder", - "version": "7.28.1", + "version": "7.29.0", "description": "A service that computes embedding vectors from Parabol objects", "author": "Jordan Husney ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/embedder#readme", diff --git a/packages/gql-executor/package.json b/packages/gql-executor/package.json index fe462691b1e..0464d2aae00 100644 --- a/packages/gql-executor/package.json +++ b/packages/gql-executor/package.json @@ -1,6 +1,6 @@ { "name": "gql-executor", - "version": "7.28.1", + "version": "7.29.0", "description": "A Stateless GraphQL Executor", "author": "Matt Krick ", "homepage": "https://github.com/ParabolInc/parabol/tree/master/packages/gqlExecutor#readme", @@ -27,8 +27,8 @@ }, "dependencies": { "dd-trace": "^4.2.0", - "parabol-client": "7.28.1", - "parabol-server": "7.28.1", + "parabol-client": "7.29.0", + "parabol-server": "7.29.0", "undici": "^5.26.2" } } diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 3b86b2296b1..02a835d564d 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -2,7 +2,7 @@ "name": "integration-tests", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "7.28.1", + "version": "7.29.0", "description": "", "main": "index.js", "scripts": { diff --git a/packages/server/database/types/User.ts b/packages/server/database/types/User.ts index f59cc8165b3..0f5002becae 100644 --- a/packages/server/database/types/User.ts +++ b/packages/server/database/types/User.ts @@ -13,7 +13,7 @@ interface Input { lastSeenAt?: Date lastSeenAtURLs?: string[] updatedAt?: Date - picture?: string + picture: string inactive?: boolean identities?: AuthIdentity[] isWatched?: boolean @@ -24,9 +24,6 @@ interface Input { tms?: string[] } -const letters = 'abcdefghijklmnopqrstuvwxyz' -const AVATAR_BUCKET = `https://${process.env.AWS_S3_BUCKET}/static/avatars` - export default class User { id: string preferredName: string @@ -69,19 +66,12 @@ export default class User { sendSummaryEmail, tier } = input - const avatarName = - preferredName - .toLowerCase() - .split('') - .filter((letter) => letters.includes(letter)) - .slice(0, 2) - .join('') || 'pa' const now = new Date() this.id = id ?? `local|${generateUID()}` this.tms = tms || [] this.email = email this.createdAt = createdAt || now - this.picture = picture || `${AVATAR_BUCKET}/${avatarName}.png` + this.picture = picture this.updatedAt = updatedAt || now this.featureFlags = featureFlags || [] this.identities = identities || [] diff --git a/packages/server/fileStorage/FileStoreManager.ts b/packages/server/fileStorage/FileStoreManager.ts index 32bb27e2d6d..15aaa525e93 100644 --- a/packages/server/fileStorage/FileStoreManager.ts +++ b/packages/server/fileStorage/FileStoreManager.ts @@ -7,10 +7,10 @@ export default abstract class FileStoreManager { abstract prependPath(partialPath: string, assetDir?: FileAssetDir): string abstract getPublicFileLocation(fullPath: string): string - protected abstract putFile(file: Buffer, fullPath: string): Promise - protected abstract putUserFile(file: Buffer, partialPath: string): Promise - abstract putBuildFile(file: Buffer, partialPath: string): Promise - async putUserAvatar(file: Buffer, userId: string, ext: string, name?: string) { + protected abstract putFile(file: ArrayBufferLike, fullPath: string): Promise + protected abstract putUserFile(file: ArrayBufferLike, partialPath: string): Promise + abstract putBuildFile(file: ArrayBufferLike, partialPath: string): Promise + async putUserAvatar(file: ArrayBufferLike, userId: string, ext: string, name?: string) { const filename = name ?? generateUID() // replace the first dot, if there is one, but not any other dots const dotfreeExt = ext.replace(/^\./, '') @@ -18,14 +18,14 @@ export default abstract class FileStoreManager { return this.putUserFile(file, partialPath) } - async putOrgAvatar(file: Buffer, orgId: string, ext: string, name?: string) { + async putOrgAvatar(file: ArrayBufferLike, orgId: string, ext: string, name?: string) { const filename = name ?? generateUID() const dotfreeExt = ext.replace(/^\./, '') const partialPath = `Organization/${orgId}/picture/${filename}.${dotfreeExt}` return this.putUserFile(file, partialPath) } - async putTemplateIllustration(file: Buffer, orgId: string, ext: string, name?: string) { + async putTemplateIllustration(file: ArrayBufferLike, orgId: string, ext: string, name?: string) { const filename = name ?? generateUID() const dotfreeExt = ext.replace(/^\./, '') const partialPath = `Organization/${orgId}/template/${filename}.${dotfreeExt}` diff --git a/packages/server/fileStorage/GCSManager.ts b/packages/server/fileStorage/GCSManager.ts index d99cf943f69..d5418161889 100644 --- a/packages/server/fileStorage/GCSManager.ts +++ b/packages/server/fileStorage/GCSManager.ts @@ -112,12 +112,12 @@ export default class GCSManager extends FileStoreManager { return this.accessToken } - protected async putUserFile(file: Buffer, partialPath: string) { + protected async putUserFile(file: ArrayBufferLike, partialPath: string) { const fullPath = this.prependPath(partialPath) return this.putFile(file, fullPath) } - protected async putFile(file: Buffer, fullPath: string) { + protected async putFile(file: ArrayBufferLike, fullPath: string) { const url = new URL(`https://storage.googleapis.com/upload/storage/v1/b/${this.bucket}/o`) url.searchParams.append('uploadType', 'media') url.searchParams.append('name', fullPath) @@ -143,7 +143,7 @@ export default class GCSManager extends FileStoreManager { return this.getPublicFileLocation(fullPath) } - putBuildFile(file: Buffer, partialPath: string): Promise { + putBuildFile(file: ArrayBufferLike, partialPath: string): Promise { const fullPath = this.prependPath(partialPath, 'build') return this.putFile(file, fullPath) } diff --git a/packages/server/fileStorage/LocalFileStoreManager.ts b/packages/server/fileStorage/LocalFileStoreManager.ts index 732e3f1cd5d..f6203144279 100644 --- a/packages/server/fileStorage/LocalFileStoreManager.ts +++ b/packages/server/fileStorage/LocalFileStoreManager.ts @@ -12,14 +12,14 @@ export default class LocalFileSystemManager extends FileStoreManager { } } - protected async putUserFile(file: Buffer, partialPath: string) { + protected async putUserFile(file: ArrayBufferLike, partialPath: string) { const fullPath = this.prependPath(partialPath) return this.putFile(file, fullPath) } - protected async putFile(file: Buffer, fullPath: string) { + protected async putFile(file: ArrayBufferLike, fullPath: string) { const fsAbsLocation = path.join(process.cwd(), fullPath) await fs.promises.mkdir(path.dirname(fsAbsLocation), {recursive: true}) - await fs.promises.writeFile(fsAbsLocation, file) + await fs.promises.writeFile(fsAbsLocation, Buffer.from(file)) return this.getPublicFileLocation(fullPath) } diff --git a/packages/server/fileStorage/S3FileStoreManager.ts b/packages/server/fileStorage/S3FileStoreManager.ts index 3971ea80eea..817ad605f40 100644 --- a/packages/server/fileStorage/S3FileStoreManager.ts +++ b/packages/server/fileStorage/S3FileStoreManager.ts @@ -40,13 +40,13 @@ export default class S3Manager extends FileStoreManager { }) } - protected async putUserFile(file: Buffer, partialPath: string) { + protected async putUserFile(file: ArrayBufferLike, partialPath: string) { const fullPath = this.prependPath(partialPath) return this.putFile(file, fullPath) } - protected async putFile(file: Buffer, fullPath: string) { + protected async putFile(file: ArrayBufferLike, fullPath: string) { const s3Params = { - Body: file, + Body: Buffer.from(file), Bucket: this.bucket, Key: fullPath, ContentType: mime.lookup(fullPath) || 'application/octet-stream' @@ -63,7 +63,7 @@ export default class S3Manager extends FileStoreManager { return encodeURI(`${this.baseUrl}${fullPath}`) } - putBuildFile(file: Buffer, partialPath: string): Promise { + putBuildFile(file: ArrayBufferLike, partialPath: string): Promise { const fullPath = this.prependPath(partialPath, 'build') return this.putFile(file, fullPath) } diff --git a/packages/server/graphql/private/mutations/helpers/generateIdenticon.ts b/packages/server/graphql/private/mutations/helpers/generateIdenticon.ts new file mode 100644 index 00000000000..f650a1f6225 --- /dev/null +++ b/packages/server/graphql/private/mutations/helpers/generateIdenticon.ts @@ -0,0 +1,32 @@ +import {createAvatar} from '@dicebear/core' +import * as initials from '@dicebear/initials' +import sharp from 'sharp' +import tailwindPreset from '../../../../../client/tailwindTheme' +import getFileStoreManager from '../../../../fileStorage/getFileStoreManager' + +export const generateIdenticon = async (userId: string, name: string) => { + const letters = 'abcdefghijklmnopqrstuvwxyz' + const {colors} = tailwindPreset.theme + const backgroundColor = Object.values(colors) + .map((color) => { + return color['500']?.slice(1) ?? undefined + }) + .filter(Boolean) + + const seed = + name + .toLowerCase() + .split('') + .filter((letter) => letters.includes(letter)) + .slice(0, 2) + .join('') || 'pa' + const avatar = createAvatar(initials, { + seed, + backgroundColor + }) + const svgBuffer = await avatar.toArrayBuffer() + const pngBuffer = await sharp(svgBuffer).png().toBuffer() + const manager = getFileStoreManager() + const publicLocation = await manager.putUserAvatar(pngBuffer, userId, 'png') + return publicLocation +} diff --git a/packages/server/graphql/private/mutations/loginSAML.ts b/packages/server/graphql/private/mutations/loginSAML.ts index 03584f15300..9e861aa4f98 100644 --- a/packages/server/graphql/private/mutations/loginSAML.ts +++ b/packages/server/graphql/private/mutations/loginSAML.ts @@ -17,6 +17,7 @@ import bootstrapNewUser from '../../mutations/helpers/bootstrapNewUser' import getSignOnURL from '../../public/mutations/helpers/SAMLHelpers/getSignOnURL' import {SSORelayState} from '../../public/queries/SAMLIdP' import {MutationResolvers} from '../resolverTypes' +import {generateIdenticon} from './helpers/generateIdenticon' const serviceProvider = samlify.ServiceProvider({}) samlify.setSchemaValidator(samlXMLValidator) @@ -135,10 +136,12 @@ const loginSAML: MutationResolvers['loginSAML'] = async ( } const userId = `sso|${generateUID()}` + const picture = await generateIdenticon(userId, preferredName) const tempUser = new User({ id: userId, email, preferredName, + picture, tier: 'enterprise' }) diff --git a/packages/server/graphql/public/mutations/loginWithGoogle.ts b/packages/server/graphql/public/mutations/loginWithGoogle.ts index b2d120c4e7f..d09247d482f 100644 --- a/packages/server/graphql/public/mutations/loginWithGoogle.ts +++ b/packages/server/graphql/public/mutations/loginWithGoogle.ts @@ -11,6 +11,7 @@ import getSAMLURLFromEmail from '../../../utils/getSAMLURLFromEmail' import GoogleServerManager from '../../../utils/GoogleServerManager' import standardError from '../../../utils/standardError' import bootstrapNewUser from '../../mutations/helpers/bootstrapNewUser' +import {generateIdenticon} from '../../private/mutations/helpers/generateIdenticon' import {MutationResolvers} from '../resolverTypes' const loginWithGoogle: MutationResolvers['loginWithGoogle'] = async ( @@ -93,7 +94,7 @@ const loginWithGoogle: MutationResolvers['loginWithGoogle'] = async ( const newUser = new User({ id: userId, preferredName, - picture, + picture: picture || (await generateIdenticon(userId, preferredName)), email, identities: [identity], pseudoId diff --git a/packages/server/graphql/public/mutations/loginWithMicrosoft.ts b/packages/server/graphql/public/mutations/loginWithMicrosoft.ts index e41022046d6..045c3a01ebe 100644 --- a/packages/server/graphql/public/mutations/loginWithMicrosoft.ts +++ b/packages/server/graphql/public/mutations/loginWithMicrosoft.ts @@ -11,6 +11,7 @@ import getSAMLURLFromEmail from '../../../utils/getSAMLURLFromEmail' import MicrosoftServerManager from '../../../utils/MicrosoftServerManager' import standardError from '../../../utils/standardError' import bootstrapNewUser from '../../mutations/helpers/bootstrapNewUser' +import {generateIdenticon} from '../../private/mutations/helpers/generateIdenticon' import {MutationResolvers} from '../resolverTypes' const loginWithMicrosoft: MutationResolvers['loginWithMicrosoft'] = async ( @@ -96,6 +97,7 @@ const loginWithMicrosoft: MutationResolvers['loginWithMicrosoft'] = async ( const newUser = new User({ id: userId, preferredName, + picture: await generateIdenticon(userId, preferredName), email, identities: [identity], pseudoId diff --git a/packages/server/graphql/public/mutations/signUpWithPassword.ts b/packages/server/graphql/public/mutations/signUpWithPassword.ts index fa7486a05f0..2982d3fbdc9 100644 --- a/packages/server/graphql/public/mutations/signUpWithPassword.ts +++ b/packages/server/graphql/public/mutations/signUpWithPassword.ts @@ -63,7 +63,12 @@ const signUpWithPassword: MutationResolvers['signUpWithPassword'] = async ( return createEmailVerification({invitationToken, password, pseudoId, email, redirectTo}) } const hashedPassword = await bcrypt.hash(password, Security.SALT_ROUNDS) - const newUser = createNewLocalUser({email, hashedPassword, isEmailVerified: false, pseudoId}) + const newUser = await createNewLocalUser({ + email, + hashedPassword, + isEmailVerified: false, + pseudoId + }) // MUTATIVE context.authToken = await bootstrapNewUser(newUser, isOrganic, dataLoader) return { diff --git a/packages/server/graphql/public/mutations/verifyEmail.ts b/packages/server/graphql/public/mutations/verifyEmail.ts index 0b9485c13e2..8f210c96e7e 100644 --- a/packages/server/graphql/public/mutations/verifyEmail.ts +++ b/packages/server/graphql/public/mutations/verifyEmail.ts @@ -60,7 +60,7 @@ const verifyEmail: MutationResolvers['verifyEmail'] = async ( return {error: {message: 'Invalid hash for email. Please reverify'}} } // user does not exist, create them bootstrap - const newUser = createNewLocalUser({email, hashedPassword, isEmailVerified: true, pseudoId}) + const newUser = await createNewLocalUser({email, hashedPassword, isEmailVerified: true, pseudoId}) // it's possible that the invitationToken is no good. // if that happens, then they'll get into the app & won't be on any team // edge case because that requires the invitation token to have expired diff --git a/packages/server/package.json b/packages/server/package.json index e607e0f94df..f7bd0888ab2 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -3,7 +3,7 @@ "description": "An open-source app for building smarter, more agile teams.", "author": "Parabol Inc. (http://github.com/ParabolInc)", "license": "AGPL-3.0", - "version": "7.28.1", + "version": "7.29.0", "repository": { "type": "git", "url": "https://github.com/ParabolInc/parabol" @@ -76,6 +76,8 @@ "dependencies": { "@amplitude/analytics-node": "^1.3.2", "@aws-sdk/client-s3": "^3.347.1", + "@dicebear/core": "^8.0.1", + "@dicebear/initials": "^8.0.1", "@graphql-tools/schema": "^9.0.16", "@mattkrick/sanitize-svg": "0.4.0", "@octokit/graphql-schema": "^10.36.0", @@ -120,7 +122,7 @@ "oauth-1.0a": "^2.2.6", "openai": "^4.24.1", "oy-vey": "^0.12.1", - "parabol-client": "7.28.1", + "parabol-client": "7.29.0", "pg": "^8.5.1", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/packages/server/utils/createNewLocalUser.ts b/packages/server/utils/createNewLocalUser.ts index 4c216fb19b0..92037c394fe 100644 --- a/packages/server/utils/createNewLocalUser.ts +++ b/packages/server/utils/createNewLocalUser.ts @@ -1,6 +1,8 @@ import {AuthIdentityTypeEnum} from '../../client/types/constEnums' import AuthIdentityLocal from '../database/types/AuthIdentityLocal' import User from '../database/types/User' +import generateUID from '../generateUID' +import {generateIdenticon} from '../graphql/private/mutations/helpers/generateIdenticon' interface Props { email: string @@ -9,17 +11,19 @@ interface Props { isEmailVerified: boolean } -const createNewLocalUser = (props: Props) => { +const createNewLocalUser = async (props: Props) => { const {email, hashedPassword, pseudoId, isEmailVerified} = props const nickname = email.split('@')[0]! const preferredName = nickname.length === 1 ? nickname.repeat(2) : nickname + const userId = `local|${generateUID()}` const newUser = new User({ + id: userId, preferredName, email, + picture: await generateIdenticon(userId, preferredName), identities: [], pseudoId }) - const {id: userId} = newUser const identityId = `${userId}:${AuthIdentityTypeEnum.LOCAL}` newUser.identities.push(new AuthIdentityLocal({hashedPassword, id: identityId, isEmailVerified})) return newUser diff --git a/scripts/webpack/dev.servers.config.js b/scripts/webpack/dev.servers.config.js index 0d8e4db7e0e..198cebc52b4 100644 --- a/scripts/webpack/dev.servers.config.js +++ b/scripts/webpack/dev.servers.config.js @@ -34,8 +34,7 @@ module.exports = { }, output: { filename: '[name].js', - path: path.join(PROJECT_ROOT, 'dev'), - libraryTarget: 'commonjs' + path: path.join(PROJECT_ROOT, 'dev') }, resolve: { alias: { @@ -54,13 +53,15 @@ module.exports = { target: 'node', externals: [ nodeExternals({ - allowlist: [/parabol-client/, /parabol-server/] + allowlist: [/parabol-client/, /parabol-server/, /@dicebear/] }) ], plugins: [ new webpack.DefinePlugin({ __PRODUCTION__: false - }) + }), + new webpack.IgnorePlugin({resourceRegExp: /^exiftool-vendored$/, contextRegExp: /@dicebear/}), + new webpack.IgnorePlugin({resourceRegExp: /^@resvg\/resvg-js$/, contextRegExp: /@dicebear/}) ], module: { rules: [ diff --git a/scripts/webpack/prod.servers.config.js b/scripts/webpack/prod.servers.config.js index 4f11b012db4..2d81fd739df 100644 --- a/scripts/webpack/prod.servers.config.js +++ b/scripts/webpack/prod.servers.config.js @@ -67,7 +67,7 @@ module.exports = (config) => { externals: [ !noDeps && nodeExternals({ - allowlist: [/parabol-client/, /parabol-server/] + allowlist: [/parabol-client/, /parabol-server/, /@dicebear/] }) ].filter(Boolean), optimization: { @@ -92,6 +92,9 @@ module.exports = (config) => { new webpack.IgnorePlugin({resourceRegExp: /^canvas$/, contextRegExp: /jsdom$/}), // native bindings might be faster, but abandonware & not currently used new webpack.IgnorePlugin({resourceRegExp: /^pg-native$/, contextRegExp: /pg\/lib/}), + new webpack.IgnorePlugin({resourceRegExp: /^exiftool-vendored$/, contextRegExp: /@dicebear/}), + new webpack.IgnorePlugin({resourceRegExp: /^@resvg\/resvg-js$/, contextRegExp: /@dicebear/}), + noDeps && new CopyWebpackPlugin({ patterns: [ diff --git a/scripts/webpack/toolbox.config.js b/scripts/webpack/toolbox.config.js index d63a8f6505c..bb3913a2b78 100644 --- a/scripts/webpack/toolbox.config.js +++ b/scripts/webpack/toolbox.config.js @@ -49,13 +49,15 @@ module.exports = { target: 'node', externals: [ nodeExternals({ - allowlist: [/parabol-client/, '/parabol-server/'] + allowlist: [/parabol-client/, /parabol-server/, /@dicebear/] }) ], plugins: [ new webpack.DefinePlugin({ __PRODUCTION__: true - }) + }), + new webpack.IgnorePlugin({resourceRegExp: /^exiftool-vendored$/, contextRegExp: /@dicebear/}), + new webpack.IgnorePlugin({resourceRegExp: /^@resvg\/resvg-js$/, contextRegExp: /@dicebear/}) // new CircularDependencyPlugin({ // // `onStart` is called before the cycle detection starts // onStart({compilation}) { diff --git a/yarn.lock b/yarn.lock index 19cdfead7f3..7d65afd154f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3007,6 +3007,27 @@ resolved "https://registry.yarnpkg.com/@datadog/sketches-js/-/sketches-js-2.1.0.tgz#8c7e8028a5fc22ad102fa542b0a446c956830455" integrity sha512-smLocSfrt3s53H/XSVP3/1kP42oqvrkjUPtyaFd1F79ux24oE31BKt+q0c6lsa6hOYrFzsIwyc5GXAI5JmfOew== +"@dicebear/converter@8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@dicebear/converter/-/converter-8.0.1.tgz#c037c1404f73a994ee4f943928edb367029425e1" + integrity sha512-65L04fN4V07WcUnwQuDYDH+zrP8WA6/UeIuqqH/Pv7VWoJtIk9qHlaA+XGpPr4qgRtkmY7uXVkrED/RMlqvUDA== + dependencies: + "@types/json-schema" "^7.0.11" + tmp-promise "^3.0.3" + +"@dicebear/core@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@dicebear/core/-/core-8.0.1.tgz#3ac1e98a5380071c4a1e0d874cc8ff83b1c9ba8f" + integrity sha512-HWqvQRpVjkboQXinCOjU3poZIMd5p+32wPvc9N5fYiXe3KQLhJNw5T5XiRttDUm3XpoTvhQ4DVTPDsXT8CqrTg== + dependencies: + "@dicebear/converter" "8.0.1" + "@types/json-schema" "^7.0.11" + +"@dicebear/initials@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@dicebear/initials/-/initials-8.0.1.tgz#0e9686abd67af452f650373ab1156104aecb37ed" + integrity sha512-ctO1f92XAms72qkhiKI/vvS/E6mco1RiTEACPJGv6hDPfdjR1vxpkzFpo3jm3RohfwOPCN5fH2l3BSinnlbzzw== + "@discoveryjs/json-ext@^0.5.0": version "0.5.6" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" @@ -10231,9 +10252,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001580, caniuse-lite@~1.0.0: - version "1.0.30001608" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz#7ae6e92ffb300e4b4ec2f795e0abab456ec06cc0" - integrity sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA== + version "1.0.30001614" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz#f894b4209376a0bf923d67d9c361d96b1dfebe39" + integrity sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog== capital-case@^1.0.4: version "1.0.4" @@ -21251,6 +21272,13 @@ tlds@^1.192.0: resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.228.0.tgz#416ab76ac1a06aad0b5d6b484a13bf5a0ad63f39" integrity sha512-Q0TU9zh5hDs2CpRFNM7SOW3K7OSgUgJC/cMrq9t44ei4tu+G3KV8BZyIJuYVvryJHH96mKgc9WXdhgKVvGD7jg== +tmp-promise@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7" + integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ== + dependencies: + tmp "^0.2.0" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -21258,6 +21286,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + tmp@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"