diff --git a/README.md b/README.md
index 2ff862c17..1d8f2ad22 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/docs/guides/getting-started/fr/getting-started-guide.md b/docs/guides/getting-started/fr/getting-started-guide.md
new file mode 100644
index 000000000..79dce2450
--- /dev/null
+++ b/docs/guides/getting-started/fr/getting-started-guide.md
@@ -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 :
+
+* Modifier la mise en forme
+* Surligner le texte
+* Ajouter des notes
+* Voir toutes les surlignages et notes enregistrés
+* Suivre la progression de la lecture
+
+### 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:
+
+* Archiving
+* Labels
+* Search
+* Filters
+
+### 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 Filtres 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. Cet exemple montre comment utiliser les webhooks pour écrire tous les liens enregistrés dans une feuille de calcul Google Sheets stockée sur Google Drive.
\ No newline at end of file
diff --git a/packages/api/package.json b/packages/api/package.json
index c7ed1be8c..d7aea4f75 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -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",
diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts
index 075245092..0a8f49fb8 100644
--- a/packages/api/src/apollo.ts
+++ b/packages/api/src/apollo.ts
@@ -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 = async ({
const claims = await getClaimsByToken(token)
async function setClaims(
- tx: Transaction,
+ tx: Knex.Transaction,
uuid?: string,
userRole?: string
): Promise {
diff --git a/packages/api/src/datalayer/article/index.ts b/packages/api/src/datalayer/article/index.ts
index 5ddb6f12a..f6235265a 100644
--- a/packages/api/src/datalayer/article/index.ts
+++ b/packages/api/src/datalayer/article/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/article_saving_request/index.ts b/packages/api/src/datalayer/article_saving_request/index.ts
index c753fcddb..c9d625622 100644
--- a/packages/api/src/datalayer/article_saving_request/index.ts
+++ b/packages/api/src/datalayer/article_saving_request/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/helpers.ts b/packages/api/src/datalayer/helpers.ts
index 65cd78ef0..7768d0667 100644
--- a/packages/api/src/datalayer/helpers.ts
+++ b/packages/api/src/datalayer/helpers.ts
@@ -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 => {
diff --git a/packages/api/src/datalayer/highlight/index.ts b/packages/api/src/datalayer/highlight/index.ts
index 1f7ac2fc5..8bd8fb06a 100644
--- a/packages/api/src/datalayer/highlight/index.ts
+++ b/packages/api/src/datalayer/highlight/index.ts
@@ -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 {
}
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 {
)
}
- 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 {
userId: string,
articleId: string
): Promise {
- 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)
diff --git a/packages/api/src/datalayer/knex_config.ts b/packages/api/src/datalayer/knex_config.ts
index 6758a4454..06ff66783 100644
--- a/packages/api/src/datalayer/knex_config.ts
+++ b/packages/api/src/datalayer/knex_config.ts
@@ -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: {
diff --git a/packages/api/src/datalayer/links/index.ts b/packages/api/src/datalayer/links/index.ts
index ab8a36308..08ba9e266 100644
--- a/packages/api/src/datalayer/links/index.ts
+++ b/packages/api/src/datalayer/links/index.ts
@@ -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,
diff --git a/packages/api/src/datalayer/links/share_info.ts b/packages/api/src/datalayer/links/share_info.ts
index 2646cfc57..cf1126eaa 100644
--- a/packages/api/src/datalayer/links/share_info.ts
+++ b/packages/api/src/datalayer/links/share_info.ts
@@ -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'
diff --git a/packages/api/src/datalayer/model.ts b/packages/api/src/datalayer/model.ts
index 98b3d5dac..f2ebfe2d2 100644
--- a/packages/api/src/datalayer/model.ts
+++ b/packages/api/src/datalayer/model.ts
@@ -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 {
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)
diff --git a/packages/api/src/datalayer/reaction/index.ts b/packages/api/src/datalayer/reaction/index.ts
index 2b1cec74c..6c77544f1 100644
--- a/packages/api/src/datalayer/reaction/index.ts
+++ b/packages/api/src/datalayer/reaction/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/reminders/index.ts b/packages/api/src/datalayer/reminders/index.ts
index c910dc605..2b6e74728 100644
--- a/packages/api/src/datalayer/reminders/index.ts
+++ b/packages/api/src/datalayer/reminders/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/report/index.ts b/packages/api/src/datalayer/report/index.ts
index fbcbd8166..0906e281e 100644
--- a/packages/api/src/datalayer/report/index.ts
+++ b/packages/api/src/datalayer/report/index.ts
@@ -1,4 +1,4 @@
-import Knex from 'knex'
+import { Knex } from 'knex'
import { ReportType } from '../../generated/graphql'
interface ReportItem {
diff --git a/packages/api/src/datalayer/task/index.ts b/packages/api/src/datalayer/task/index.ts
index 969f883dd..b0f31624d 100644
--- a/packages/api/src/datalayer/task/index.ts
+++ b/packages/api/src/datalayer/task/index.ts
@@ -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 {
diff --git a/packages/api/src/datalayer/upload_files/index.ts b/packages/api/src/datalayer/upload_files/index.ts
index 6a412b99f..6899d6309 100644
--- a/packages/api/src/datalayer/upload_files/index.ts
+++ b/packages/api/src/datalayer/upload_files/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/user/index.ts b/packages/api/src/datalayer/user/index.ts
index a4f6058b2..5112c08b6 100644
--- a/packages/api/src/datalayer/user/index.ts
+++ b/packages/api/src/datalayer/user/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/user_friends/index.ts b/packages/api/src/datalayer/user_friends/index.ts
index 15695261d..8ff18e0d8 100644
--- a/packages/api/src/datalayer/user_friends/index.ts
+++ b/packages/api/src/datalayer/user_friends/index.ts
@@ -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'
diff --git a/packages/api/src/datalayer/user_personalization/index.ts b/packages/api/src/datalayer/user_personalization/index.ts
index 1fd0894e0..424de749d 100644
--- a/packages/api/src/datalayer/user_personalization/index.ts
+++ b/packages/api/src/datalayer/user_personalization/index.ts
@@ -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'
diff --git a/packages/api/src/elastic/highlights.ts b/packages/api/src/elastic/highlights.ts
index 19564c80e..7a93338b4 100644
--- a/packages/api/src/elastic/highlights.ts
+++ b/packages/api/src/elastic/highlights.ts
@@ -254,7 +254,7 @@ export const updateHighlight = async (
ctx: PageContext
): Promise => {
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(
EntityType.HIGHLIGHT,
highlight,
diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts
index 161a0dca3..44c16e204 100644
--- a/packages/api/src/generated/graphql.ts
+++ b/packages/api/src/generated/graphql.ts
@@ -2714,6 +2714,7 @@ export enum UpdateHighlightErrorCode {
export type UpdateHighlightInput = {
annotation?: InputMaybe;
highlightId: Scalars['ID'];
+ quote?: InputMaybe;
sharedAt?: InputMaybe;
};
@@ -2813,6 +2814,7 @@ export type UpdatePageInput = {
byline?: InputMaybe;
description?: InputMaybe;
pageId: Scalars['ID'];
+ publishedAt?: InputMaybe;
savedAt?: InputMaybe;
title?: InputMaybe;
};
diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql
index 34968394b..7c7b36037 100644
--- a/packages/api/src/generated/schema.graphql
+++ b/packages/api/src/generated/schema.graphql
@@ -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
}
diff --git a/packages/api/src/graphql.d.ts b/packages/api/src/graphql.d.ts
index edc12ba67..6c4bc953c 100755
--- a/packages/api/src/graphql.d.ts
+++ b/packages/api/src/graphql.d.ts
@@ -8,7 +8,7 @@ declare module '*.graphql' {
}
declare module 'knex-stringcase' {
- import * as Knex from 'knex'
+ import { Knex } from 'knex'
type StringCase =
| 'camelcase'
diff --git a/packages/api/src/resolvers/highlight/index.ts b/packages/api/src/resolvers/highlight/index.ts
index 120554c86..55c2a7879 100644
--- a/packages/api/src/resolvers/highlight/index.ts
+++ b/packages/api/src/resolvers/highlight/index.ts
@@ -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(),
}
diff --git a/packages/api/src/resolvers/types.ts b/packages/api/src/resolvers/types.ts
index 00e11b978..5e7aa2d00 100644
--- a/packages/api/src/resolvers/types.ts
+++ b/packages/api/src/resolvers/types.ts
@@ -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'
diff --git a/packages/api/src/resolvers/update/index.ts b/packages/api/src/resolvers/update/index.ts
index 8b2551518..0570e43b8 100644
--- a/packages/api/src/resolvers/update/index.ts
+++ b/packages/api/src/resolvers/update/index.ts
@@ -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 })
diff --git a/packages/api/src/resolvers/user_friends/index.ts b/packages/api/src/resolvers/user_friends/index.ts
index ea13cc095..39da6e5d8 100644
--- a/packages/api/src/resolvers/user_friends/index.ts
+++ b/packages/api/src/resolvers/user_friends/index.ts
@@ -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<
diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts
index 5d4353c0b..1a1efa40d 100755
--- a/packages/api/src/schema.ts
+++ b/packages/api/src/schema.ts
@@ -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 {
diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts
index bb15c3d3e..506046777 100755
--- a/packages/api/src/server.ts
+++ b/packages/api/src/server.ts
@@ -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'
diff --git a/packages/api/src/services/save_file.ts b/packages/api/src/services/save_file.ts
index da3e32f4f..64233aab6 100644
--- a/packages/api/src/services/save_file.ts
+++ b/packages/api/src/services/save_file.ts
@@ -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'
diff --git a/packages/api/test/resolvers/highlight.test.ts b/packages/api/test/resolvers/highlight.test.ts
index bd7a6d1dc..3a687c12a 100644
--- a/packages/api/test/resolvers/highlight.test.ts
+++ b/packages/api/test/resolvers/highlight.test.ts
@@ -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
+ )
})
})
})
diff --git a/packages/content-handler/src/content-handler.ts b/packages/content-handler/src/content-handler.ts
index 1a27344f0..7ef7dffd2 100644
--- a/packages/content-handler/src/content-handler.ts
+++ b/packages/content-handler/src/content-handler.ts
@@ -150,8 +150,8 @@ export abstract class ContentHandler {
// e.g. List-Unsubscribe: ,
const decoded = rfc2047.decode(unSubHeader)
return {
- mailTo: decoded.match(/<(https?:\/\/[^>]*)>/)?.[1],
- httpUrl: decoded.match(/]*)>/)?.[1],
+ httpUrl: decoded.match(/<(https?:\/\/[^>]*)>/)?.[1],
+ mailTo: decoded.match(/]*)>/)?.[1],
}
}
diff --git a/packages/content-handler/test/newsletter.test.ts b/packages/content-handler/test/newsletter.test.ts
index 0ffa6d666..a515cf486 100644
--- a/packages/content-handler/test/newsletter.test.ts
+++ b/packages/content-handler/test/newsletter.test.ts
@@ -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 = `, `
+
+ 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'
+ )
+ })
+ })
+ })
})
diff --git a/packages/cypress/package.json b/packages/cypress/package.json
index 34a14a5a6..f13495814 100644
--- a/packages/cypress/package.json
+++ b/packages/cypress/package.json
@@ -7,7 +7,7 @@
},
"dependencies": {
"@testing-library/cypress": "^8.0.2",
- "cypress": "^10.1.0"
+ "cypress": "^12.7.0"
},
"devDependencies": {},
"volta": {
diff --git a/packages/inbound-email-handler/src/index.ts b/packages/inbound-email-handler/src/index.ts
index 12e587e3c..adb44f4eb 100644
--- a/packages/inbound-email-handler/src/index.ts
+++ b/packages/inbound-email-handler/src/index.ts
@@ -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)
diff --git a/packages/puppeteer-parse/index.js b/packages/puppeteer-parse/index.js
index a9da97977..26dc7eef2 100644
--- a/packages/puppeteer-parse/index.js
+++ b/packages/puppeteer-parse/index.js
@@ -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;
}
diff --git a/yarn.lock b/yarn.lock
index 706119194..9f0406df7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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"