mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-02-24 02:46:11 -05:00
Fix linting
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
"semi": false,
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": false,
|
||||
"plugins": ["prettier-plugin-sql"],
|
||||
"overrides": [
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import pgPromise, {IDatabase, ITask} from 'pg-promise'
|
||||
import {log, metrics} from '../utils'
|
||||
import {IClient, type IConnectionParameters} from 'pg-promise/typescript/pg-subset'
|
||||
import {IClient, type IConnectionParameters,} from 'pg-promise/typescript/pg-subset'
|
||||
import {HOUR_MS} from 'common/util/time'
|
||||
import {METRICS_INTERVAL_MS} from 'shared/monitoring/metric-writer'
|
||||
import {getMonitoringContext} from 'shared/monitoring/context'
|
||||
import {ENV_CONFIG} from "common/envs/constants";
|
||||
import {ENV_CONFIG} from 'common/envs/constants'
|
||||
|
||||
export {SupabaseClient} from 'common/supabase/utils'
|
||||
|
||||
@@ -32,8 +32,10 @@ export const pgp = pgPromise({
|
||||
pgp.pg.types.setTypeParser(20, (value: any) => parseInt(value, 10))
|
||||
pgp.pg.types.setTypeParser(1700, parseFloat) // Type Id 1700 = NUMERIC
|
||||
|
||||
export type SupabaseTransaction = ITask<{}>
|
||||
export type SupabaseDirectClient = IDatabase<{}, IClient> | SupabaseTransaction
|
||||
export type SupabaseTransaction = ITask<object>
|
||||
export type SupabaseDirectClient =
|
||||
| IDatabase<object, IClient>
|
||||
| SupabaseTransaction
|
||||
|
||||
export function getInstanceId() {
|
||||
return ENV_CONFIG.supabaseInstanceId
|
||||
@@ -87,7 +89,7 @@ const newClient = (
|
||||
}
|
||||
|
||||
// Use one connection to avoid WARNING: Creating a duplicate database object for the same connection.
|
||||
let pgpDirect: IDatabase<{}, IClient> | null = null
|
||||
let pgpDirect: IDatabase<object, IClient> | null = null
|
||||
|
||||
export function createSupabaseDirectClient(
|
||||
instanceId?: string,
|
||||
@@ -128,7 +130,7 @@ export function createSupabaseDirectClient(
|
||||
return (pgpDirect = client)
|
||||
}
|
||||
|
||||
let shortTimeoutPgpClient: IDatabase<{}, IClient> | null = null
|
||||
let shortTimeoutPgpClient: IDatabase<object, IClient> | null = null
|
||||
export const createShortTimeoutDirectClient = () => {
|
||||
if (shortTimeoutPgpClient) return shortTimeoutPgpClient
|
||||
shortTimeoutPgpClient = newClient({
|
||||
|
||||
@@ -7,7 +7,7 @@ export const isProd = () => {
|
||||
return process.env.NEXT_PUBLIC_FIREBASE_ENV?.toUpperCase() == 'PROD'
|
||||
} else {
|
||||
// For local scripts and cloud functions
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const admin = require('firebase-admin')
|
||||
return admin.app().options.projectId === 'compass-130ba'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const safeJsonParse = (json: string | undefined | null) => {
|
||||
try {
|
||||
return JSON.parse(json ?? '')
|
||||
} catch (e) {
|
||||
return JSON.parse(json ?? '')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
14
package.json
14
package.json
@@ -45,7 +45,19 @@
|
||||
"prepare": "npx husky"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,js,jsx}": [
|
||||
"web/**/*.{ts,tsx,js,jsx}": [
|
||||
"next lint --fix --file",
|
||||
"next lint --max-warnings 0 --file"
|
||||
],
|
||||
"common/**/*.{ts,tsx,js,jsx}": [
|
||||
"eslint --fix",
|
||||
"eslint --max-warnings 0"
|
||||
],
|
||||
"backend/api/**/*.{ts,tsx,js,jsx}": [
|
||||
"eslint --fix",
|
||||
"eslint --max-warnings 0"
|
||||
],
|
||||
"backend/shared/**/*.{ts,tsx,js,jsx}": [
|
||||
"eslint --fix",
|
||||
"eslint --max-warnings 0"
|
||||
]
|
||||
|
||||
@@ -15,6 +15,7 @@ module.exports = {
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
"react/prop-types": "off",
|
||||
'react/display-name': 'off',
|
||||
'react/no-unescaped-entities': 'off',
|
||||
'react/jsx-no-target-blank': 'off',
|
||||
|
||||
@@ -29,11 +29,7 @@ export function AddCompatibilityQuestionButton(props: {
|
||||
if (!user) return null
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(true)}
|
||||
className="text-sm"
|
||||
>
|
||||
<button type="button" onClick={() => setOpen(true)} className="text-sm">
|
||||
{t('answers.add.submit_own', 'submit your own!')}
|
||||
</button>
|
||||
<AddCompatibilityQuestionModal
|
||||
@@ -55,9 +51,8 @@ function AddCompatibilityQuestionModal(props: {
|
||||
onClose?: () => void
|
||||
}) {
|
||||
const {open, setOpen, user, onClose} = props
|
||||
const [dbQuestion, setDbQuestion] = useState<rowFor<'compatibility_prompts'> | null>(
|
||||
null
|
||||
)
|
||||
const [dbQuestion, setDbQuestion] =
|
||||
useState<rowFor<'compatibility_prompts'> | null>(null)
|
||||
const afterAddQuestion = (newQuestion: rowFor<'compatibility_prompts'>) => {
|
||||
setDbQuestion(newQuestion)
|
||||
console.debug('setDbQuestion', newQuestion)
|
||||
@@ -125,12 +120,15 @@ function CreateCompatibilityModalContent(props: {
|
||||
|
||||
const generateJson = () => {
|
||||
// Note the change in the generic type
|
||||
return options.reduce((obj, item, index) => {
|
||||
if (item.trim() !== '') {
|
||||
obj[item] = index // Mapping each option to its index
|
||||
}
|
||||
return obj
|
||||
}, {} as Record<string, number>)
|
||||
return options.reduce(
|
||||
(obj, item, index) => {
|
||||
if (item.trim() !== '') {
|
||||
obj[item] = index // Mapping each option to its index
|
||||
}
|
||||
return obj
|
||||
},
|
||||
{} as Record<string, number>
|
||||
)
|
||||
}
|
||||
|
||||
const onAddQuestion = useEvent(async () => {
|
||||
@@ -138,7 +136,7 @@ function CreateCompatibilityModalContent(props: {
|
||||
const data = {
|
||||
question: question,
|
||||
options: generateJson(),
|
||||
};
|
||||
}
|
||||
const newQuestion = await api('create-compatibility-question', data)
|
||||
console.debug('create-compatibility-question', newQuestion, data)
|
||||
const q = newQuestion?.question
|
||||
@@ -146,8 +144,13 @@ function CreateCompatibilityModalContent(props: {
|
||||
afterAddQuestion(q as rowFor<'compatibility_prompts'>)
|
||||
}
|
||||
track('create compatibility question')
|
||||
} catch (e) {
|
||||
toast.error(t('answers.add.error_create', 'Error creating compatibility question. Try again?'))
|
||||
} catch (_e) {
|
||||
toast.error(
|
||||
t(
|
||||
'answers.add.error_create',
|
||||
'Error creating compatibility question. Try again?'
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -176,7 +179,9 @@ function CreateCompatibilityModalContent(props: {
|
||||
value={options[index]}
|
||||
onChange={(e) => onOptionChange(index, e.target.value)}
|
||||
className="w-full"
|
||||
placeholder={t('answers.add.option_placeholder', 'Option {n}', {n: String(index + 1)})}
|
||||
placeholder={t('answers.add.option_placeholder', 'Option {n}', {
|
||||
n: String(index + 1),
|
||||
})}
|
||||
rows={1}
|
||||
maxLength={MAX_ANSWER_LENGTH}
|
||||
/>
|
||||
|
||||
@@ -67,7 +67,7 @@ export const submitCompatibilityAnswer = async (
|
||||
explanation: input.explanation ?? null,
|
||||
})
|
||||
|
||||
// Track only if the upsert succeeds
|
||||
// Track only if upsert succeeds
|
||||
track('answer compatibility question', {
|
||||
...newAnswer,
|
||||
})
|
||||
@@ -179,7 +179,7 @@ export function AnswerCompatibilityQuestionContent(props: {
|
||||
{shortenedPopularity && (
|
||||
<Row className="text-ink-500 select-none items-center text-sm">
|
||||
<Tooltip
|
||||
text={t('answers.content.people_answered', '{count} people have answered this question', { count: String(shortenedPopularity) })}
|
||||
text={t('answers.content.people_answered', '{count} people have answered this question', {count: String(shortenedPopularity)})}
|
||||
>
|
||||
{shortenedPopularity}
|
||||
</Tooltip>
|
||||
@@ -204,7 +204,8 @@ export function AnswerCompatibilityQuestionContent(props: {
|
||||
/>
|
||||
</Col>
|
||||
<Col className="gap-2">
|
||||
<span className="text-ink-500 text-sm">{t('answers.content.answers_you_accept', "Answers you'll accept")}</span>
|
||||
<span
|
||||
className="text-ink-500 text-sm">{t('answers.content.answers_you_accept', "Answers you'll accept")}</span>
|
||||
<MultiSelectAnswers
|
||||
values={answer.pref_choices ?? []}
|
||||
setValue={(choice) =>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { LinkIcon, CheckIcon, TrashIcon } from '@heroicons/react/solid'
|
||||
import { Editor } from '@tiptap/core'
|
||||
import { BubbleMenu } from '@tiptap/react'
|
||||
import {CheckIcon, LinkIcon, TrashIcon} from '@heroicons/react/solid'
|
||||
import {Editor} from '@tiptap/core'
|
||||
import {BubbleMenu} from '@tiptap/react'
|
||||
import clsx from 'clsx'
|
||||
import { getUrl } from 'common/util/parse'
|
||||
import { useState } from 'react'
|
||||
import BoldIcon from 'web/lib/icons/bold-icon.svg'
|
||||
import ItalicIcon from 'web/lib/icons/italic-icon.svg'
|
||||
import TypeIcon from 'web/lib/icons/type-icon.svg'
|
||||
import {getUrl} from 'common/util/parse'
|
||||
import {useState} from 'react'
|
||||
import {Bold, Italic, Type} from 'lucide-react'
|
||||
|
||||
// see https://tiptap.dev/guide/menus
|
||||
|
||||
@@ -40,14 +38,14 @@ export function FloatingFormatMenu(props: {
|
||||
{advanced && (
|
||||
<>
|
||||
<IconButton
|
||||
icon={TypeIcon}
|
||||
icon={Type}
|
||||
onClick={() =>
|
||||
editor.chain().focus().toggleHeading({ level: 1 }).run()
|
||||
}
|
||||
isActive={editor.isActive('heading', { level: 1 })}
|
||||
/>
|
||||
<IconButton
|
||||
icon={TypeIcon}
|
||||
icon={Type}
|
||||
onClick={() =>
|
||||
editor.chain().focus().toggleHeading({ level: 2 }).run()
|
||||
}
|
||||
@@ -58,12 +56,12 @@ export function FloatingFormatMenu(props: {
|
||||
</>
|
||||
)}
|
||||
<IconButton
|
||||
icon={BoldIcon}
|
||||
icon={Bold}
|
||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||
isActive={editor.isActive('bold')}
|
||||
/>
|
||||
<IconButton
|
||||
icon={ItalicIcon}
|
||||
icon={Italic}
|
||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||
isActive={editor.isActive('italic')}
|
||||
/>
|
||||
|
||||
@@ -4,8 +4,8 @@ import {Input} from 'web/components/widgets/input'
|
||||
import {Button} from 'web/components/buttons/button'
|
||||
import clsx from 'clsx'
|
||||
import {useEffect, useMemo, useState} from 'react'
|
||||
import {useT} from "web/lib/locale";
|
||||
import {toKey} from "common/parsing";
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {toKey} from 'common/parsing'
|
||||
|
||||
export const MultiCheckbox = (props: {
|
||||
// Map of label -> value
|
||||
@@ -20,14 +20,27 @@ export const MultiCheckbox = (props: {
|
||||
// - string: the stored value for the new option; label will be the input text
|
||||
// - { key, value }: explicit label (key) and stored value
|
||||
// - null/undefined to indicate failure/cancellation
|
||||
addOption?: (label: string) => string | { key: string; value: string } | null | undefined
|
||||
addOption?: (
|
||||
label: string
|
||||
) => string | { key: string; value: string } | null | undefined
|
||||
addPlaceholder?: string
|
||||
translationPrefix?: string
|
||||
}) => {
|
||||
const {choices, selected, onChange, className, optionsClassName, addOption, addPlaceholder, translationPrefix} = props
|
||||
const {
|
||||
choices,
|
||||
selected,
|
||||
onChange,
|
||||
className,
|
||||
optionsClassName,
|
||||
addOption,
|
||||
addPlaceholder,
|
||||
translationPrefix,
|
||||
} = props
|
||||
|
||||
// Keep a local merged copy to allow optimistic adds while remaining in sync with props
|
||||
const [localChoices, setLocalChoices] = useState<{ [key: string]: string }>(choices)
|
||||
const [localChoices, setLocalChoices] = useState<{ [key: string]: string }>(
|
||||
choices
|
||||
)
|
||||
useEffect(() => {
|
||||
setLocalChoices((prev) => {
|
||||
// If incoming choices changed, merge them with any locally added that still don't collide
|
||||
@@ -56,7 +69,9 @@ export const MultiCheckbox = (props: {
|
||||
let q = newLabel.trim()
|
||||
q = translateOption(q, q).toLowerCase()
|
||||
if (!q) return entries
|
||||
return entries.filter(([key, value]) => translateOption(key, value).toLowerCase().includes(q))
|
||||
return entries.filter(([key, value]) =>
|
||||
translateOption(key, value).toLowerCase().includes(q)
|
||||
)
|
||||
}, [addOption, entries, newLabel])
|
||||
|
||||
const submitAdd = async () => {
|
||||
@@ -68,8 +83,10 @@ export const MultiCheckbox = (props: {
|
||||
return
|
||||
}
|
||||
// prevent duplicate by label or by value already selected
|
||||
const existingEntry = Object.entries(localChoices).find(([key, value]) =>
|
||||
translateOption(key, value).toLowerCase() === translateOption(label, label).toLowerCase()
|
||||
const existingEntry = Object.entries(localChoices).find(
|
||||
([key, value]) =>
|
||||
translateOption(key, value).toLowerCase() ===
|
||||
translateOption(label, label).toLowerCase()
|
||||
)
|
||||
|
||||
if (existingEntry) {
|
||||
@@ -88,12 +105,13 @@ export const MultiCheckbox = (props: {
|
||||
setAdding(false)
|
||||
return
|
||||
}
|
||||
const {key, value} = typeof result === 'string' ? {key: label, value: result} : result
|
||||
const {key, value} =
|
||||
typeof result === 'string' ? {key: label, value: result} : result
|
||||
setLocalChoices((prev) => ({...prev, [key]: value}))
|
||||
// auto-select newly added option if not already selected
|
||||
if (!selected.includes(value)) onChange([...selected, value])
|
||||
setNewLabel('')
|
||||
} catch (e) {
|
||||
} catch (_e) {
|
||||
setError(t('multi-checkbox.add_failed', 'Failed to add option.'))
|
||||
} finally {
|
||||
setAdding(false)
|
||||
@@ -106,7 +124,10 @@ export const MultiCheckbox = (props: {
|
||||
<Row className="items-center gap-2">
|
||||
<Input
|
||||
value={newLabel}
|
||||
placeholder={addPlaceholder ?? t('multi-checkbox.search_or_add', 'Search or add')}
|
||||
placeholder={
|
||||
addPlaceholder ??
|
||||
t('multi-checkbox.search_or_add', 'Search or add')
|
||||
}
|
||||
onChange={(e) => {
|
||||
setNewLabel(e.target.value)
|
||||
setError(null)
|
||||
@@ -119,7 +140,12 @@ export const MultiCheckbox = (props: {
|
||||
}}
|
||||
className="h-10"
|
||||
/>
|
||||
<Button size="sm" onClick={submitAdd} loading={adding} disabled={adding}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={submitAdd}
|
||||
loading={adding}
|
||||
disabled={adding}
|
||||
>
|
||||
{t('common.add', 'Add')}
|
||||
</Button>
|
||||
{error && <span className="text-sm text-error">{error}</span>}
|
||||
@@ -144,9 +170,12 @@ export const MultiCheckbox = (props: {
|
||||
</Row>
|
||||
{addOption && newLabel.trim() && filteredEntries.length === 0 && (
|
||||
<div className="px-2 text-sm text-ink-500">
|
||||
{t('multi-checkbox.no_matching_options', 'No matching options, feel free to add it.')}
|
||||
{t(
|
||||
'multi-checkbox.no_matching_options',
|
||||
'No matching options, feel free to add it.'
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,9 @@ export const OptionalProfileUserForm = (props: {
|
||||
return
|
||||
}
|
||||
}
|
||||
onSubmit && (await onSubmit())
|
||||
if (onSubmit) {
|
||||
await onSubmit()
|
||||
}
|
||||
track('submit optional profile')
|
||||
if (user) {
|
||||
let profile
|
||||
|
||||
@@ -60,7 +60,7 @@ export function PageBase(props: {
|
||||
)
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
trackPageView && useTracking(`view ${trackPageView}`, trackPageProps)
|
||||
if (trackPageView) useTracking(`view ${trackPageView}`, trackPageProps)
|
||||
useOnline()
|
||||
const [_, setIsAddFundsModalOpen] = useState(false)
|
||||
|
||||
|
||||
@@ -72,10 +72,10 @@ export const RequiredProfileUserForm = (props: {
|
||||
} = userInfo
|
||||
|
||||
useEffect(() => {
|
||||
props.setEditUsername && props.setEditUsername(username)
|
||||
if (props.setEditUsername) props.setEditUsername(username)
|
||||
}, [username])
|
||||
useEffect(() => {
|
||||
props.setEditDisplayName && props.setEditDisplayName(name)
|
||||
if (props.setEditDisplayName) props.setEditDisplayName(name)
|
||||
}, [name])
|
||||
|
||||
const canContinue = true
|
||||
|
||||
@@ -12,22 +12,10 @@ export const Input = forwardRef(
|
||||
const { error, className, ...rest } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<style jsx>{`
|
||||
input::-webkit-inner-spin-button,
|
||||
input::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
input {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
`}</style>
|
||||
<input
|
||||
<input
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
'invalid:border-error invalid:text-error disabled:bg-canvas-50 disabled:border-ink-200 disabled:text-ink-500 bg-canvas-0 h-12 rounded-md border px-4 shadow-sm transition-colors invalid:placeholder-rose-700 focus:outline-none focus:ring-1 disabled:cursor-not-allowed md:text-sm',
|
||||
'invalid:border-error invalid:text-error disabled:bg-canvas-50 disabled:border-ink-200 disabled:text-ink-500 bg-canvas-0 h-12 rounded-md border px-4 shadow-sm transition-colors invalid:placeholder-rose-700 focus:outline-none focus:ring-1 disabled:cursor-not-allowed md:text-sm [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:m-0 [&::-webkit-outer-spin-button]:m-0',
|
||||
error
|
||||
? 'border-error text-error focus:border-error focus:ring-error placeholder-rose-700' // matches invalid: styles
|
||||
: 'border-ink-300 placeholder-ink-400 focus:ring-primary-500 focus:border-primary-500',
|
||||
@@ -36,7 +24,6 @@ export const Input = forwardRef(
|
||||
step={0.001} // default to 3 decimal places
|
||||
{...rest}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ export function updateSupabaseAuth(token?: string) {
|
||||
if (currentToken != token) {
|
||||
currentToken = token
|
||||
if (token == null) {
|
||||
db['rest'].headers['Authorization']
|
||||
// db['rest'].headers['Authorization']
|
||||
db['realtime'].setAuth(null)
|
||||
} else {
|
||||
db['rest'].headers['Authorization'] = `Bearer ${token}`
|
||||
|
||||
@@ -2,8 +2,8 @@ import {db} from './db'
|
||||
import {run} from 'common/supabase/utils'
|
||||
import {api} from 'web/lib/api'
|
||||
import type {DisplayUser} from 'common/api/user-types'
|
||||
import {MONTH_MS} from "common/util/time";
|
||||
import {APIError} from "common/api/utils";
|
||||
import {MONTH_MS} from 'common/util/time'
|
||||
import {APIError} from 'common/api/utils'
|
||||
|
||||
export type {DisplayUser}
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function getUserSafe(userId: string) {
|
||||
export async function getPrivateUserSafe() {
|
||||
try {
|
||||
return await api('me/private')
|
||||
} catch (e) {
|
||||
} catch (_e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -59,9 +59,7 @@ export async function getDisplayUsers(userIds: string[]) {
|
||||
|
||||
export async function getProfilesCreations() {
|
||||
const {data} = await run(
|
||||
db.from('profiles')
|
||||
.select(`id, created_time`)
|
||||
.order('created_time')
|
||||
db.from('profiles').select(`id, created_time`).order('created_time')
|
||||
)
|
||||
return data
|
||||
}
|
||||
@@ -89,14 +87,12 @@ export async function getCount(table: string) {
|
||||
.select('*', {count: 'exact', head: true})
|
||||
.gt('last_online_time', new Date(Date.now() - MONTH_MS).toISOString()) // last month
|
||||
)
|
||||
return count;
|
||||
return count
|
||||
}
|
||||
const {count} = await run(
|
||||
db
|
||||
.from(table)
|
||||
.select('*', {count: 'exact', head: true})
|
||||
db.from(table).select('*', {count: 'exact', head: true})
|
||||
)
|
||||
return count;
|
||||
return count
|
||||
}
|
||||
|
||||
// export async function getNumberProfiles() {
|
||||
|
||||
@@ -18,7 +18,7 @@ function getStorageProxy(store: Storage): Store | undefined {
|
||||
setItem: (key: string, value: string) => {
|
||||
try {
|
||||
store.setItem(key, value)
|
||||
} catch (e) {
|
||||
} catch {
|
||||
store.clear()
|
||||
// try again
|
||||
store.setItem(key, value)
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"heic2any": "0.0.4",
|
||||
"link-preview-js": "3.0.4",
|
||||
"lodash": "4.17.23",
|
||||
"lucide-react": "0.575.0",
|
||||
"nanoid": "5.0.9",
|
||||
"next": "14.1.0",
|
||||
"posthog-js": "1.234.1",
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"typeRoots": [
|
||||
"./types",
|
||||
"./node_modules/@types"
|
||||
],
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
|
||||
@@ -11242,6 +11242,11 @@ lsofi@1.0.0:
|
||||
is-number "^2.1.0"
|
||||
through2 "^2.0.1"
|
||||
|
||||
lucide-react@0.575.0:
|
||||
version "0.575.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.575.0.tgz#90feaa4c140e9693e4ee9426d9927a6b833267ac"
|
||||
integrity sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg==
|
||||
|
||||
lz-string@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
|
||||
|
||||
Reference in New Issue
Block a user