Update yarn.lock

This commit is contained in:
Jackson Harper 2023-03-09 10:44:42 +08:00
commit 58156b72ff
38 changed files with 401 additions and 196 deletions

View file

@ -19,12 +19,14 @@ We built Omnivore because we love reading and we want it to be more social. Join
- PDF support
- [Web app](https://omnivore.app/) written in Node.js and TypeScript
- [Native iOS app](https://omnivore.app/install/ios)
- [Android app](https://omnivore.app/install/android) ([source](https://github.com/omnivore-app/omnivore/tree/main/android/Omnivore))
- Progressive web app for Android users
- Browser extensions for [Chrome](https://omnivore.app/install/chrome), [Safari](https://omnivore.app/install/safari), [Firefox](https://omnivore.app/install/firefox), and [Edge](https://omnivore.app/install/edge)
- Labels (aka tagging)
- Offline support
- Text to speech (iOS only)
- [Logseq](https://logseq.com/) support via our [Logseq Plugin](https://github.com/omnivore-app/logseq-omnivore)
- [Obsidian](https://obsidian.md/) support via our [Obsidian Plugin](https://github.com/omnivore-app/obsidian-omnivore)
Every single part is fully open source! Fork it, extend it, or deploy it to your own server.

View file

@ -0,0 +1,172 @@
# Commencer avec Omnivore
Omnivore est une **application de lecture ultérieure** qui vous permet de sauvegarder et d'organiser tout ce que vous lisez en ligne.
Ce guide vous montrera comment utiliser les fonctions de base et les fonctionnalités avancées d'Omnivore, divisées en quatre activités principales:
* Sauvegarde
* Lecture
* Organisation
* Intégrations
La **Library** est le centre de votre expérience Omnivore, où vous pouvez accéder rapidement à tous les liens que vous avez enregistrés. Les liens enregistrés restent dans votre bibliothèque à jamais, à moins que vous ne les supprimiez.
## Sauvegarde
Il existe cinq façons de sauvegarder des liens vers des pages ou des articles que vous souhaitez lire plus tard:
* Sauvegarde depuis votre bibliothèque Omnivore
* Sauvegarde depuis un navigateur
* Sauvegarde depuis un téléphone ou une tablette (iOS ou Android)
* Abonnements à des newsletters via e-mail
* Sauvegarde de PDF à partir d'un Mac
### Sauvegarde depuis votre bibliothèque Omnivore
1. Dans le coin supérieur droit de votre bibliothèque, appuyez sur le bouton **Add Link**.
2. Entrez l'URL que vous souhaitez enregistrer et appuyez sur **Add Link**.
3. Le lien apparaîtra dans votre bibliothèque la prochaine fois que vous la rafraîchissez.
### Sauvegarde depuis un navigateur
1. Téléchargez et installez l'extension Omnivore pour votre navigateur :
* [Chrome ](https://omnivore.app/install/chrome)
* [Edge](https://omnivore.app/install/edge)
* [Firefox](https://omnivore.app/install/firefox)
* [Safari](https://omnivore.app/install/safari)
2. Accédez à la page que vous souhaitez enregistrer et appuyez sur le bouton Omnivore dans la barre d'outils de votre navigateur ou dans le menu Extensions.
3. Alternativement, vous pouvez cliquer avec le bouton droit (commande + clic sur Mac) sur n'importe quel lien hypertexte et sélectionner **Enregistrer dans Omnivore** dans le menu.
4. Le lien apparaîtra dans votre bibliothèque la prochaine fois que vous la rafraîchissez.
### Sauvegarde depuis un téléphone ou une tablette
La meilleure façon d'enregistrer des liens à partir de votre appareil mobile est via l'application Omnivore. Vous pouvez télécharger l'application ici :
* [iOS (iPhone ou iPad)](https://omnivore.app/install/ios)
* Android
Une fois que l'application mobile est installée :
1. Dans votre navigateur, accédez à la page que vous souhaitez enregistrer et appuyez sur le bouton **Share**.
2. Appuyez sur l'icône **Omnivore** dans le menu Partager.
3. Le lien apparaîtra dans votre bibliothèque la prochaine fois que vous la rafraîchirez.
### Abonnements à la newsletter via e-mail
1. Sur le site web ou l'application Omnivore, appuyez sur votre photo, initiale ou avatar dans le coin supérieur droit pour accéder au menu de profil. Sélectionnez **Emails** dans le menu.
2. Appuyez sur **Create a New Email Address** pour ajouter une nouvelle adresse e-mail (par exemple : username-123_abc@inbox.omnivore.app) à la liste.
3. Cliquez sur l'icône Copier à côté de l'adresse e-mail.
4. Accédez à la page d'inscription pour la newsletter à laquelle vous souhaitez vous abonner.
5. Collez l'adresse e-mail Omnivore dans le formulaire d'inscription.
6. Les nouvelles newsletters seront automatiquement livrées à votre boîte de réception Omnivore.
### Enregistrement de PDF à partir d'un Mac
1. Installez [l'application Mac](https://omnivore.app/install/mac).
2. Sur votre Mac, localisez le PDF que vous souhaitez enregistrer et faites un clic droit ou ctrl + clic sur le nom de fichier.
3. Sélectionnez **Share** dans le menu et choisissez **Omnivore**.
4. Le lien apparaîtra dans votre bibliothèque la prochaine fois que vous la rafraîchirez.
## Lecture
Cliquez sur n'importe quel lien enregistré dans votre bibliothèque pour accéder à la vue du lecteur.
Omnivore formatte les pages pour une lecture facile et une surbrillance, en enlevant les publicités et les encombrements pour une lecture exempte de distractions. La vue axée sur le texte rend également les articles plus petits et plus rapides à charger.
Pendant la lecture, vous pouvez :
* <span style="text-decoration:underline;">Modifier la mise en forme</span>
* <span style="text-decoration:underline;">Surligner le texte</span>
* <span style="text-decoration:underline;">Ajouter des notes</span>
* <span style="text-decoration:underline;">Voir toutes les surlignages et notes enregistrés</span>
* <span style="text-decoration:underline;">Suivre la progression de la lecture</span>
### Modification de la mise en forme
1. **_Thème:_** Appuyez sur votre photo, initiale ou avatar dans le coin supérieur droit pour accéder au menu de profil. Sélectionnez la miniature blanche ou noire pour choisir le thème clair ou sombre.
2. **_Mise en forme du texte:_** Appuyez sur l'icône Aa pour ajuster la taille du texte, la police, les marges et les espacements entre les lignes.
### Mettre en surbrillance du texte
1. Sélectionnez le texte que vous souhaitez mettre en surbrillance.
2. Appuyez sur le bouton **Highlight**.
3. Le texte apparaîtra en surbrillance la prochaine fois que vous consulterez l'article.
### Ajouter des notes
1. Mettre en surbrillance une section de texte où vous souhaitez ajouter une note.
2. Appuyez sur le bouton **Note**, tapez votre note et appuyez sur **Save**.
3. L'icône de note apparaîtra la prochaine fois que vous consulterez cet article.
### Afficher toutes les surbrillances et les notes enregistrées
1. Appuyez sur l'icône Highlight/Note pour afficher une liste de toutes les sections de texte mises en surbrillance et les notes que vous avez ajoutées à cette page.
2. Pour supprimer une note ou une surbrillance, sélectionnez-la dans la liste et appuyez sur l'icône Corbeille.
### Suivre l'avancement de la lecture
Omnivore garde automatiquement une trace de votre avancement de lecture sur vos différents appareils, de sorte que vous puissiez facilement reprendre là où vous vous êtes arrêté. Une barre de progression apparaîtra en haut de chaque lien de votre bibliothèque après que vous avez commencé à lire.
## Organisation
Par défaut, la boîte de réception de la bibliothèque affiche tous les liens que vous avez enregistrés. Pour gérer votre liste et maintenir votre lecture organisée, Omnivore fournit les actions suivantes:
* <span style="text-decoration:underline;">Archiving</span>
* <span style="text-decoration:underline;">Labels</span>
* <span style="text-decoration:underline;">Search</span>
* <span style="text-decoration:underline;">Filters</span>
### Archivage
1. Appuyez sur l'icône Menu à côté du lien que vous souhaitez archiver (dans l'application mobile, appuyez longuement sur le lien pour ouvrir le menu).
2. Sélectionnez **Archive**.
3. Le lien disparaîtra de la vue par défaut de la bibliothèque, mais sera visible si vous sélectionnez le filtre Archivé (voir <span style="text-decoration:underline;">Filtres </span>ci-dessous).
### Étiquettes
1. Appuyez sur l'icône Menu à côté de n'importe quel lien et sélectionnez **Set Labels**.
2. Sélectionnez une étiquette existante dans la liste ou appuyez sur **Edit Labels** les étiquettes pour en créer une nouvelle.
3. L'étiquette apparaîtra à côté du lien dans votre bibliothèque. Appuyez dessus pour afficher tous les liens avec la même étiquette.
4. _Application mobile d'Omnivore uniquement_: appuyez sur **Labels ** pour voir une liste complète de toutes les étiquettes que vous avez utilisées; appuyez sur une étiquette pour afficher tous les liens avec la même étiquette.
5. Note : Omnivore attribuera automatiquement certaines étiquettes, telles que "Newsletters".
### Recherche
1. Pour rechercher parmi tous les liens que vous avez enregistrés, entrez un mot-clé ou une phrase dans la barre de recherche.
2. Vous pouvez combiner les mots-clés avec les étiquettes et les filtres pour cibler encore plus votre recherche. [En savoir plus sur la recherche avancée.](https://omnivore.app/help/search).
### Filtres
1. Utilisez le menu **Filters** pour affiner votre vue de la bibliothèque (certains filtres peuvent être visibles par défaut).
2. Sélectionnez **Read Later** pour afficher une liste de tous vos liens non archivés à l'exception des newsletters.
3. Sélectionnez **Highlights** pour afficher les sélections de texte que vous avez surlignées dans toutes les pages que vous avez enregistrées.
4. Sélectionnez **Today** pour afficher une liste de liens que vous avez enregistrés aujourd'hui.
5. Sélectionnez **Newsletters** pour afficher les liens enregistrés via vos abonnements à des newsletters.
## Intégrations
Omnivore permet des intégrations avec des bases de connaissances et des applications de prise de notes, notamment :
* Logseq
* Webhooks
### Logseq
Avec le plugin Omnivore pour Logseq, vous pouvez synchroniser tous vos articles enregistrés, vos surlignages et vos notes dans Logseq, une base de connaissances populaire. Pour obtenir des informations sur la configuration et l'utilisation du plugin Logseq, veuillez consulter ce guide utile [Omnivore pour le plugin Logseq](https://briansunter.com/graph/#/page/omnivore-logseq-guide).
### Webhooks
Omnivore peut déclencher des webhooks lorsque vous enregistrez un lien ou ajoutez des surlignages à une page que vous lisez. <span style="text-decoration:underline;">Cet exemple</span> montre comment utiliser les webhooks pour écrire tous les liens enregistrés dans une feuille de calcul Google Sheets stockée sur Google Drive.

View file

@ -68,7 +68,7 @@
"intercom-client": "^3.1.4",
"jsonwebtoken": "^8.5.1",
"jwks-rsa": "^2.0.3",
"knex": "0.21.12",
"knex": "2.4.2",
"knex-stringcase": "^1.4.2",
"linkedom": "^0.14.9",
"luxon": "^3.2.1",

View file

@ -7,7 +7,7 @@
import { ContextFunction } from 'apollo-server-core'
import { ClaimsToSet, ResolverContext } from './resolvers/types'
import { SetClaimsRole } from './utils/dictionary'
import Knex, { Transaction } from 'knex'
import { Knex } from 'knex'
import { ExpressContext } from 'apollo-server-express/dist/ApolloServer'
import * as jwt from 'jsonwebtoken'
import { kx } from './datalayer/knex_config'
@ -48,7 +48,7 @@ const contextFunc: ContextFunction<ExpressContext, ResolverContext> = async ({
const claims = await getClaimsByToken(token)
async function setClaims(
tx: Transaction,
tx: Knex.Transaction,
uuid?: string,
userRole?: string
): Promise<void> {

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ArticleData, CreateSet, keys as modelKeys, UpdateSet } from './model'
import DataModel from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { logMethod } from '../helpers'

View file

@ -1,11 +1,11 @@
import {
ArticleSavingRequestData,
CreateSet,
keys as modelKeys,
UpdateSet,
ArticleSavingRequestData,
} from './model'
import DataModel from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { logMethod } from '../helpers'

View file

@ -5,7 +5,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import DataModel from './model'
import Knex, { Transaction } from 'knex'
import { Knex } from 'knex'
import DataLoader from 'dataloader'
import { snakeCase } from 'snake-case'
import { buildLogger } from '../utils/logger'
@ -14,7 +14,7 @@ import { SetClaimsRole } from '../utils/dictionary'
const logger = buildLogger('datalayer')
export const setClaims = async (
tx: Transaction,
tx: Knex.Transaction,
uuid?: string,
userRole?: string
): Promise<void> => {

View file

@ -4,7 +4,7 @@
import DataModel, { DataModelError, MAX_RECORDS_LIMIT } from '../model'
import { CreateSet, HighlightData, keys as modelKeys, UpdateSet } from './model'
import { Table } from '../../utils/dictionary'
import Knex from 'knex'
import { Knex } from 'knex'
import { ENABLE_DB_REQUEST_LOGGING, globalCounter } from '../helpers'
import DataLoader from 'dataloader'
@ -26,7 +26,8 @@ class HighlightModel extends DataModel<HighlightData, CreateSet, UpdateSet> {
}
try {
const rows: HighlightData[] = await kx(this.tableName)
const rows: HighlightData[] = await kx
.table(this.tableName)
.select(this.modelKeys)
.whereIn('id', keys)
.andWhere('deleted', false)
@ -60,7 +61,8 @@ class HighlightModel extends DataModel<HighlightData, CreateSet, UpdateSet> {
)
}
const result = await this.kx(Table.HIGHLIGHT)
const result = await this.kx
.table(Table.HIGHLIGHT)
.select(modelKeys)
.whereIn('elasticPageId', articleIds)
.andWhere('deleted', false)
@ -153,7 +155,8 @@ class HighlightModel extends DataModel<HighlightData, CreateSet, UpdateSet> {
userId: string,
articleId: string
): Promise<HighlightData[]> {
const highlights = await this.kx(Table.HIGHLIGHT)
const highlights: HighlightData[] = await this.kx
.table(Table.HIGHLIGHT)
.select(modelKeys)
.where('user_id', userId)
.andWhere('elastic_page_id', articleId)

View file

@ -1,8 +1,8 @@
import { env } from '../env'
import Knex from 'knex'
import knex from 'knex'
import knexStringcase from 'knex-stringcase'
export const kx = Knex(
export const kx = knex(
knexStringcase({
client: 'pg',
connection: {

View file

@ -12,7 +12,7 @@ import {
UserFeedArticleData,
} from './model'
import DataModel, { MAX_RECORDS_LIMIT } from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import {
Article,

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import Knex from 'knex'
import { Knex } from 'knex'
import { LinkShareInfo } from '../../generated/graphql'
import { DataModels } from '../../resolvers/types'
import { getPageByParam } from '../../elastic/pages'

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import DataLoader from 'dataloader'
import Knex from 'knex'
import { Knex } from 'knex'
import { ENABLE_DB_REQUEST_LOGGING, globalCounter } from './helpers'
export enum DataModelError {
@ -113,7 +113,7 @@ abstract class DataModel<
tx: Knex.Transaction
): Promise<ModelData[]> {
const rows: ModelData[] = await tx
.batchInsert(this.tableName, data)
.batchInsert(this.tableName, data as never)
.returning('*')
for (const row of rows) {
this.loader.prime(row.id, row)

View file

@ -1,11 +1,11 @@
import {
globalCounter,
ENABLE_DB_REQUEST_LOGGING,
globalCounter,
logMethod,
} from './../helpers'
import { CreateSet, keys as modelKeys, UpdateSet, ReactionData } from './model'
import { CreateSet, keys as modelKeys, ReactionData, UpdateSet } from './model'
import DataModel, { DataModelError, MAX_RECORDS_LIMIT } from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import DataLoader from 'dataloader'

View file

@ -6,7 +6,7 @@ import {
UpdateSet,
} from './model'
import DataModel, { DataModelError } from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { logMethod } from '../helpers'
import { ArticleData } from '../article/model'

View file

@ -1,4 +1,4 @@
import Knex from 'knex'
import { Knex } from 'knex'
import { ReportType } from '../../generated/graphql'
interface ReportItem {

View file

@ -1,6 +1,6 @@
import { CreateSet, keys as modelKeys, UpdateSet, TaskData } from './model'
import { CreateSet, keys as modelKeys, TaskData, UpdateSet } from './model'
import DataModel from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { logMethod } from '../helpers'
class TaskModel extends DataModel<TaskData, CreateSet, UpdateSet> {

View file

@ -7,7 +7,7 @@ import {
UploadFileData,
} from './model'
import DataModel from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { logMethod } from '../helpers'

View file

@ -11,7 +11,7 @@ import {
UserData,
} from './model'
import DataModel, { DataModelError, MAX_RECORDS_LIMIT } from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { ENABLE_DB_REQUEST_LOGGING, globalCounter, logMethod } from '../helpers'
import { Table } from '../../utils/dictionary'
import DataLoader from 'dataloader'

View file

@ -6,7 +6,7 @@ import {
UserFriendData,
} from './model'
import DataModel, { MAX_RECORDS_LIMIT } from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { ENABLE_DB_REQUEST_LOGGING, globalCounter, logMethod } from '../helpers'
import DataLoader from 'dataloader'

View file

@ -9,7 +9,7 @@ import {
UserPersonalizationData,
} from './model'
import DataModel from '../model'
import Knex from 'knex'
import { Knex } from 'knex'
import { Table } from '../../utils/dictionary'
import { camelCase } from 'voca'
import { logMethod } from '../helpers'

View file

@ -254,7 +254,7 @@ export const updateHighlight = async (
ctx: PageContext
): Promise<boolean> => {
try {
const { body } = await client.updateByQuery({
await client.updateByQuery({
index: INDEX_ALIAS,
body: {
script: {
@ -263,7 +263,7 @@ export const updateHighlight = async (
ctx._source.updatedAt = params.highlight.updatedAt`,
lang: 'painless',
params: {
highlight: highlight,
highlight,
},
},
query: {
@ -289,10 +289,9 @@ export const updateHighlight = async (
},
},
refresh: ctx.refresh,
conflicts: 'proceed',
})
if (body.updated === 0) return false
await ctx.pubsub.entityUpdated<Highlight>(
EntityType.HIGHLIGHT,
highlight,

View file

@ -2714,6 +2714,7 @@ export enum UpdateHighlightErrorCode {
export type UpdateHighlightInput = {
annotation?: InputMaybe<Scalars['String']>;
highlightId: Scalars['ID'];
quote?: InputMaybe<Scalars['String']>;
sharedAt?: InputMaybe<Scalars['Date']>;
};
@ -2813,6 +2814,7 @@ export type UpdatePageInput = {
byline?: InputMaybe<Scalars['String']>;
description?: InputMaybe<Scalars['String']>;
pageId: Scalars['ID'];
publishedAt?: InputMaybe<Scalars['Date']>;
savedAt?: InputMaybe<Scalars['Date']>;
title?: InputMaybe<Scalars['String']>;
};

View file

@ -2075,6 +2075,7 @@ enum UpdateHighlightErrorCode {
input UpdateHighlightInput {
annotation: String
highlightId: ID!
quote: String
sharedAt: Date
}
@ -2166,6 +2167,7 @@ input UpdatePageInput {
byline: String
description: String
pageId: ID!
publishedAt: Date
savedAt: Date
title: String
}

View file

@ -8,7 +8,7 @@ declare module '*.graphql' {
}
declare module 'knex-stringcase' {
import * as Knex from 'knex'
import { Knex } from 'knex'
type StringCase =
| 'camelcase'

View file

@ -204,8 +204,7 @@ export const updateHighlightResolver = authorized<
UpdateHighlightError,
MutationUpdateHighlightArgs
>(async (_, { input }, { pubsub, claims, log }) => {
const { highlightId } = input
const highlight = await getHighlightById(highlightId)
const highlight = await getHighlightById(input.highlightId)
if (!highlight?.id) {
return {
@ -219,20 +218,16 @@ export const updateHighlightResolver = authorized<
}
}
if (input.annotation && input.annotation.length > 4000) {
return {
errorCodes: [UpdateHighlightErrorCode.BadData],
}
}
// unescape HTML entities
const annotation = input.annotation
? unescapeHtml(input.annotation)
: undefined
const quote = input.quote ? unescapeHtml(input.quote) : highlight.quote
const updatedHighlight: HighlightData = {
...highlight,
annotation,
quote,
updatedAt: new Date(),
}

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/ban-types */
import { Context as ApolloContext } from 'apollo-server-core'
import winston from 'winston'
import Knex from 'knex'
import { Knex } from 'knex'
import UserModel from '../datalayer/user'
import ArticleModel from '../datalayer/article'
import UserArticleModel from '../datalayer/links'

View file

@ -41,6 +41,7 @@ export const updatePageResolver = authorized<
description: input.description ?? undefined,
author: input.byline ?? undefined,
savedAt: input.savedAt ? new Date(input.savedAt) : undefined,
publishedAt: input.publishedAt ? new Date(input.publishedAt) : undefined,
}
const updateResult = await updatePage(input.pageId, pageData, { ...ctx, uid })

View file

@ -1,18 +1,18 @@
import Knex from 'knex'
import { Knex } from 'knex'
import { UserData } from '../../datalayer/user/model'
import {
User,
ResolverFn,
SetFollowSuccess,
SetFollowError,
MutationSetFollowArgs,
SetFollowErrorCode,
GetFollowersResult,
GetFollowingResult,
MutationSetFollowArgs,
QueryGetFollowersArgs,
QueryGetFollowingArgs,
ResolverFn,
SetFollowError,
SetFollowErrorCode,
SetFollowSuccess,
User,
} from '../../generated/graphql'
import { userDataToUser, authorized } from '../../utils/helpers'
import { authorized, userDataToUser } from '../../utils/helpers'
import { DataModels, WithDataSourcesContext } from '../types'
export const setFollowResolver = authorized<

View file

@ -565,6 +565,7 @@ const schema = gql`
description: String
byline: String
savedAt: Date
publishedAt: Date
}
type UpdatePageSuccess {
@ -747,8 +748,9 @@ const schema = gql`
input UpdateHighlightInput {
highlightId: ID!
annotation: String @sanitize
annotation: String @sanitize(maxLength: 4000)
sharedAt: Date
quote: String @sanitize(maxLength: 6000)
}
type UpdateHighlightSuccess {

View file

@ -7,7 +7,7 @@ import { json, urlencoded } from 'body-parser'
import cookieParser from 'cookie-parser'
import express, { Express } from 'express'
import { createServer, Server } from 'http'
import Knex from 'knex'
import { Knex } from 'knex'
import { env } from './env'
import * as Sentry from '@sentry/node'
import * as lw from '@google-cloud/logging-winston'

View file

@ -1,4 +1,4 @@
import Knex from 'knex'
import { Knex } from 'knex'
import { PubsubClient } from '../datalayer/pubsub'
import { UserData } from '../datalayer/user/model'
import { homePageURL } from '../env'

View file

@ -104,23 +104,29 @@ const mergeHighlightQuery = (
`
}
const updateHighlightQuery = (
authToken: string,
highlightId: string,
annotation = '_annotation'
) => {
const updateHighlightQuery = ({
highlightId,
annotation = null,
quote = null,
}: {
highlightId: string
annotation?: string | null
quote?: string | null
}) => {
return `
mutation {
updateHighlight(
input: {
annotation: "${annotation}",
highlightId: "${highlightId}",
quote: "${quote}"
}
) {
... on UpdateHighlightSuccess {
highlight {
id
annotation
quote
}
}
... on UpdateHighlightError {
@ -271,15 +277,30 @@ describe('Highlights API', () => {
)
})
context('when the annotation has HTML reserved characters', () => {
it('unescapes the annotation and updates', async () => {
const annotation = '> This is a test'
const query = updateHighlightQuery(authToken, highlightId, annotation)
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.updateHighlight.highlight.annotation).to.eql(
'> This is a test'
)
it('updates the quote when the quote is in HTML format when the annotation has HTML reserved characters', async () => {
const quote = '> This is a test'
const query = updateHighlightQuery({ highlightId, quote })
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.updateHighlight.highlight.quote).to.eql(quote)
})
it('updates the quote when the quote is in plain text format', async () => {
const quote = 'This is a test'
const query = updateHighlightQuery({ highlightId, quote })
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.updateHighlight.highlight.quote).to.eql(quote)
})
it('unescapes the annotation and updates the annotation when the annotation has HTML reserved characters', async () => {
const annotation = '> This is a test'
const query = updateHighlightQuery({
highlightId,
annotation,
})
const res = await graphqlRequest(query, authToken).expect(200)
expect(res.body.data.updateHighlight.highlight.annotation).to.eql(
annotation
)
})
})
})

View file

@ -150,8 +150,8 @@ export abstract class ContentHandler {
// e.g. List-Unsubscribe: <https://omnivore.com/unsub>, <mailto:unsub@omnivore.com>
const decoded = rfc2047.decode(unSubHeader)
return {
mailTo: decoded.match(/<(https?:\/\/[^>]*)>/)?.[1],
httpUrl: decoded.match(/<mailto:([^>]*)>/)?.[1],
httpUrl: decoded.match(/<(https?:\/\/[^>]*)>/)?.[1],
mailTo: decoded.match(/<mailto:([^>]*)>/)?.[1],
}
}

View file

@ -516,4 +516,35 @@ describe('Newsletter email test', () => {
expect(url1).to.not.eql(url2)
})
})
describe('get unsubscribe from header', () => {
const mailTo = 'unsub@omnivore.com'
const httpUrl = 'https://omnivore.com/unsubscribe'
it('returns mail to address if exists', () => {
const header = `<https://omnivore.com/unsub>, <mailto:${mailTo}>`
expect(new GenericHandler().parseUnsubscribe(header).mailTo).to.equal(
mailTo
)
})
it('returns http url if exists', () => {
const header = `<${httpUrl}>`
expect(new GenericHandler().parseUnsubscribe(header).httpUrl).to.equal(
httpUrl
)
})
context('when unsubscribe header rfc2047 encoded', () => {
it('returns mail to address if exists', () => {
const header = `=?us-ascii?Q?=3Cmailto=3A654e9594-184c-4884-8e02-e6e58a3a6871+87e39b3d-c3ca-4be?= =?us-ascii?Q?b-ba4d-977cc2ba61e7+067a353f-f775-4f2c-?= =?us-ascii?Q?a5cc-978df38deeca=40unsub=2Ebeehiiv=2Ecom=3E=2C?= =?us-ascii?Q?_=3Chttps=3A=2F=2Fwww=2Emilkroad=2Ecom=2Fsubscribe=2F87e39b3d-c3ca-4beb-ba4d-97?= =?us-ascii?Q?7cc2ba61e7=2Fmanage=3Fpost=5Fid=3D067a353f-f775?= =?us-ascii?Q?-4f2c-a5cc-978df38deeca=3E?=',`
expect(new GenericHandler().parseUnsubscribe(header).mailTo).to.equal(
'654e9594-184c-4884-8e02-e6e58a3a6871+87e39b3d-c3ca-4beb-ba4d-977cc2ba61e7+067a353f-f775-4f2c-a5cc-978df38deeca@unsub.beehiiv.com'
)
})
})
})
})

View file

@ -7,7 +7,7 @@
},
"dependencies": {
"@testing-library/cypress": "^8.0.2",
"cypress": "^10.1.0"
"cypress": "^12.7.0"
},
"devDependencies": {},
"volta": {

View file

@ -141,7 +141,6 @@ export const inboundEmailHandler = Sentry.GCPFunction.wrapHttpFunction(
if (isConfirmationEmail(from, subject)) {
console.log('handleConfirmation', from)
await handleConfirmation(to, subject)
return res.send('ok')
}
if (pdfAttachment) {
@ -187,6 +186,7 @@ export const inboundEmailHandler = Sentry.GCPFunction.wrapHttpFunction(
receivedEmailId,
},
})
res.send('ok')
}
} catch (e) {
console.log(e)

View file

@ -397,15 +397,33 @@ function validateUrlString(url) {
}
}
function tryParseUrl(urlStr) {
if (!urlStr) {
return null;
}
// a regular expression to match all URLs
const regex = /(https?:\/\/[^\s]+)/g;
const matches = urlStr.match(regex);
if (matches) {
return matches[0]; // only return first match
} else {
return null;
}
}
function getUrl(req) {
const urlStr = (req.query ? req.query.url : undefined) || (req.body ? req.body.url : undefined);
if (!urlStr) {
const url = tryParseUrl(urlStr)
if (!url) {
throw new Error('No URL specified');
}
validateUrlString(urlStr);
validateUrlString(url);
const parsed = Url.parse(urlStr);
const parsed = Url.parse(url);
return parsed.href;
}

201
yarn.lock
View file

@ -4277,9 +4277,9 @@
integrity sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==
"@next/bundle-analyzer@^13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-13.2.1.tgz#a80bf24adef2380233c9e3cd9f5c77849c851b36"
integrity sha512-ex5CyyqWfBaDE0eguyhWlWZAsg2n9zN1c/YK4FNui7C/cKnjib5FcZeVNeKU9PfSYXDDT9onIhWkhsMNQwIGVg==
version "13.2.3"
resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-13.2.3.tgz#8a34f595f9d213b39fc68f5246f59d5043f8c6f4"
integrity sha512-hPAT0ja6zHmEIrLYAWmdtpS07FCuUL8TxKP5ekzel+NoP4cNOykBS2Y265ciJwurpisd8Ux29g3QgeyBBSBnLA==
dependencies:
webpack-bundle-analyzer "4.7.0"
@ -4920,15 +4920,15 @@
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-slot" "0.1.2"
"@radix-ui/react-collection@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5"
integrity sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==
"@radix-ui/react-collection@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.2.tgz#d50da00bfa2ac14585319efdbbb081d4c5a29a97"
integrity sha512-s8WdQQ6wNXpaxdZ308KSr8fEWGrg4un8i4r/w7fhiS4ElRNjk5rRcl0/C6TANG2LvLOGIxtzo/jAg6Qf73TEBw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.0"
"@radix-ui/react-context" "1.0.0"
"@radix-ui/react-primitive" "1.0.1"
"@radix-ui/react-primitive" "1.0.2"
"@radix-ui/react-slot" "1.0.1"
"@radix-ui/react-compose-refs@0.1.0":
@ -5152,6 +5152,14 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.1"
"@radix-ui/react-primitive@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz#54e22f49ca59ba88d8143090276d50b93f8a7053"
integrity sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.1"
"@radix-ui/react-progress@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.0.1.tgz#49ec2f729a67ba3b580a90356fc1d871466a4212"
@ -5185,18 +5193,18 @@
"@radix-ui/react-primitive" "0.1.3"
"@radix-ui/react-slider@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.1.0.tgz#b3fdaca27619150e9e6067ad9f979a4535f68d5e"
integrity sha512-5H/QB4xD3GF9UfoSCVLBx2JjlXamMcmTyL6gr4kkd/MiAGaYB0W7Exi4MQa0tJApBFJe+KmS5InKCI56p2kmjA==
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.1.1.tgz#5685f23b6244804a5b1f55cee2d321a2acd1878e"
integrity sha512-0aswLpUKZIraPEOcXfwW25N1KPfLA6Mvm1TxogUChGsbLbys2ihd7uk9XAKsol9ZQPucxh2/mybwdRtAKrs/MQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/number" "1.0.0"
"@radix-ui/primitive" "1.0.0"
"@radix-ui/react-collection" "1.0.1"
"@radix-ui/react-collection" "1.0.2"
"@radix-ui/react-compose-refs" "1.0.0"
"@radix-ui/react-context" "1.0.0"
"@radix-ui/react-direction" "1.0.0"
"@radix-ui/react-primitive" "1.0.1"
"@radix-ui/react-primitive" "1.0.2"
"@radix-ui/react-use-controllable-state" "1.0.0"
"@radix-ui/react-use-layout-effect" "1.0.0"
"@radix-ui/react-use-previous" "1.0.0"
@ -5219,15 +5227,15 @@
"@radix-ui/react-compose-refs" "1.0.0"
"@radix-ui/react-switch@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-switch/-/react-switch-1.0.1.tgz#56665fa951a4190313be21fab70a90041bdbd191"
integrity sha512-tTxGluMtwrc5ffgAiOSMrYIx0r3vSTcgM4Vl8rqfpXcHt6ryB9B0OlFKUOiDpKASXlhvzfHf4Y0AYKJdpzjL8w==
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-switch/-/react-switch-1.0.2.tgz#e3d1b9fe18b6b1173aadc8b8e6efdc96a28a70f8"
integrity sha512-BcG/LKehxt36NXG0wPnoCitIfSMtU9Xo7BmythYA1PAMLtsMvW7kALfBzmduQoHTWcKr0AVcFyh0gChBUp9TiQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.0"
"@radix-ui/react-compose-refs" "1.0.0"
"@radix-ui/react-context" "1.0.0"
"@radix-ui/react-primitive" "1.0.1"
"@radix-ui/react-primitive" "1.0.2"
"@radix-ui/react-use-controllable-state" "1.0.0"
"@radix-ui/react-use-previous" "1.0.0"
"@radix-ui/react-use-size" "1.0.0"
@ -11861,26 +11869,16 @@ color@3.0.x:
color-convert "^1.9.1"
color-string "^1.5.2"
colorette@1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
colorette@2.0.19, colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16:
version "2.0.19"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798"
integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==
colorette@^1.2.2:
colorette@^1.2.2, colorette@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
colorette@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af"
integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==
colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16:
version "2.0.16"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
colorspace@1.1.x:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
@ -11944,6 +11942,11 @@ commander@^8.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
commander@^9.1.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
common-path-prefix@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0"
@ -12644,10 +12647,10 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
cypress@^10.1.0:
version "10.6.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.6.0.tgz#13f46867febf2c3715874ed5dce9c2e946b175fe"
integrity sha512-6sOpHjostp8gcLO34p6r/Ci342lBs8S5z9/eb3ZCQ22w2cIhMWGUoGKkosabPBfKcvRS9BE4UxybBtlIs8gTQA==
cypress@^12.7.0:
version "12.7.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.7.0.tgz#69900f82af76cf3ba0ddb9b59ec3b0d38222ab22"
integrity sha512-7rq+nmhzz0u6yabCFyPtADU2OOrYt6pvUau9qV7xyifJ/hnsaw/vkr0tnLlcuuQKUAOC1v1M1e4Z0zG7S0IAvA==
dependencies:
"@cypress/request" "^2.88.10"
"@cypress/xvfb" "^1.2.4"
@ -12666,9 +12669,9 @@ cypress@^10.1.0:
commander "^5.1.0"
common-tags "^1.8.0"
dayjs "^1.10.4"
debug "^4.3.2"
debug "^4.3.4"
enquirer "^2.3.6"
eventemitter2 "^6.4.3"
eventemitter2 "6.4.7"
execa "4.1.0"
executable "^4.1.1"
extract-zip "2.0.1"
@ -12748,16 +12751,11 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
dayjs@1.x:
dayjs@1.x, dayjs@^1.10.4:
version "1.11.6"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.6.tgz#2e79a226314ec3ec904e3ee1dd5a4f5e5b1c7afb"
integrity sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ==
dayjs@^1.10.4:
version "1.11.0"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805"
integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==
dayjs@^1.11.7:
version "1.11.7"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"
@ -12775,20 +12773,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
dependencies:
ms "^2.1.1"
debug@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
@ -14201,10 +14192,10 @@ event-target-shim@^5.0.0:
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
eventemitter2@^6.4.3:
version "6.4.5"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.5.tgz#97380f758ae24ac15df8353e0cc27f8b95644655"
integrity sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==
eventemitter2@6.4.7:
version "6.4.7"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==
eventemitter3@^3.1.0:
version "3.1.2"
@ -14761,16 +14752,6 @@ findup-sync@^2.0.0:
micromatch "^3.0.4"
resolve-dir "^1.0.1"
findup-sync@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
dependencies:
detect-file "^1.0.0"
is-glob "^4.0.0"
micromatch "^3.0.4"
resolve-dir "^1.0.1"
fined@^1.0.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b"
@ -15302,10 +15283,10 @@ get-value@^2.0.3, get-value@^2.0.6:
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
getopts@2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b"
integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==
getopts@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4"
integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==
getos@^3.2.1:
version "3.2.1"
@ -18495,23 +18476,25 @@ knex-stringcase@^1.4.2:
dependencies:
stringcase "^4.3.1"
knex@0.21.12:
version "0.21.12"
resolved "https://registry.yarnpkg.com/knex/-/knex-0.21.12.tgz#961bdb484311eb853030f6f49bd5bf9eca89dc51"
integrity sha512-AEyyiTM9p/x/Pb38TPZkvphKPmn8UWxP7MdIphzjAOielOfFFeU6pjP6y3M7UJ7rxrQsCrAYHwdonLQ3l1JCDw==
knex@2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/knex/-/knex-2.4.2.tgz#a34a289d38406dc19a0447a78eeaf2d16ebedd61"
integrity sha512-tMI1M7a+xwHhPxjbl/H9K1kHX+VncEYcvCx5K00M16bWvpYPKAZd6QrCu68PtHAdIZNQPWZn0GVhqVBEthGWCg==
dependencies:
colorette "1.2.1"
commander "^5.1.0"
debug "4.1.1"
colorette "2.0.19"
commander "^9.1.0"
debug "4.3.4"
escalade "^3.1.1"
esm "^3.2.25"
getopts "2.2.5"
get-package-type "^0.1.0"
getopts "2.3.0"
interpret "^2.2.0"
liftoff "3.1.0"
lodash "^4.17.20"
pg-connection-string "2.3.0"
tarn "^3.0.1"
lodash "^4.17.21"
pg-connection-string "2.5.0"
rechoir "^0.8.0"
resolve-from "^5.0.0"
tarn "^3.0.2"
tildify "2.0.0"
v8flags "^3.2.0"
kuler@^2.0.0:
version "2.0.0"
@ -18636,20 +18619,6 @@ lie@3.1.1:
dependencies:
immediate "~3.0.5"
liftoff@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==
dependencies:
extend "^3.0.0"
findup-sync "^3.0.0"
fined "^1.0.1"
flagged-respawn "^1.0.0"
is-plain-object "^2.0.4"
object.map "^1.0.0"
rechoir "^0.6.2"
resolve "^1.1.7"
liftoff@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec"
@ -21612,12 +21581,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pg-connection-string@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.3.0.tgz#c13fcb84c298d0bfa9ba12b40dd6c23d946f55d6"
integrity sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==
pg-connection-string@^2.5.0:
pg-connection-string@2.5.0, pg-connection-string@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
@ -23427,6 +23391,13 @@ rechoir@^0.7.0:
dependencies:
resolve "^1.9.0"
rechoir@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
dependencies:
resolve "^1.20.0"
redent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
@ -24199,14 +24170,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
semver@^7.1.2:
semver@^7.1.1, semver@^7.1.2, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
@ -25446,10 +25410,10 @@ tar@^6.0.2, tar@^6.1.0:
mkdirp "^1.0.3"
yallist "^4.0.0"
tarn@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.1.tgz#ebac2c6dbc6977d34d4526e0a7814200386a8aec"
integrity sha512-6usSlV9KyHsspvwu2duKH+FMUhqJnAh6J5J/4MITl8s94iSUQTLkJggdiewKv4RyARQccnigV48Z+khiuVZDJw==
tarn@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693"
integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==
teeny-request@^7.0.0:
version "7.1.1"
@ -26705,13 +26669,6 @@ v8flags@^2.0.10:
dependencies:
user-home "^1.1.1"
v8flags@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656"
integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==
dependencies:
homedir-polyfill "^1.0.1"
valid-url@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"