Website improvements 4 (#3182)

* Add contributor individual page

* Improve mobile menu

* Fix

* Remove yarn.lock from twenty-website

* Add yarn to gitingore

* Fix linter
This commit is contained in:
Félix Malfait
2023-12-31 10:41:53 +01:00
committed by GitHub
parent 97f83b55b0
commit 858c294f14
60 changed files with 571 additions and 9797 deletions

3
.gitignore vendored
View File

@ -17,3 +17,6 @@
!.yarn/sdks
!.yarn/versions
.vercel
# yarn.lock should be managed at the root level only (nx monorepo)
**/yarn.lock

View File

@ -6,12 +6,12 @@ import { isNonEmptyString } from '@sniptt/guards';
import debounce from 'lodash.debounce';
import { Activity } from '@/activities/types/Activity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { BlockEditor } from '@/ui/input/editor/components/BlockEditor';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledBlockNoteStyledContainer = styled.div`
width: 100%;

View File

@ -7,6 +7,7 @@ import { Comment } from '@/activities/comment/Comment';
import { Activity } from '@/activities/types/Activity';
import { Comment as CommentType } from '@/activities/types/Comment';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import {
@ -14,7 +15,6 @@ import {
AutosizeTextInputVariant,
} from '@/ui/input/components/AutosizeTextInput';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledThreadItemListContainer = styled.div`
align-items: flex-start;

View File

@ -6,6 +6,7 @@ import { AttachmentDropdown } from '@/activities/files/components/AttachmentDrop
import { AttachmentIcon } from '@/activities/files/components/AttachmentIcon';
import { Attachment } from '@/activities/files/types/Attachment';
import { downloadFile } from '@/activities/files/utils/downloadFile';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import {
FieldContext,
GenericFieldContextType,
@ -14,7 +15,6 @@ import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { IconCalendar } from '@/ui/display/icon';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { formatToHumanReadableDate } from '~/utils';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledRow = styled.div`
align-items: center;

View File

@ -8,11 +8,11 @@ import { Attachment } from '@/activities/files/types/Attachment';
import { getFileType } from '@/activities/files/utils/getFileType';
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { IconPlus } from '@/ui/display/icon';
import { Button } from '@/ui/input/button/components/Button';
import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledTaskGroupEmptyContainer = styled.div`
align-items: center;

View File

@ -1,8 +1,8 @@
import { Attachment } from '@/activities/files/types/Attachment';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { ActivityTargetableEntity } from '../../types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
// do we need to test this?
export const useAttachments = (entity: ActivityTargetableEntity) => {

View File

@ -5,6 +5,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
import { Activity, ActivityType } from '@/activities/types/Activity';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
@ -15,7 +16,6 @@ import { activityTargetableEntityArrayState } from '../states/activityTargetable
import { viewableActivityIdState } from '../states/viewableActivityIdState';
import { ActivityTargetableEntity } from '../types/ActivityTargetableEntity';
import { getTargetableEntitiesWithParents } from '../utils/getTargetableEntitiesWithParents';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useOpenCreateActivityDrawer = () => {
const { openRightDrawer } = useRightDrawer();

View File

@ -6,12 +6,12 @@ import { useHandleCheckableActivityTargetChange } from '@/activities/hooks/useHa
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/activities/utils/flatMapAndSortEntityForSelectArrayByName';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
import { MultipleEntitySelect } from '@/object-record/relation-picker/components/MultipleEntitySelect';
import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker';
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
import { assertNotNull } from '~/utils/assert';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
type ActivityTargetInlineCellEditModeProps = {
activityId: string;

View File

@ -1,9 +1,9 @@
import { Note } from '@/activities/types/Note';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { OrderByField } from '@/object-metadata/types/OrderByField';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { ActivityTargetableEntity } from '../../types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useNotes = (entity: ActivityTargetableEntity) => {
const { records: activityTargets } = useFindManyRecords({

View File

@ -1,10 +1,10 @@
import { useRecoilState } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { IconTrash } from '@/ui/display/icon';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
type ActivityActionBarProps = {
activityId: string;

View File

@ -4,11 +4,11 @@ import { useRecoilState } from 'recoil';
import { ActivityEditor } from '@/activities/components/ActivityEditor';
import { Activity } from '@/activities/types/Activity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import '@blocknote/core/style.css';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledContainer = styled.div`
box-sizing: border-box;

View File

@ -6,6 +6,7 @@ import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRi
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { GraphQLActivity } from '@/activities/types/GraphQLActivity';
import { getActivitySummary } from '@/activities/utils/getActivitySummary';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { IconCalendar, IconComment } from '@/ui/display/icon';
import { OverflowingTextWithTooltip } from '@/ui/display/tooltip/OverflowingTextWithTooltip';
@ -13,7 +14,6 @@ import { Checkbox, CheckboxShape } from '@/ui/input/components/Checkbox';
import { beautifyExactDate, hasDatePassed } from '~/utils/date-utils';
import { useCompleteTask } from '../hooks/useCompleteTask';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledContainer = styled.div`
align-items: center;

View File

@ -1,8 +1,8 @@
import { useCallback } from 'react';
import { Activity } from '@/activities/types/Activity';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
type Task = Pick<Activity, 'id' | 'completedAt'>;

View File

@ -2,9 +2,9 @@ import { DateTime } from 'luxon';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { parseDate } from '~/utils/date-utils';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useCurrentUserTaskCount = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);

View File

@ -3,11 +3,11 @@ import { DateTime } from 'luxon';
import { Activity } from '@/activities/types/Activity';
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { parseDate } from '~/utils/date-utils';
import { isDefined } from '~/utils/isDefined';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
type UseTasksProps = {
filterDropdownId?: string;

View File

@ -5,11 +5,11 @@ import { ActivityCreateButton } from '@/activities/components/ActivityCreateButt
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { Activity } from '@/activities/types/Activity';
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { TimelineItemsContainer } from './TimelineItemsContainer';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledMainContainer = styled.div`
align-items: flex-start;

View File

@ -6,6 +6,7 @@ import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRi
import { Activity } from '@/activities/types/Activity';
import { Company } from '@/companies/types/Company';
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { Person } from '@/people/types/Person';
import { IconNotes } from '@/ui/display/icon';
@ -26,7 +27,6 @@ import { Command, CommandType } from '../types/Command';
import { CommandGroup } from './CommandGroup';
import { CommandMenuItem } from './CommandMenuItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const StyledDialog = styled.div`
background: ${({ theme }) => theme.background.secondary};

View File

@ -6,6 +6,7 @@ import { flip, offset, useFloating } from '@floating-ui/react';
import { v4 } from 'uuid';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { FieldDoubleText } from '@/object-record/field/types/FieldDoubleText';
import { RelationPicker } from '@/object-record/relation-picker/components/RelationPicker';
import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect';
@ -16,7 +17,6 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledContainer = styled.div`
position: static;

View File

@ -2,6 +2,7 @@ import { ReactNode, useContext } from 'react';
import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import {
FieldContext,
RecordUpdateHook,
@ -24,7 +25,6 @@ import { getLogoUrlFromDomainName } from '~/utils';
import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState';
import { CompanyChip } from './CompanyChip';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledBoardCard = styled.div<{ selected: boolean }>`
background-color: ${({ theme, selected }) =>

View File

@ -4,11 +4,11 @@ import { isNonEmptyArray } from '@sniptt/guards';
import { Company } from '@/companies/types/Company';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { mapPaginatedRecordsToRecords } from '@/object-record/utils/mapPaginatedRecordsToRecords';
import { PeopleCard } from '@/people/components/PeopleCard';
import { AddPersonToCompany } from './AddPersonToCompany';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type CompanyTeamProps = {
company: Pick<Company, 'id'>;

View File

@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useRecordBoardScopedStates } from '@/object-record/record-board/hooks/internal/useRecordBoardScopedStates';
import { availableRecordBoardCardFieldsScopedState } from '@/object-record/record-board/states/availableRecordBoardCardFieldsScopedState';
import { recordBoardCardFieldsScopedState } from '@/object-record/record-board/states/recordBoardCardFieldsScopedState';
@ -14,7 +15,6 @@ import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'
import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
type HooksCompanyBoardEffectProps = {
viewBarId: string;

View File

@ -2,6 +2,7 @@ import { useCallback, useContext, useState } from 'react';
import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { NewButton } from '@/object-record/record-board/components/NewButton';
import { BoardColumnContext } from '@/object-record/record-board/contexts/BoardColumnContext';
import { useCreateOpportunity } from '@/object-record/record-board/hooks/internal/useCreateOpportunity';
@ -11,7 +12,6 @@ import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const NewOpportunityButton = () => {
const [isCreatingCard, setIsCreatingCard] = useState(false);

View File

@ -3,6 +3,7 @@ import { useQuery } from '@apollo/client';
import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { SingleEntitySelectBase } from '@/object-record/relation-picker/components/SingleEntitySelectBase';
import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/useEntitySelectSearch';
import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker';
@ -17,7 +18,6 @@ import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/Dropdow
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type OpportunityPickerProps = {
companyId: string | null;

View File

@ -1,11 +1,11 @@
import { Company } from '@/companies/types/Company';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport';
import { SpreadsheetOptions } from '@/spreadsheet-import/types';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { fieldsForCompany } from '../utils/fieldsForCompany';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type FieldCompanyMapping = (typeof fieldsForCompany)[number]['key'];

View File

@ -9,12 +9,12 @@ import { Favorite } from '@/favorites/types/Favorite';
import { mapFavorites } from '@/favorites/utils/mapFavorites';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { PaginatedRecordTypeResults } from '@/object-record/types/PaginatedRecordTypeResults';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { favoritesState } from '../states/favoritesState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useFavorites = ({
objectNamePlural,

View File

@ -3,6 +3,7 @@ import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { Company } from '@/companies/types/Company';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { useRecordBoardScopedStates } from '@/object-record/record-board/hooks/internal/useRecordBoardScopedStates';
import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter';
@ -11,7 +12,6 @@ import { Opportunity } from '@/pipeline/types/Opportunity';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
import { useFindManyRecords } from './useFindManyRecords';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useObjectRecordBoard = () => {
const objectNameSingular = 'opportunity';

View File

@ -3,6 +3,7 @@ import styled from '@emotion/styled';
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
import { useRecoilValue } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordBoardActionBar } from '@/object-record/record-board/action-bar/components/RecordBoardActionBar';
import { RecordBoardInternalEffect } from '@/object-record/record-board/components/RecordBoardInternalEffect';
@ -22,7 +23,6 @@ import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
import { BoardOptions } from '../types/BoardOptions';
import { RecordBoardColumn } from './RecordBoardColumn';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type RecordBoardProps = {
recordBoardId: string;

View File

@ -1,10 +1,10 @@
import { useRecoilCallback } from 'recoil';
import { v4 } from 'uuid';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { recordBoardCardIdsByColumnIdFamilyState } from '@/object-record/record-board/states/recordBoardCardIdsByColumnIdFamilyState';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useCreateOpportunity = () => {
const { createOneRecord: createOneOpportunity } =

View File

@ -1,12 +1,12 @@
import { useApolloClient } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
import { useRecordBoardScopedStates } from '@/object-record/record-board/hooks/internal/useRecordBoardScopedStates';
import { Opportunity } from '@/pipeline/types/Opportunity';
import { useRemoveRecordBoardCardIdsInternal } from './useRemoveRecordBoardCardIdsInternal';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useDeleteSelectedRecordBoardCardsInternal = () => {
const removeCardIds = useRemoveRecordBoardCardIdsInternal();

View File

@ -1,12 +1,12 @@
import { useRecoilState } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { useRecordBoardScopedStates } from '@/object-record/record-board/hooks/internal/useRecordBoardScopedStates';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns';
import { BoardColumnDefinition } from '../../types/BoardColumnDefinition';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useBoardColumnsInternal = () => {
const { boardColumnsState } = useRecordBoardScopedStates();

View File

@ -6,6 +6,7 @@ import styled from '@emotion/styled';
import { autoUpdate, flip, offset, useFloating } from '@floating-ui/react';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { Person } from '@/people/types/Person';
import { IconDotsVertical, IconLinkOff, IconTrash } from '@/ui/display/icon';
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
@ -14,7 +15,6 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { Avatar } from '@/users/components/Avatar';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type PeopleCardProps = {
person: Pick<Person, 'id' | 'avatarUrl' | 'name' | 'jobTitle'>;

View File

@ -1,5 +1,6 @@
import { v4 } from 'uuid';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
import { Person } from '@/people/types/Person';
import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport';
@ -7,7 +8,6 @@ import { SpreadsheetOptions } from '@/spreadsheet-import/types';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { fieldsForPerson } from '../utils/fieldsForPerson';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export type FieldPersonMapping = (typeof fieldsForPerson)[number]['key'];

View File

@ -1,11 +1,11 @@
import { useRecoilCallback } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { BoardColumnDefinition } from '@/object-record/record-board/types/BoardColumnDefinition';
import { currentPipelineState } from '@/pipeline/states/currentPipelineState';
import { PipelineStep } from '@/pipeline/types/PipelineStep';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const usePipelineSteps = () => {
const { createOneRecord: createOnePipelineStep } =

View File

@ -17,7 +17,9 @@ export const useRelationFieldPreviewValue = ({
: undefined;
const { records: relationObjects } = useFindManyRecords({
objectNameSingular: relationObjectMetadataItem?.nameSingular ?? CoreObjectNameSingular.Company, // TODO fix this hack
objectNameSingular:
relationObjectMetadataItem?.nameSingular ??
CoreObjectNameSingular.Company, // TODO fix this hack
skip: skip || !relationObjectMetadataItem,
});

View File

@ -5,10 +5,10 @@ import { useRecoilState, useRecoilValue } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { TextInput } from '@/ui/input/components/TextInput';
import { logError } from '~/utils/logError';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledComboInputContainer = styled.div`
display: flex;

View File

@ -2,11 +2,11 @@ import { useState } from 'react';
import { useRecoilState } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ImageInput } from '@/ui/input/components/ImageInput';
import { getImageAbsoluteURIOrBase64 } from '@/users/utils/getProfilePictureAbsoluteURI';
import { useUploadProfilePictureMutation } from '~/generated/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const ProfilePictureUploader = () => {
const [uploadPicture, { loading: isUploading }] =

View File

@ -2,9 +2,9 @@ import { useCallback } from 'react';
import { useRecoilState } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useColorScheme = () => {
const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState(

View File

@ -2,13 +2,13 @@ import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useViewBar } from '@/views/hooks/useViewBar';
import { GraphQLView } from '@/views/types/GraphQLView';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const ViewBarEffect = () => {
const {

View File

@ -2,10 +2,10 @@ import { useApolloClient } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ViewField } from '@/views/types/ViewField';
import { getViewScopedStatesFromSnapshot } from '@/views/utils/getViewScopedStatesFromSnapshot';
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useViewFields = (viewScopeId: string) => {
const { updateOneRecordMutation, createOneRecordMutation } =

View File

@ -3,13 +3,13 @@ import { produce } from 'immer';
import { useRecoilCallback } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
import { savedViewFiltersScopedFamilyState } from '@/views/states/savedViewFiltersScopedFamilyState';
import { ViewFilter } from '@/views/types/ViewFilter';
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
import { useViewScopedStates } from './useViewScopedStates';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useViewFilters = (viewScopeId: string) => {
const {

View File

@ -3,13 +3,13 @@ import { produce } from 'immer';
import { useRecoilCallback } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
import { savedViewSortsScopedFamilyState } from '@/views/states/savedViewSortsScopedFamilyState';
import { ViewSort } from '@/views/types/ViewSort';
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
import { useViewScopedStates } from './useViewScopedStates';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useViewSorts = (viewScopeId: string) => {
const {

View File

@ -2,9 +2,9 @@ import { useApolloClient } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { GraphQLView } from '@/views/types/GraphQLView';
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const useViews = (scopeId: string) => {
const {

View File

@ -12,6 +12,7 @@ import { Title } from '@/auth/components/Title';
import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
@ -21,7 +22,6 @@ import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledContentContainer = styled.div`
width: 100%;

View File

@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { CompanyBoard } from '@/companies/board/components/CompanyBoard';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
import { usePipelineSteps } from '@/pipeline/hooks/usePipelineSteps';
@ -9,7 +10,6 @@ import { IconTargetArrow } from '@/ui/display/icon';
import { PageBody } from '@/ui/layout/page/PageBody';
import { PageContainer } from '@/ui/layout/page/PageContainer';
import { PageHeader } from '@/ui/layout/page/PageHeader';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledBoardContainer = styled.div`
display: flex;

View File

@ -3,6 +3,7 @@ import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@ -16,7 +17,6 @@ import { Section } from '@/ui/layout/section/components/Section';
import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink';
import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;

View File

@ -5,6 +5,7 @@ import { useCreateOneRelationMetadataItem } from '@/object-metadata/hooks/useCre
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { PaginatedRecordTypeResults } from '@/object-record/types/PaginatedRecordTypeResults';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
@ -22,7 +23,6 @@ import { View } from '@/views/types/View';
import { ViewType } from '@/views/types/ViewType';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const SettingsObjectNewFieldStep2 = () => {
const navigate = useNavigate();

View File

@ -5,6 +5,7 @@ import { DateTime } from 'luxon';
import { useRecoilState } from 'recoil';
import { useOptimisticEvict } from '@/apollo/optimistic-effect/hooks/useOptimisticEvict';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
@ -24,7 +25,6 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledInfo = styled.span`
color: ${({ theme }) => theme.font.color.light};

View File

@ -2,6 +2,7 @@ import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { objectSettingsWidth } from '@/settings/data-model/constants/objectSettings';
import { SettingsApiKeysFieldItemTableRow } from '@/settings/developers/components/SettingsApiKeysFieldItemTableRow';
@ -15,7 +16,6 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Table } from '@/ui/layout/table/components/Table';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
const StyledContainer = styled.div`
height: fit-content;

View File

@ -2,6 +2,7 @@ import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { DateTime } from 'luxon';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
@ -17,7 +18,6 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const SettingsDevelopersApiKeysNew = () => {
const [generateOneApiKeyToken] = useGenerateApiKeyTokenMutation();

View File

@ -12,6 +12,8 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@jsdevtools/rehype-toc": "^3.0.2",
"@nivo/calendar": "^0.84.0",
"@nivo/core": "^0.84.0",
"@stoplight/elements": "^7.16.2",
"@tabler/icons-react": "^2.44.0",
"better-sqlite3": "^9.2.2",

View File

@ -1,6 +1,7 @@
'use client'
import styled from '@emotion/styled';
import Link from 'next/link';
export interface User {
login: string;
@ -50,10 +51,12 @@ const AvatarGrid = ({ users }: { users: User[] }) => {
return (
<AvatarGridContainer>
{users.map(user => (
<AvatarItem key={user.login}>
<img src={user.avatarUrl} alt={user.login} />
<span className="username">{user.login}</span>
</AvatarItem>
<Link href={`/developers/contributors/${user.login}`} key={`l_${user.login}`}>
<AvatarItem key={user.login}>
<img src={user.avatarUrl} alt={user.login} />
<span className="username">{user.login}</span>
</AvatarItem>
</Link>
))}
</AvatarGridContainer>
);

View File

@ -33,6 +33,7 @@ const Nav = styled.nav`
const LinkList = styled.div`
display: flex;
flex-direction: column;
gap: 16px;
`;
const ListItem = styled.a`
@ -164,6 +165,13 @@ const HamburgerLine2 = styled.div`
const NavOpen = styled.div`
flex-direction: column;
align-items: center;
position: fixed;
inset: 0px;
top: 63px;
background-color: #fff;
gap: 33px;
padding-top: 32px;
z-index: 100;
`;
const MobileMenu = styled.div`

View File

@ -0,0 +1,9 @@
'use client'
import { ResponsiveTimeRange } from '@nivo/calendar'
export const ActivityLog = ({ data }: { data: { value: number, day: string }[] }) => {
return <ResponsiveTimeRange
data={data}
/>;
}

View File

@ -0,0 +1,100 @@
import Image from 'next/image';
import Database from 'better-sqlite3';
import AvatarGrid from '@/app/components/AvatarGrid';
import { ResponsiveTimeRange } from '@nivo/calendar'
import { ActivityLog } from './components/ActivityLog';
import { Metadata } from 'next';
interface Contributor {
login: string;
avatarUrl: string;
pullRequestCount: number;
}
export function generateMetadata({ params }: { params: { slug: string } }): Metadata {
return {
title: params.slug + ' | Contributors',
};
}
export default async function (
{ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
const contributor = db.prepare(`
SELECT
u.login,
u.avatarUrl,
(SELECT COUNT(*) FROM pullRequests WHERE authorId = u.id) AS pullRequestCount,
(SELECT COUNT(*) FROM issues WHERE authorId = u.id) AS issuesCount
FROM
users u
WHERE
u.login = :user_id
`).get({'user_id' : params.slug}) as Contributor;
const pullRequestActivity = db.prepare(`
SELECT
COUNT(*) as value,
DATE(createdAt) as day
FROM
pullRequests
WHERE
authorId = (SELECT id FROM users WHERE login = :user_id)
GROUP BY
DATE(createdAt)
ORDER BY
DATE(createdAt)
`).all({'user_id': params.slug}) as { value: number, day: string }[];
const pullRequestList = db.prepare(`
SELECT
id,
title,
body,
url,
createdAt,
updatedAt,
closedAt,
mergedAt
FROM
pullRequests
WHERE
authorId = (SELECT id FROM users WHERE login = :user_id)
ORDER BY
DATE(createdAt) DESC
`).all({'user_id': params.slug}) as { title: string, createdAt: string, url: string }[];
db.close();
return (
<div style={{maxWidth: '900px', display: 'flex', padding: '40px', gap: '24px'}}>
<div style={{ flexDirection: 'column', width: '240px'}}>
<Image src={contributor.avatarUrl} alt={contributor.login} width={240} height={240} />
<h1>{contributor.login}</h1>
</div>
<div style={{flexDirection: 'column'}}>
<div style={{width: '450px', height: '200px'}}>
<ActivityLog
data={pullRequestActivity}
/>
</div>
<div style={{width: '450px'}}>
{pullRequestList.map(pr => (
<div>
<a href={pr.url}>{pr.title}</a>
</div>
))}
</div>
</div>
</div>
);
};

View File

@ -7,7 +7,7 @@ export async function GET(
{ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
if(params.slug !== 'users' && params.slug !== 'labels' && params.slug !== 'pullRequests') {
if(params.slug !== 'users' && params.slug !== 'labels' && params.slug !== 'pullRequests' && params.slug !== 'issues') {
return Response.json({ error: 'Invalid table name' }, { status: 400 });
}

View File

@ -21,6 +21,7 @@ interface PullRequestNode {
id: string;
title: string;
body: string;
url: string;
createdAt: string;
updatedAt: string;
closedAt: string;
@ -35,6 +36,7 @@ interface IssueNode {
id: string;
title: string;
body: string;
url: string;
createdAt: string;
updatedAt: string;
closedAt: string;
@ -90,6 +92,7 @@ async function fetchData(cursor: string | null = null, isIssues: boolean = false
id
title
body
url
createdAt
updatedAt
closedAt
@ -119,6 +122,7 @@ async function fetchData(cursor: string | null = null, isIssues: boolean = false
id
title
body
url
createdAt
updatedAt
closedAt
@ -178,6 +182,7 @@ const initDb = () => {
id TEXT PRIMARY KEY,
title TEXT,
body TEXT,
url TEXT,
createdAt TEXT,
updatedAt TEXT,
closedAt TEXT,
@ -192,7 +197,8 @@ const initDb = () => {
id TEXT PRIMARY KEY,
title TEXT,
body TEXT,
createdAt TEXT,
url TEXT,
createdAt TEXT,
updatedAt TEXT,
closedAt TEXT,
authorId TEXT,
@ -249,10 +255,10 @@ export async function GET() {
const assignableUsers = await fetchAssignableUsers();
const prs = await fetchData(lastPRCursor) as Array<PullRequestNode>;
const issues = await fetchData(lastIssueCursor) as Array<IssueNode>;
const issues = await fetchData(lastIssueCursor, true) as Array<IssueNode>;
const insertPR = db.prepare('INSERT INTO pullRequests (id, title, body, createdAt, updatedAt, closedAt, mergedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertIssue = db.prepare('INSERT INTO issues (id, title, body, createdAt, updatedAt, closedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertPR = db.prepare('INSERT INTO pullRequests (id, title, body, url, createdAt, updatedAt, closedAt, mergedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertIssue = db.prepare('INSERT INTO issues (id, title, body, url, createdAt, updatedAt, closedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertUser = db.prepare('INSERT INTO users (id, login, avatarUrl, url, isEmployee) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertLabel = db.prepare('INSERT INTO labels (id, name, color, description) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertPullRequestLabel = db.prepare('INSERT INTO pullRequestLabels (pullRequestId, labelId) VALUES (?, ?)');
@ -262,7 +268,7 @@ export async function GET() {
console.log(pr);
if(pr.author == null) { continue; }
insertUser.run(pr.author.resourcePath, pr.author.login, pr.author.avatarUrl, pr.author.url, assignableUsers.has(pr.author.login) ? 1 : 0);
insertPR.run(pr.id, pr.title, pr.body, pr.createdAt, pr.updatedAt, pr.closedAt, pr.mergedAt, pr.author.resourcePath);
insertPR.run(pr.id, pr.title, pr.body, pr.url, pr.createdAt, pr.updatedAt, pr.closedAt, pr.mergedAt, pr.author.resourcePath);
for (const label of pr.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);
@ -274,7 +280,7 @@ export async function GET() {
if(issue.author == null) { continue; }
insertUser.run(issue.author.resourcePath, issue.author.login, issue.author.avatarUrl, issue.author.url, assignableUsers.has(issue.author.login) ? 1 : 0);
insertIssue.run(issue.id, issue.title, issue.body, issue.createdAt, issue.updatedAt, issue.closedAt, issue.author.resourcePath);
insertIssue.run(issue.id, issue.title, issue.body, issue.url, issue.createdAt, issue.updatedAt, issue.closedAt, issue.author.resourcePath);
for (const label of issue.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);

View File

@ -26,12 +26,12 @@ const Contributors = async () => {
ORDER BY
pullRequestCount DESC;
`).all() as Contributor[];
db.close();
return (
<div>
<h1>Top Contributors</h1>
<AvatarGrid users={contributors} />
</div>
);

View File

@ -7,8 +7,8 @@ import { HeaderMobile } from '@/app/components/HeaderMobile';
import './layout.css';
export const metadata: Metadata = {
title: 'Twenty.dev',
description: 'Twenty for Developer',
title: 'Twenty.com',
description: 'Open Source CRM',
icons: '/images/core/logo.svg',
};

File diff suppressed because it is too large Load Diff

377
yarn.lock
View File

@ -7622,6 +7622,109 @@ __metadata:
languageName: node
linkType: hard
"@nivo/calendar@npm:^0.84.0":
version: 0.84.0
resolution: "@nivo/calendar@npm:0.84.0"
dependencies:
"@nivo/core": "npm:0.84.0"
"@nivo/legends": "npm:0.84.0"
"@nivo/tooltip": "npm:0.84.0"
"@types/d3-scale": "npm:^3.2.3"
"@types/d3-time": "npm:^1.0.10"
"@types/d3-time-format": "npm:^3.0.0"
d3-scale: "npm:^3.2.3"
d3-time: "npm:^1.0.10"
d3-time-format: "npm:^3.0.0"
lodash: "npm:^4.17.21"
peerDependencies:
react: ">= 16.14.0 < 19.0.0"
checksum: 7c83753a6f6b830df6823eaefcaf22883aca0b2ba630085075a39ef9cdd35313ca153416d88037ebf4cc31a356bb356f26e581dda770c38d7402c97dad182572
languageName: node
linkType: hard
"@nivo/colors@npm:0.84.0":
version: 0.84.0
resolution: "@nivo/colors@npm:0.84.0"
dependencies:
"@nivo/core": "npm:0.84.0"
"@types/d3-color": "npm:^2.0.0"
"@types/d3-scale": "npm:^3.2.3"
"@types/d3-scale-chromatic": "npm:^2.0.0"
"@types/prop-types": "npm:^15.7.2"
d3-color: "npm:^3.1.0"
d3-scale: "npm:^3.2.3"
d3-scale-chromatic: "npm:^2.0.0"
lodash: "npm:^4.17.21"
prop-types: "npm:^15.7.2"
peerDependencies:
react: ">= 16.14.0 < 19.0.0"
checksum: 036d9128bd451711c66bd377d80470fa9aa4a763fc2e89ac379fbde4661b3899096d1a8926e64a0edf56fa403d75e68eaead02bd5d4649883bb5c375796a63cc
languageName: node
linkType: hard
"@nivo/core@npm:0.84.0, @nivo/core@npm:^0.84.0":
version: 0.84.0
resolution: "@nivo/core@npm:0.84.0"
dependencies:
"@nivo/recompose": "npm:0.84.0"
"@nivo/tooltip": "npm:0.84.0"
"@react-spring/web": "npm:9.4.5 || ^9.7.2"
"@types/d3-shape": "npm:^2.0.0"
d3-color: "npm:^3.1.0"
d3-format: "npm:^1.4.4"
d3-interpolate: "npm:^3.0.1"
d3-scale: "npm:^3.2.3"
d3-scale-chromatic: "npm:^3.0.0"
d3-shape: "npm:^1.3.5"
d3-time-format: "npm:^3.0.0"
lodash: "npm:^4.17.21"
peerDependencies:
prop-types: ">= 15.5.10 < 16.0.0"
react: ">= 16.14.0 < 19.0.0"
checksum: c92cca26ca7b33ae29c04a4da429843bc0a9c7b7a49be1b8d98b01af74384719a5f7e35d31e42a37f2191e0359d8d44e8e911acedae5371a02c4f7abdfb40fa3
languageName: node
linkType: hard
"@nivo/legends@npm:0.84.0":
version: 0.84.0
resolution: "@nivo/legends@npm:0.84.0"
dependencies:
"@nivo/colors": "npm:0.84.0"
"@nivo/core": "npm:0.84.0"
"@types/d3-scale": "npm:^3.2.3"
"@types/prop-types": "npm:^15.7.2"
d3-scale: "npm:^3.2.3"
prop-types: "npm:^15.7.2"
peerDependencies:
react: ">= 16.14.0 < 19.0.0"
checksum: 25f64a068910a411b5073a30e74c5da0eb8e91d00d39619d62472726686349536bca95de8eb7e3c7e4a29872f652bdcd272f68f315ec54248c1cfdb15e3c37b6
languageName: node
linkType: hard
"@nivo/recompose@npm:0.84.0":
version: 0.84.0
resolution: "@nivo/recompose@npm:0.84.0"
dependencies:
"@types/prop-types": "npm:^15.7.2"
"@types/react-lifecycles-compat": "npm:^3.0.1"
prop-types: "npm:^15.7.2"
react-lifecycles-compat: "npm:^3.0.4"
peerDependencies:
react: ">= 16.14.0 < 19.0.0"
checksum: 5a182544d445bf277cabb82e4139681231ab9659275e35e8e15f79b31ae96ebb223b19b8326c101c419bc82c26a4f26eb9980ff21937d84f971ce5833fe17d30
languageName: node
linkType: hard
"@nivo/tooltip@npm:0.84.0":
version: 0.84.0
resolution: "@nivo/tooltip@npm:0.84.0"
dependencies:
"@nivo/core": "npm:0.84.0"
"@react-spring/web": "npm:9.4.5 || ^9.7.2"
checksum: c9b52157951359c573b9bbe8e976d73f217694d89f2df470272a22d89b428fcab8d4e2c1e030104de5c2cf4fc06c0895ba7f4e56d93be2f42c25a836e1503038
languageName: node
linkType: hard
"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
@ -10108,6 +10211,64 @@ __metadata:
languageName: node
linkType: hard
"@react-spring/animated@npm:~9.7.3":
version: 9.7.3
resolution: "@react-spring/animated@npm:9.7.3"
dependencies:
"@react-spring/shared": "npm:~9.7.3"
"@react-spring/types": "npm:~9.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: 5151da4fa7da010bb2edbee05871aa7a4aea8763fe617389d17605810aa0dd817374205e5fb3930b650f4a7f25fcdf23205fdfb7365686ff75888bdfd0b39839
languageName: node
linkType: hard
"@react-spring/core@npm:~9.7.3":
version: 9.7.3
resolution: "@react-spring/core@npm:9.7.3"
dependencies:
"@react-spring/animated": "npm:~9.7.3"
"@react-spring/shared": "npm:~9.7.3"
"@react-spring/types": "npm:~9.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: e28c05de8435bf2eaf8481f8acdf093909d4be9881a9a854c51dfac7c2d5562088d0fb2ce04e2f07e1b3bf621d8da3ab57bf6fedb4fdc954e3aa263bc1e393af
languageName: node
linkType: hard
"@react-spring/shared@npm:~9.7.3":
version: 9.7.3
resolution: "@react-spring/shared@npm:9.7.3"
dependencies:
"@react-spring/types": "npm:~9.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: afb03ed28ccf62efa4012e531c3659999bb364d1e0eb0fb729b962f9bd21a0b772a2d98e862062c9c32c06edf72327afcc45984d9eb22fdd961706b6ddf6950d
languageName: node
linkType: hard
"@react-spring/types@npm:~9.7.3":
version: 9.7.3
resolution: "@react-spring/types@npm:9.7.3"
checksum: d645044f3cc9ceb7c4f6c4d061aaf6660018568a1553d05638f56b3328c5f91597ee4118334abe22fc8f07f5ee02f054340170c1d52e11b3faea22888b5170d4
languageName: node
linkType: hard
"@react-spring/web@npm:9.4.5 || ^9.7.2":
version: 9.7.3
resolution: "@react-spring/web@npm:9.7.3"
dependencies:
"@react-spring/animated": "npm:~9.7.3"
"@react-spring/core": "npm:~9.7.3"
"@react-spring/shared": "npm:~9.7.3"
"@react-spring/types": "npm:~9.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: a5b4847a2921a29a3e8ce569f4951abeb268b6e8eb230f8c49d98709216b2b3a23ba1e58628c51c9eaa0bd20d83f9d7b8f8f03df98215e933de4c66c39e17fe1
languageName: node
linkType: hard
"@react-types/button@npm:3.4.1":
version: 3.4.1
resolution: "@react-types/button@npm:3.4.1"
@ -13995,6 +14156,66 @@ __metadata:
languageName: node
linkType: hard
"@types/d3-color@npm:^2.0.0":
version: 2.0.6
resolution: "@types/d3-color@npm:2.0.6"
checksum: 3d4b064d304fce21e9dccea3b8e11d11b7f1393df9bf577ea8b26fe16e0ea4b4ee4710c4fc4147c95c2db96512a23f80345dc22ebbb8d9c6dc473c4b709af47d
languageName: node
linkType: hard
"@types/d3-path@npm:^2":
version: 2.0.4
resolution: "@types/d3-path@npm:2.0.4"
checksum: 82214a9644cfffe0c1f9a7aab00e3912aaba89115c60d94ecf716d282eac71671761962a9e911a8ebc457777e3db42f80c355b61010e5e27218f6aed32128d39
languageName: node
linkType: hard
"@types/d3-scale-chromatic@npm:^2.0.0":
version: 2.0.4
resolution: "@types/d3-scale-chromatic@npm:2.0.4"
checksum: d545ea57b4c2fb539d60fce090bc2d265df48047702b8762c7decca1557edf9f761722a5e47d4a65bbf9c7271421a4f6088dde5ee700f94ba8f798c8b0ca3af6
languageName: node
linkType: hard
"@types/d3-scale@npm:^3.2.3":
version: 3.3.5
resolution: "@types/d3-scale@npm:3.3.5"
dependencies:
"@types/d3-time": "npm:^2"
checksum: 2689ab13092e3fded22cdd1b888afd91aa60190be40c8eddc12b2d42de59b00917778340f90317c68c5ffc3a1bee68f5ca155434cd466bc7804f400f3f9e7529
languageName: node
linkType: hard
"@types/d3-shape@npm:^2.0.0":
version: 2.1.7
resolution: "@types/d3-shape@npm:2.1.7"
dependencies:
"@types/d3-path": "npm:^2"
checksum: 2433f073b20a1f0180406a83e070a8d862101e637c1f6be8fbe814065d6627848b84b2bd33251752f5b469cd8e02217d21c43a8454ea1b56d7a0f493fa1a75a0
languageName: node
linkType: hard
"@types/d3-time-format@npm:^3.0.0":
version: 3.0.4
resolution: "@types/d3-time-format@npm:3.0.4"
checksum: 3c0d22ff0e30610036d6f75f791fe8d957e750511e930bb4ea466bb43e1505497ffac8a77a0e62b3f0f5ee3c5515202fecfc7d3522ff78d2487af19d398d2184
languageName: node
linkType: hard
"@types/d3-time@npm:^1.0.10":
version: 1.1.4
resolution: "@types/d3-time@npm:1.1.4"
checksum: d1dafa4605c10739de216bdf3dfe9c3953e583e849dc5586216525897c96bbbae8972c50e9c11a4c54e700c089914cf7a9764e9806d316a84838ecf9e5c52722
languageName: node
linkType: hard
"@types/d3-time@npm:^2":
version: 2.1.4
resolution: "@types/d3-time@npm:2.1.4"
checksum: b597bfa51a163d4231e953d6903b06fd6341d0f11a28222a79fafaddb46155d7f458a67c814de53df84926a47dd535897228a475679d228576b0cda87351e534
languageName: node
linkType: hard
"@types/debug@npm:^4.0.0":
version: 4.1.12
resolution: "@types/debug@npm:4.1.12"
@ -14845,7 +15066,7 @@ __metadata:
languageName: node
linkType: hard
"@types/prop-types@npm:*":
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.2":
version: 15.7.11
resolution: "@types/prop-types@npm:15.7.11"
checksum: e53423cf9d510515ef8b47ff42f4f1b65a7b7b37c8704e2dbfcb9a60defe0c0e1f3cb1acfdeb466bad44ca938d7c79bffdd51b48ffb659df2432169d0b27a132
@ -14905,6 +15126,15 @@ __metadata:
languageName: node
linkType: hard
"@types/react-lifecycles-compat@npm:^3.0.1":
version: 3.0.4
resolution: "@types/react-lifecycles-compat@npm:3.0.4"
dependencies:
"@types/react": "npm:*"
checksum: 3c33fcd7d52d44031b21cf8a6ae9c0f208fe3b972ee4f03fcbe4509d2c50da474bfdd3330f5a09046b7fd63a1f7f23b194bc8d774823c1981cc13929744b90d2
languageName: node
linkType: hard
"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.7":
version: 5.0.11
resolution: "@types/react-router-config@npm:5.0.11"
@ -21241,6 +21471,135 @@ __metadata:
languageName: node
linkType: hard
"d3-array@npm:2, d3-array@npm:^2.3.0":
version: 2.12.1
resolution: "d3-array@npm:2.12.1"
dependencies:
internmap: "npm:^1.0.0"
checksum: 7eca10427a9f113a4ca6a0f7301127cab26043fd5e362631ef5a0edd1c4b2dd70c56ed317566700c31e4a6d88b55f3951aaba192291817f243b730cb2352882e
languageName: node
linkType: hard
"d3-color@npm:1 - 2":
version: 2.0.0
resolution: "d3-color@npm:2.0.0"
checksum: 5aa58dfb78e3db764373a904eabb643dc024ff6071128a41e86faafa100e0e17a796e06ac3f2662e9937242bb75b8286788629773d76936f11c17bd5fe5e15cd
languageName: node
linkType: hard
"d3-color@npm:1 - 3, d3-color@npm:^3.1.0":
version: 3.1.0
resolution: "d3-color@npm:3.1.0"
checksum: a4e20e1115fa696fce041fbe13fbc80dc4c19150fa72027a7c128ade980bc0eeeba4bcf28c9e21f0bce0e0dbfe7ca5869ef67746541dcfda053e4802ad19783c
languageName: node
linkType: hard
"d3-format@npm:1 - 2":
version: 2.0.0
resolution: "d3-format@npm:2.0.0"
checksum: c869af459e20767dc3d9cbb2946ba79cc266ae4fb35d11c50c63fc89ea4ed168c702c7e3db94d503b3618de9609bf3bf2d855ef53e21109ddd7eb9c8f3fcf8a1
languageName: node
linkType: hard
"d3-format@npm:^1.4.4":
version: 1.4.5
resolution: "d3-format@npm:1.4.5"
checksum: 40800a2fb2182d2d711cea3acc2b8b2b3afdb6f644c51de77feb9b08a6150b14c753933d2fd4ad2f6f45130757b738673372c45b4b820466c560f3b1ec0b3ce8
languageName: node
linkType: hard
"d3-interpolate@npm:1 - 2, d3-interpolate@npm:1.2.0 - 2":
version: 2.0.1
resolution: "d3-interpolate@npm:2.0.1"
dependencies:
d3-color: "npm:1 - 2"
checksum: 2a5725b0c9c7fef3e8878cf75ad67be851b1472de3dda1f694c441786a1a32e198ddfaa6880d6b280401c1af5b844b61ccdd63d85d1607c1e6bb3a3f0bf532ea
languageName: node
linkType: hard
"d3-interpolate@npm:1 - 3, d3-interpolate@npm:^3.0.1":
version: 3.0.1
resolution: "d3-interpolate@npm:3.0.1"
dependencies:
d3-color: "npm:1 - 3"
checksum: 19f4b4daa8d733906671afff7767c19488f51a43d251f8b7f484d5d3cfc36c663f0a66c38fe91eee30f40327443d799be17169f55a293a3ba949e84e57a33e6a
languageName: node
linkType: hard
"d3-path@npm:1":
version: 1.0.9
resolution: "d3-path@npm:1.0.9"
checksum: e35e84df5abc18091f585725b8235e1fa97efc287571585427d3a3597301e6c506dea56b11dfb3c06ca5858b3eb7f02c1bf4f6a716aa9eade01c41b92d497eb5
languageName: node
linkType: hard
"d3-scale-chromatic@npm:^2.0.0":
version: 2.0.0
resolution: "d3-scale-chromatic@npm:2.0.0"
dependencies:
d3-color: "npm:1 - 2"
d3-interpolate: "npm:1 - 2"
checksum: 93cafe497b00046b1d4e237a8bb8981fbb35ba03070f420bd913872f6e9d2c9628ed8bb8c84c6a6ffe16029359fa74b646c5c5129732ef4186ab059a77da3021
languageName: node
linkType: hard
"d3-scale-chromatic@npm:^3.0.0":
version: 3.0.0
resolution: "d3-scale-chromatic@npm:3.0.0"
dependencies:
d3-color: "npm:1 - 3"
d3-interpolate: "npm:1 - 3"
checksum: 920a80f2e31b5686798c116e99d1671c32f55fb60fa920b742aa4ac5175b878c615adb4e55a246d65367e6e1061fdbcc55807be731fb5b18ae628d1df62bfac1
languageName: node
linkType: hard
"d3-scale@npm:^3.2.3":
version: 3.3.0
resolution: "d3-scale@npm:3.3.0"
dependencies:
d3-array: "npm:^2.3.0"
d3-format: "npm:1 - 2"
d3-interpolate: "npm:1.2.0 - 2"
d3-time: "npm:^2.1.1"
d3-time-format: "npm:2 - 3"
checksum: cb63c271ec9c5b632c245c63e0d0716b32adcc468247972c552f5be62fb34a17f71e4ac29fd8976704369f4b958bc6789c61a49427efe2160ae979d7843569dc
languageName: node
linkType: hard
"d3-shape@npm:^1.3.5":
version: 1.3.7
resolution: "d3-shape@npm:1.3.7"
dependencies:
d3-path: "npm:1"
checksum: 548057ce59959815decb449f15632b08e2a1bdce208f9a37b5f98ec7629dda986c2356bc7582308405ce68aedae7d47b324df41507404df42afaf352907577ae
languageName: node
linkType: hard
"d3-time-format@npm:2 - 3, d3-time-format@npm:^3.0.0":
version: 3.0.0
resolution: "d3-time-format@npm:3.0.0"
dependencies:
d3-time: "npm:1 - 2"
checksum: 0abe3379f07d1c12ce8930cdddad1223c99cd3e4eac05cf409b5a7953e9ebed56a95a64b0977f63958cfb6101fa4a2a85533a5eae40df84f22c0117dbf5e8982
languageName: node
linkType: hard
"d3-time@npm:1 - 2, d3-time@npm:^2.1.1":
version: 2.1.1
resolution: "d3-time@npm:2.1.1"
dependencies:
d3-array: "npm:2"
checksum: 4a01770a857bc37d2bafb8f00250e0e6a1fcc8051aea93e5eed168d8ee93e92da508a75ab5e42fc5472aa37e2a83aac68afaf3f12d9167c184ce781faadf5682
languageName: node
linkType: hard
"d3-time@npm:^1.0.10":
version: 1.1.0
resolution: "d3-time@npm:1.1.0"
checksum: 69ab137adff5b22d0fa148ea514a207bd9cd7d2c042ccf34a268f2ef73720b404f0be6e7b56c95650c53caf52080b5254e2a27f0a676f41d1dd22ef8872c8335
languageName: node
linkType: hard
"d@npm:1, d@npm:^1.0.1":
version: 1.0.1
resolution: "d@npm:1.0.1"
@ -27505,6 +27864,13 @@ __metadata:
languageName: node
linkType: hard
"internmap@npm:^1.0.0":
version: 1.0.1
resolution: "internmap@npm:1.0.1"
checksum: 60942be815ca19da643b6d4f23bd0bf4e8c97abbd080fb963fe67583b60bdfb3530448ad4486bae40810e92317bded9995cc31411218acc750d72cd4e8646eee
languageName: node
linkType: hard
"interpret@npm:^1.0.0":
version: 1.4.0
resolution: "interpret@npm:1.4.0"
@ -37937,6 +38303,13 @@ __metadata:
languageName: node
linkType: hard
"react-lifecycles-compat@npm:^3.0.4":
version: 3.0.4
resolution: "react-lifecycles-compat@npm:3.0.4"
checksum: 1d0df3c85af79df720524780f00c064d53a9dd1899d785eddb7264b378026979acbddb58a4b7e06e7d0d12aa1494fd5754562ee55d32907b15601068dae82c27
languageName: node
linkType: hard
"react-loadable-ssr-addon-v5-slorber@npm:^1.0.1":
version: 1.0.1
resolution: "react-loadable-ssr-addon-v5-slorber@npm:1.0.1"
@ -42906,6 +43279,8 @@ __metadata:
"@emotion/react": "npm:^11.11.1"
"@emotion/styled": "npm:^11.11.0"
"@jsdevtools/rehype-toc": "npm:^3.0.2"
"@nivo/calendar": "npm:^0.84.0"
"@nivo/core": "npm:^0.84.0"
"@stoplight/elements": "npm:^7.16.2"
"@tabler/icons-react": "npm:^2.44.0"
"@types/better-sqlite3": "npm:^7.6.8"