diff --git a/.gitignore b/.gitignore index ff3babd..c9e85bb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules .temp .cache .env -dist/ \ No newline at end of file +dist/ +.idea/ \ No newline at end of file diff --git a/README.md b/README.md index 85fc224..9be1e42 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,12 @@ The following [Notion API block object types](https://developers.notion.com/refe | Video | ❌ Missing | | | File | ❌ Missing | | | PDF | ❌ Missing | | -| Bookmark | ❌ Missing | | +| Bookmark | ✅ Yes | use a caption as a link name | | | Equation | ❌ Missing | | | Divider | ✅ Yes | | | Table Of Contents | ❌ not planned | static site generators have their own ToC implementations | | Breadcrumb | ❌ not planned | static site generators have their own nav implementations | +| Synced Block | ✅ Yes | renders all children blocks | Support for other block types can be considered once they are available on the official Notion API. @@ -76,7 +77,7 @@ The following [Notion API page property types](https://developers.notion.com/ref | Propety type | Supported | Notes | | ---------------- | --------- | ----------------------------- | -| Rich text | ✅ Yes | rendered as markdown string | +| Rich text | ✅ Yes | rendered as plaintext string | | Number | ✅ Yes | | | Select | ✅ Yes | rendered as name | | Multi Select | ✅ Yes | rendered as array of names | @@ -85,7 +86,7 @@ The following [Notion API page property types](https://developers.notion.com/ref | Relation | ✅ Yes | rendered as array of page ids | | Rollup | ❌ missing | | | Title | ✅ Yes | used as page title | -| People | ❌ missing | | +| People | ✅ Yes | rendered as comma-separated list of names | | Files | ❌ missing | | | Checkbox | ❌ missing | | | Url | ✅ Yes | rendered as string | @@ -111,15 +112,20 @@ Consult the [SyncConfig](./src/SyncConfig.ts) reference for documentation of ava > A CLI tool could be made available later. ```typescript -import { SyncConfig, sync } from "notion-markdown-cms"; - +import { slugify, SyncConfig, sync } from "notion-markdown-cms"; const config: SyncConfig = { cmsDatabaseId: "8f1de8c578fb4590ad6fbb0dbe283338", - outDir: "docs/", - indexPath: "docs/.vuepress/index.ts", + pages: { + destinationDirBuilder: (page) => slugify(page.properties.get("Category")), + frontmatterBuilder: (page) => ({ + id: page.meta.id, + url: page.meta.url, + title: page.meta.title, + category: page.properties.get("Category") + }), + }, databases: { "fe9836a9-6557-4f17-8adb-a93d2584f35f": { - parentCategory: "cfmm/", sorts: [ { property: "Scope", @@ -130,9 +136,23 @@ const config: SyncConfig = { direction: "ascending", }, ], - properties: { - category: "scope", - include: ["Name", "Scope", "Cluster", "Journey Stage", "Summary"], + renderAs: "pages+views", + pages: { + destinationDirBuilder: (page) => slugify(page.properties.get("Scope")), + frontmatterBuilder: (page) => ({ + id: page.meta.id, + url: page.meta.url, + title: page.meta.title, + cluster: page.properties.get("Cluster") + }), + }, + views: [ + { + title: "By Scope", + properties: { + groupBy: "Scope", + include: ["Name", "Scope", "Cluster", "Summary"], + }, }, }, }, @@ -146,10 +166,20 @@ async function main() { ); } - await sync(notionApiToken, config); + rimraf.sync("docs/!(README.md)**/*"); + + // change into the docs dir, this simplifies handling relative paths + process.chdir("docs/"); + + const rendered = await sync(notionApiToken, config); + + // do something with the rendered index, e.g. writing it to a file or building a nav structure } -main(); +main().catch((e) => { + console.error(e); + process.exit(1); +}); ``` ## Credits, Related Projects and Inspiration diff --git a/jest.config.js b/jest.config.js index bd27b33..693577e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,12 @@ module.exports = { transform: { "^.+\\.ts?$": "ts-jest", + "^.+\\markdown-table.js?$": "ts-jest", + }, + globals: { + 'ts-jest': { + isolatedModules: true + } }, testEnvironment: "node", testRegex: "./src/.*\\.(test|spec)?\\.(ts|ts)$", diff --git a/package.json b/package.json index 98696c2..7d64c0f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.6.0", + "version": "0.11.1", "name": "@meshcloud/notion-markdown-cms", "engines": { "node": ">=14" @@ -40,4 +40,4 @@ "mime-types": "^2.1.32", "slugify": "^1.6.0" } -} \ No newline at end of file +} diff --git a/src/AssetWriter.ts b/src/AssetWriter.ts index 6d01ff5..d9dcdf9 100644 --- a/src/AssetWriter.ts +++ b/src/AssetWriter.ts @@ -1,27 +1,25 @@ -import { promises as fs } from 'fs'; -import got from 'got'; -import { KeyvFile } from 'keyv-file'; -import * as mime from 'mime-types'; - -import { RenderingLoggingContext } from './logger'; +import { promises as fs } from "fs"; +import got from "got"; +import { KeyvFile } from "keyv-file"; +import * as mime from "mime-types"; +import { RenderingContextLogger } from "./RenderingContextLogger"; const cache = new KeyvFile({ filename: ".cache/keyv.json", }); export class AssetWriter { - constructor(readonly dir: string) {} + constructor( + private readonly dir: string, + private readonly logger: RenderingContextLogger + ) {} async store(name: string, buffer: Buffer) { await fs.mkdir(this.dir, { recursive: true }); await fs.writeFile(`${this.dir}/${name}`, buffer); } - async download( - url: string, - fileName: string, - context: RenderingLoggingContext - ) { + async download(url: string, fileName: string) { // the got http lib promises to do proper user-agent compliant http caching // see https://github.com/sindresorhus/got/blob/main/documentation/cache.md @@ -35,7 +33,7 @@ export class AssetWriter { const imageFile = fileName + "." + ext; const cacheInfo = response.isFromCache ? " (from cache)" : ""; - context.info(`downloading ${imageFile}` + cacheInfo); + this.logger.info(`downloading ${imageFile}` + cacheInfo); await this.store(imageFile, response.rawBody); return imageFile; diff --git a/src/BlockRenderer.ts b/src/BlockRenderer.ts index 018e8be..6f98ea9 100644 --- a/src/BlockRenderer.ts +++ b/src/BlockRenderer.ts @@ -1,12 +1,20 @@ -import { RichText } from '@notionhq/client/build/src/api-types'; +import { RichText } from "@notionhq/client/build/src/api-types"; -import { AssetWriter } from './AssetWriter'; +import { AssetWriter } from "./AssetWriter"; import { - Block, Emoji, ExternalFile, ExternalFileWithCaption, File, FileWithCaption, ImageBlock -} from './Blocks'; -import { DeferredRenderer } from './DeferredRenderer'; -import { RenderingLoggingContext } from './logger'; -import { RichTextRenderer } from './RichTextRenderer'; + Block, + Emoji, + ExternalFile, + ExternalFileWithCaption, + File, + FileWithCaption, + ImageBlock, +} from "./Blocks"; +import { DeferredRenderer } from "./DeferredRenderer"; +import { RenderingContextLogger } from "./RenderingContextLogger"; +import { RichTextRenderer } from "./RichTextRenderer"; +import { RenderingContext } from "./RenderingContext"; +import { LinkRenderer } from "./LinkRenderer"; const debug = require("debug")("blocks"); @@ -17,14 +25,14 @@ export interface BlockRenderResult { export class BlockRenderer { constructor( private readonly richText: RichTextRenderer, - private readonly deferredRenderer: DeferredRenderer + private readonly deferredRenderer: DeferredRenderer, + private readonly link: LinkRenderer ) {} async renderBlock( block: Block, - assets: AssetWriter, - context: RenderingLoggingContext - ): Promise { + context: RenderingContext + ): Promise { const renderMarkdown = async (text: RichText[]) => { return await this.richText.renderMarkdown(text, context); }; @@ -63,7 +71,7 @@ export class BlockRenderer { }; case "image": return { - lines: await this.renderImage(block, assets, context), + lines: await this.renderImage(block, context.assetWriter), }; case "quote": { // it's legal for a notion block to be cmoposed of multiple lines @@ -85,7 +93,7 @@ export class BlockRenderer { case "callout": { // render emoji as bold, this enables css to target it as `blockquote > strong:first-child` const content = - `**${this.renderIcon(block.callout.icon, context)}** ` + + `**${this.renderIcon(block.callout.icon, context.logger)}** ` + (await renderMarkdown(block.callout.text)); return { @@ -96,12 +104,27 @@ export class BlockRenderer { return { lines: "---" }; case "child_database": const msg = `\n`; - const db = await this.deferredRenderer.renderChildDatabase(block.id); + const db = await this.deferredRenderer.renderChildDatabase( + block.id, + context.linkResolver + ); return { lines: msg + db.markdown }; + case "synced_block": + // nothing to render, only the contents of the synced block are relevant + // however, these are children nöpcl, and thus retrieved by recursion in RecusivveBodyRenderer + return null; + case "bookmark": + // render caption (if provided) as a link name + const caption = block.bookmark.caption || []; + let title = block.bookmark.url; + if (caption.length > 0) + title = await this.richText.renderPlainText(caption); + return { + lines: this.link.renderUrlLink(title, block.bookmark.url), + }; case "toggle": case "child_page": case "embed": - case "bookmark": case "video": case "file": case "pdf": @@ -112,7 +135,7 @@ export class BlockRenderer { lines: this.renderUnsupported( `unsupported block type: ${block.type}`, block, - context + context.logger ), }; } @@ -120,7 +143,7 @@ export class BlockRenderer { private renderIcon( icon: File | ExternalFile | Emoji, - context: RenderingLoggingContext + logger: RenderingContextLogger ): string { switch (icon.type) { case "emoji": @@ -130,19 +153,15 @@ export class BlockRenderer { return this.renderUnsupported( `unsupported icon type: ${icon.type}`, icon, - context + logger ); } } - async renderImage( - block: ImageBlock, - assets: AssetWriter, - context: RenderingLoggingContext - ): Promise { + async renderImage(block: ImageBlock, assets: AssetWriter): Promise { const url = this.parseUrl(block.image); - const imageFile = await assets.download(url, block.id, context); + const imageFile = await assets.download(url, block.id); // todo: caption support const markdown = `![image-${block.id}](./${imageFile})`; @@ -168,7 +187,7 @@ export class BlockRenderer { private renderUnsupported( msg: string, obj: any, - context: RenderingLoggingContext + context: RenderingContextLogger ): string { context.warn(msg); debug(msg + "\n%O", obj); diff --git a/src/Blocks.ts b/src/Blocks.ts index d99e014..5ac9b7e 100644 --- a/src/Blocks.ts +++ b/src/Blocks.ts @@ -35,6 +35,10 @@ export interface ChildDatabaseBlock extends BlockBase { type: "child_database"; } +export interface SyncedBlock extends BlockBase { + type: "synced_block"; +} + // these are blocks that the notion API client code does not have proper typings for // for unknown reasons they removed types alltogether in v0.4 of the client // https://github.com/makenotion/notion-sdk-js/pulls?q=is%3Apr+is%3Aclosed#issuecomment-927781781 @@ -44,7 +48,8 @@ export type Block = | QuoteBlock | CalloutBlock | DividerBlock - | ChildDatabaseBlock; + | ChildDatabaseBlock + | SyncedBlock; export { Emoji, diff --git a/src/ChildDatabaseRenderer.ts b/src/ChildDatabaseRenderer.ts index 0dccbec..ae52645 100644 --- a/src/ChildDatabaseRenderer.ts +++ b/src/ChildDatabaseRenderer.ts @@ -1,56 +1,73 @@ -import { Client } from '@notionhq/client/build/src'; -import { Page } from '@notionhq/client/build/src/api-types'; - -import { SyncConfig } from './'; -import { lookupDatabaseConfig } from './config'; -import { Database } from './Database'; -import { DatabaseTableRenderer } from './DatabaseTableRenderer'; -import { DatabaseViewRenderer } from './DatabaseViewRenderer'; -import { DeferredRenderer } from './DeferredRenderer'; -import { RenderDatabasePageTask } from './RenderDatabasePageTask'; -import { DatabaseConfig, DatabaseConfigRenderPages, DatabaseConfigRenderTable } from './SyncConfig'; +import { Page } from "@notionhq/client/build/src/api-types"; + +import { SyncConfig } from "./"; +import { lookupDatabaseConfig } from "./config"; +import { Database } from "./Database"; +import { DatabaseViewRenderer } from "./DatabaseViewRenderer"; +import { DeferredRenderer } from "./DeferredRenderer"; +import { NotionApiFacade } from "./NotionApiFacade"; +import { PageLinkResolver } from "./PageLinkResolver"; +import { RenderDatabasePageTask } from "./RenderDatabasePageTask"; +import { + DatabaseConfig, + DatabaseConfigRenderPages, + DatabaseConfigRenderTable, +} from "./SyncConfig"; const debug = require("debug")("child-database"); export class ChildDatabaseRenderer { constructor( private readonly config: SyncConfig, - private readonly publicApi: Client, + private readonly publicApi: NotionApiFacade, private readonly deferredRenderer: DeferredRenderer, - private readonly tableRenderer: DatabaseTableRenderer, private readonly viewRenderer: DatabaseViewRenderer - ) { } + ) {} - async renderChildDatabase(databaseId: string): Promise { + async renderChildDatabase( + databaseId: string, + linkResolver: PageLinkResolver + ): Promise { const dbConfig = lookupDatabaseConfig(this.config, databaseId); // no view was defined for this database, render as a plain inline table const allPages = await this.fetchPages(databaseId, dbConfig); - const renderPages = dbConfig.renderAs === "pages+views" + const renderPages = dbConfig.renderAs === "pages+views"; - debug("rendering child database " + databaseId + " as " + dbConfig.renderAs); + debug( + "rendering child database " + databaseId + " as " + dbConfig.renderAs + ); if (renderPages) { const pageConfig = dbConfig as DatabaseConfigRenderPages; const entries = await this.queuePageRendering(allPages, pageConfig); - const markdown = await this.viewRenderer.renderViews(entries, dbConfig as DatabaseConfigRenderPages); + const markdown = await this.viewRenderer.renderViews( + entries, + dbConfig as DatabaseConfigRenderPages, + linkResolver + ); return { config: dbConfig, entries, markdown, }; - } - - const entries = await this.queueEntryRendering(allPages, dbConfig); - const markdown = this.tableRenderer.renderTable(entries); + } else { + // render table + const entries = await this.queueEntryRendering(allPages, dbConfig); + const markdown = this.viewRenderer.renderViews( + entries, + dbConfig, + linkResolver + ); - return { - config: dbConfig, - entries, - markdown, - }; + return { + config: dbConfig, + entries, + markdown, + }; + } } private async queueEntryRendering( @@ -81,22 +98,14 @@ export class ChildDatabaseRenderer { databaseId: string, dbConfig: DatabaseConfig ): Promise { - const db = await this.publicApi.databases.retrieve({ - database_id: databaseId, - }); + const db = await this.publicApi.retrieveDatabase(databaseId); - const allPages = await this.publicApi.databases.query({ + const allPages = await this.publicApi.queryDatabase({ database_id: db.id, sorts: dbConfig.sorts, page_size: 100, - }); // todo: paging - - if (allPages.next_cursor) { - throw new Error( - `Paging not implemented, db ${db.id} has more than 100 entries` - ); - } + }); - return allPages.results; + return allPages; } } diff --git a/src/DatabaseEntryRenderer.ts b/src/DatabaseEntryRenderer.ts index 0b0819f..0943080 100644 --- a/src/DatabaseEntryRenderer.ts +++ b/src/DatabaseEntryRenderer.ts @@ -1,25 +1,22 @@ import { Page } from "@notionhq/client/build/src/api-types"; +import { DatabaseConfigRenderTable } from "."; import { PropertiesParser } from "./PropertiesParser"; import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; -import { DatabaseConfig } from "./SyncConfig"; export class DatabaseEntryRenderer { constructor(private readonly propertiesParser: PropertiesParser) {} async renderEntry( page: Page, - config: DatabaseConfig + config: DatabaseConfigRenderTable ): Promise { - const props = await this.propertiesParser.parseProperties(page, config); + const props = await this.propertiesParser.parsePageProperties(page); + const frontmatterProperties = config.entries?.frontmatterBuilder(props); return { - id: page.id, - url: page.url, - properties: { - keys: props.keys, - values: props.properties, - }, + properties: props, + frontmatter: frontmatterProperties, }; } } diff --git a/src/DatabasePageMeta.ts b/src/DatabasePageMeta.ts index 9714e48..12496fb 100644 --- a/src/DatabasePageMeta.ts +++ b/src/DatabasePageMeta.ts @@ -6,9 +6,6 @@ import { DatabaseEntryMeta } from './DatabaseEntryMeta'; */ export interface DatabasePageMeta extends DatabaseEntryMeta { title: string; - category: string; - order?: number; - layout?: string; } diff --git a/src/DatabasePageProperties.ts b/src/DatabasePageProperties.ts index a559c4d..f0f39b3 100644 --- a/src/DatabasePageProperties.ts +++ b/src/DatabasePageProperties.ts @@ -1,4 +1,4 @@ -import { DatabasePageMeta } from './DatabasePageMeta'; +import { DatabasePageMeta } from "./DatabasePageMeta"; export interface DatabasePageProperties { /** @@ -7,12 +7,7 @@ export interface DatabasePageProperties { meta: DatabasePageMeta; /** - * A mapping of property object keys -> property values + * A mapping of Notion property names -> parsed property values */ - values: Record; - - /** - * A mapping of Notion API property names -> property object keys - */ - keys: Map; + properties: Map; } diff --git a/src/DatabasePageRenderer.ts b/src/DatabasePageRenderer.ts index edbee3c..d3ea572 100644 --- a/src/DatabasePageRenderer.ts +++ b/src/DatabasePageRenderer.ts @@ -1,15 +1,14 @@ -import * as fsc from 'fs'; +import * as fsc from "fs"; -import { Page } from '@notionhq/client/build/src/api-types'; +import { Page } from "@notionhq/client/build/src/api-types"; -import { AssetWriter } from './AssetWriter'; -import { FrontmatterRenderer } from './FrontmatterRenderer'; -import { RenderingLoggingContext } from './logger'; -import { PropertiesParser } from './PropertiesParser'; -import { RecursiveBodyRenderer } from './RecursiveBodyRenderer'; -import { RenderDatabasePageTask as RenderDatabasePageTask } from './RenderDatabasePageTask'; -import { slugify } from './slugify'; -import { DatabaseConfigRenderPages } from './SyncConfig'; +import { FrontmatterRenderer } from "./FrontmatterRenderer"; +import { PropertiesParser } from "./PropertiesParser"; +import { RecursiveBodyRenderer } from "./RecursiveBodyRenderer"; +import { RenderDatabasePageTask as RenderDatabasePageTask } from "./RenderDatabasePageTask"; +import { DatabaseConfigRenderPages } from "./SyncConfig"; +import { slugify } from "./slugify"; +import { RenderingContext } from "./RenderingContext"; const fs = fsc.promises; @@ -24,49 +23,50 @@ export class DatabasePageRenderer { page: Page, config: DatabaseConfigRenderPages ): Promise { - const props = await this.propertiesParser.parsePageProperties(page, config); + const props = await this.propertiesParser.parsePageProperties(page); - const categorySlug = slugify(props.meta.category); - const destDir = `${config.outDir}/${categorySlug}`; - - const nameSlug = slugify(props.meta.title); - const file = `${destDir}/${nameSlug}.md`; + const destDir = config.pages.destinationDirBuilder(props); + const filenameBuilder = + config.pages.filenameBuilder || ((x) => slugify(x.meta.title)); + const file = `${destDir}/${filenameBuilder(props)}.md`; // Design: all the rendering performance could be greatly enhanced writing directly to output streams instead // of concatenating all in memory. OTOH naively concatenatic strings is straightforward, easier to debug and rendering // performance probably not the bottleneck compared to the IO cost of notion API invocations. + const frontmatterProperties = config.pages.frontmatterBuilder(props); return { - id: page.id, file, + frontmatter: frontmatterProperties, properties: props, render: async () => { - const context = new RenderingLoggingContext(page.url, file); - + + const context = new RenderingContext(page.url, file) + if (page.archived) { - context.warn(`page is arvhied`); + // have to skip rendering archived pages as attempting to retrieve the block will result in a HTTP 404 + context.logger.warn(`page is archived - skipping`); + + return; } try { - const assetWriter = new AssetWriter(destDir); - - const frontmatter = this.frontmatterRenderer.renderFrontmatter(props); + const frontmatter = this.frontmatterRenderer.renderFrontmatter(frontmatterProperties); const body = await this.bodyRenderer.renderBody( page, - assetWriter, context ); await fs.mkdir(destDir, { recursive: true }); await fs.writeFile(file, frontmatter + body); - context.complete(); + context.logger.complete(); } catch (error) { // While catch-log-throw is usually an antipattern, it is the renderes job to orchestrate the rendering // job with concerns like logging and writing to the outside world. Hence this place is appropriate. // We need to throw the error here so that the rendering process can crash with a proper error message, since // an error at this point here is unrecoverable. - context.error(error); + context.logger.error(error); throw error; } }, diff --git a/src/DatabaseTableRenderer.ts b/src/DatabaseTableRenderer.ts deleted file mode 100644 index ff8c212..0000000 --- a/src/DatabaseTableRenderer.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as markdownTable from "./markdown-table"; -import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; - -export class DatabaseTableRenderer { - public renderTable(entries: RenderDatabaseEntryTask[]): string { - const table: any[][] = []; - - for (const page of entries) { - if (table.length === 0) { - const headers = Array.from(page.properties.keys.keys()); - table[0] = headers; - } - - const cols = Array.from(page.properties.keys.values()).map((c, i) => - DatabaseTableRenderer.escapeTableCell( - page.properties.values[c] - ) - ); - - table.push(cols); - } - - return markdownTable.markdownTable(table); - } - - static escapeTableCell(content: string | number | any): string { - // markdown table cells do not support newlines, however we can insert
elements instead - if (typeof content === "string") { - return content.replace(/\n/g, "
"); - } - - return content.toString(); - } -} diff --git a/src/DatabaseViewRenderer.spec.ts b/src/DatabaseViewRenderer.spec.ts new file mode 100644 index 0000000..be7f26b --- /dev/null +++ b/src/DatabaseViewRenderer.spec.ts @@ -0,0 +1,92 @@ +import { DatabaseViewRenderer } from "./DatabaseViewRenderer"; +import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; + +describe("DatabaseViewRenderer", () => { + test("renders with grouping", async () => { + const linkRenderer = {}; + const sut = new DatabaseViewRenderer(linkRenderer as any); + + const entries: RenderDatabaseEntryTask[] = [ + { + properties: { + meta: { id: "a", title: " A", url: "http://a" }, + properties: new Map([ + ["Name", "A"], + ["Foo", "Bar"], + ]), + }, + }, + { + properties: { + meta: { id: "b", title: " B", url: "http://b" }, + properties: new Map([ + ["Name", "B"], + ["Foo", "Baz"], + ]), + }, + }, + ]; + + const result = sut.renderViews(entries, { + renderAs: "table", + views: [ + { + title: "By Foo", + properties: { + groupBy: "Foo", + }, + }, + ], + }); + + const expected = `## By Foo - Bar + +| Name | Foo | +| ---- | --- | +| A | Bar | + +## By Foo - Baz + +| Name | Foo | +| ---- | --- | +| B | Baz |`; + expect(result).toEqual(expected); + }); + + test("filters columns", async () => { + const linkRenderer = {}; + const sut = new DatabaseViewRenderer(linkRenderer as any); + + const entries: RenderDatabaseEntryTask[] = [ + { + properties: { + meta: { id: "a", title: " A", url: "http://a" }, + properties: new Map([ + ["Name", "A"], + ["Foo", "Bar"], + ["Alice", "Bob"], + ]), + }, + }, + ]; + + const result = sut.renderViews(entries, { + renderAs: "table", + views: [ + { + title: "By Foo", + properties: { + include: ["Name", "Foo"], + }, + }, + ], + }); + + const expected = `## By Foo + +| Name | Foo | +| ---- | --- | +| A | Bar |`; + expect(result).toEqual(expected); + }); +}); diff --git a/src/DatabaseViewRenderer.ts b/src/DatabaseViewRenderer.ts index 2cf5cf8..16cc20e 100644 --- a/src/DatabaseViewRenderer.ts +++ b/src/DatabaseViewRenderer.ts @@ -1,73 +1,83 @@ -import { DatabaseTableRenderer } from './DatabaseTableRenderer'; -import { LinkRenderer } from './LinkRenderer'; -import * as markdownTable from './markdown-table'; -import { PropertiesParser } from './PropertiesParser'; -import { RenderDatabasePageTask } from './RenderDatabasePageTask'; -import { DatabaseConfigRenderPages, DatabaseView } from './SyncConfig'; - -const debug = require("debug")("database-views"); +import { DatabaseConfigRenderTable } from "."; +import { LinkRenderer } from "./LinkRenderer"; +import * as markdownTable from "./markdown-table"; +import { PageLinkResolver } from "./PageLinkResolver"; +import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; +import { RenderDatabasePageTask } from "./RenderDatabasePageTask"; +import { DatabaseConfigRenderPages, DatabaseView } from "./SyncConfig"; // todo: name afte what it renders, not to where export class DatabaseViewRenderer { constructor(private readonly linkRenderer: LinkRenderer) {} - public renderViews(entries: RenderDatabasePageTask[], config: DatabaseConfigRenderPages): string { - const views = config.views?.map((view) => { - const propKeys = entries[0].properties.keys; - const propKey = propKeys.get(view.properties.groupBy); + public renderViews( + entries: (RenderDatabasePageTask | RenderDatabaseEntryTask)[], + config: DatabaseConfigRenderPages | DatabaseConfigRenderTable, + linkResolver: PageLinkResolver + ): string { + const configuredViews = config.views || [{}]; - if (!propKey) { - const msg = `Could not render view ${view.title}, groupBy property ${view.properties.groupBy} not found`; - debug(msg + "%O", view); - throw new Error(msg); - } + const views = configuredViews?.map((view) => { + const groupByProperty = view?.properties?.groupBy; - const grouped = new Array( - ...groupBy(entries, (p) => p.properties.values[propKey]) - ); + if (!groupByProperty) { + return this.renderView(entries, null, view, linkResolver); + } else { + const grouped = new Array( + ...groupBy(entries, (p) => + p.properties.properties.get(groupByProperty) + ) + ); - return grouped - .map(([key, pages]) => this.renderView(pages, key, view)) - .join("\n\n"); + return grouped + .map(([key, pages]) => this.renderView(pages, key, view, linkResolver)) + .join("\n\n"); + } }); return views?.join("\n\n") || ""; } - public renderView( - pages: RenderDatabasePageTask[], - titleAppendix: string, - view: DatabaseView + private renderView( + pages: (RenderDatabasePageTask | RenderDatabaseEntryTask)[], + titleAppendix: string | null, + view: DatabaseView, + linkResolver: PageLinkResolver ): string { - // todo: handle empty page - const props = pages[0].properties; + if (!pages[0]) { + return ""; + } + const pageProps = pages[0].properties; - const keys = PropertiesParser.filterIncludedKeys( - props.keys, - view.properties.include, - ); + const includedProps = + view?.properties?.include || Array.from(pageProps.properties.keys()); const table: any[][] = []; - const headers = Array.from(keys.keys()); + const headers = includedProps; table[0] = headers; - const cols = Array.from(keys.values()); + const cols = includedProps; pages.forEach((r) => table.push( cols.map((c, i) => { - const content = DatabaseTableRenderer.escapeTableCell(r.properties.values[c]); - return i == 0 - ? this.linkRenderer.renderPageLink(content, r) // make the first cell a relative link to the page + const content = escapeTableCell(r.properties.properties.get(c)); + return i == 0 && isRenderPageTask(r) + ? this.linkRenderer.renderPageLink(content, r, linkResolver) // make the first cell a relative link to the page : content; }) ) ); - return ( - `## ${view.title} - ${titleAppendix}\n\n` + - markdownTable.markdownTable(table) - ); + const tableMd = markdownTable.markdownTable(table); + if (view.title) { + const formattedTitle = [view.title, titleAppendix] + .filter((x) => !!x) + .join(" - "); + return `## ${formattedTitle}\n\n` + tableMd; + } else { + return tableMd; + } } } @@ -98,3 +108,18 @@ export function groupBy( }); return map; } + +function escapeTableCell(content: string | number | any): string { + // markdown table cells do not support newlines, however we can insert
elements instead + if (typeof content === "string") { + return content.replace(/\n/g, "
"); + } + + return content?.toString() || ""; +} + +function isRenderPageTask( + task: RenderDatabasePageTask | RenderDatabaseEntryTask +): task is RenderDatabasePageTask { + return (task as RenderDatabasePageTask).render !== undefined; +} diff --git a/src/DeferredRenderer.ts b/src/DeferredRenderer.ts index 331e70f..228e9f1 100644 --- a/src/DeferredRenderer.ts +++ b/src/DeferredRenderer.ts @@ -1,14 +1,18 @@ -import { Page } from '@notionhq/client/build/src/api-types'; - -import { ChildDatabaseRenderer } from './ChildDatabaseRenderer'; -import { Database } from './Database'; -import { DatabaseEntryRenderer } from './DatabaseEntryRenderer'; -import { DatabasePageRenderer } from './DatabasePageRenderer'; -import { RenderDatabaseEntryTask } from './RenderDatabaseEntryTask'; -import { RenderDatabasePageTask as RenderDatabasePageTask } from './RenderDatabasePageTask'; -import { RenderedDatabaseEntry } from './RenderedDatabaseEntry'; -import { RenderedDatabasePage } from './RenderedDatabasePage'; -import { DatabaseConfigRenderPages, DatabaseConfigRenderTable } from './SyncConfig'; +import { Page } from "@notionhq/client/build/src/api-types"; + +import { ChildDatabaseRenderer } from "./ChildDatabaseRenderer"; +import { Database } from "./Database"; +import { DatabaseEntryRenderer } from "./DatabaseEntryRenderer"; +import { DatabasePageRenderer } from "./DatabasePageRenderer"; +import { PageLinkResolver } from "./PageLinkResolver"; +import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; +import { RenderDatabasePageTask as RenderDatabasePageTask } from "./RenderDatabasePageTask"; +import { RenderedDatabaseEntry } from "./RenderedDatabaseEntry"; +import { RenderedDatabasePage } from "./RenderedDatabasePage"; +import { + DatabaseConfigRenderPages, + DatabaseConfigRenderTable, +} from "./SyncConfig"; const debug = require("debug")("rendering"); @@ -32,8 +36,11 @@ export class DeferredRenderer { this.entryRenderer = entryRenderer; } - public async renderChildDatabase(databaseId: string): Promise { - return await this.dbRenderer.renderChildDatabase(databaseId); + public async renderChildDatabase( + databaseId: string, + linkResolver: PageLinkResolver + ): Promise { + return await this.dbRenderer.renderChildDatabase(databaseId, linkResolver); } public async renderPage( @@ -63,7 +70,7 @@ export class DeferredRenderer { // entries are complete the moment they are retrieved, there's no more deferred processing necessary on them // also there should be no duplicate entries, so we do not cache/lookup any of them - if (config.entries.emitToIndex) { + if (task.frontmatter) { this.renderedEntries.push(task); } @@ -100,15 +107,15 @@ export class DeferredRenderer { ).map((x) => ({ file: x.file, meta: x.properties.meta, - properties: x.properties.values, + frontmatter: x.frontmatter, })); const entries: RenderedDatabaseEntry[] = this.renderedEntries.map((x) => ({ meta: { - id: x.id, - url: x.url, + id: x.properties.meta.id, + url: x.properties.meta.url, }, - properties: x.properties.values, + frontmatter: x.frontmatter, })); return pages.concat(entries); diff --git a/src/FrontmatterRenderer.ts b/src/FrontmatterRenderer.ts index 38c7b21..008c4d3 100644 --- a/src/FrontmatterRenderer.ts +++ b/src/FrontmatterRenderer.ts @@ -1,16 +1,9 @@ import * as yaml from 'js-yaml'; -import { DatabasePageProperties } from './DatabasePageProperties'; - export class FrontmatterRenderer { constructor() {} - public renderFrontmatter(props: DatabasePageProperties) { - const obj = { - ...props.meta, - properties: props.values, - }; - + public renderFrontmatter(obj: Record) { const frontmatter = `---\n${yaml.dump(obj)}---\n\n`; return frontmatter; diff --git a/src/LinkRenderer.spec.ts b/src/LinkRenderer.spec.ts index b6a347b..938ddc3 100644 --- a/src/LinkRenderer.spec.ts +++ b/src/LinkRenderer.spec.ts @@ -1,19 +1,17 @@ import { LinkRenderer } from './LinkRenderer'; +import { PageLinkResolver } from './PageLinkResolver'; import { RenderDatabasePageTask } from './RenderDatabasePageTask'; describe("LinkRenderer", () => { - const config = { - outDir: "out/", - }; - + test("renderPageLink strips outDir from link", async () => { - const sut = new LinkRenderer(config as any); + const resolver = new PageLinkResolver("out"); + const sut = new LinkRenderer(); const page: Partial = { - id: "id", file: "out/test.md", }; - const link = sut.renderPageLink("text", page as any); - expect(link).toEqual("[text](test.md)"); + const link = sut.renderPageLink("text", page as any, resolver); + expect(link).toEqual("[text](./test.md)"); }); }); diff --git a/src/LinkRenderer.ts b/src/LinkRenderer.ts index e627bf1..978ae38 100644 --- a/src/LinkRenderer.ts +++ b/src/LinkRenderer.ts @@ -1,16 +1,20 @@ -import { SyncConfig } from './'; -import { RenderDatabasePageTask } from './RenderDatabasePageTask'; +import { PageLinkResolver } from "./PageLinkResolver"; +import { RenderDatabasePageTask } from "./RenderDatabasePageTask"; export class LinkRenderer { - constructor(private readonly config: SyncConfig) {} + constructor() {} renderUrlLink(text: string, url: string): string { return `[${text}](${url})`; } - renderPageLink(text: string, page: RenderDatabasePageTask): string { - const url = page.file.substring(this.config.outDir.length); + renderPageLink( + text: string, + toPage: RenderDatabasePageTask, + linkResolver: PageLinkResolver + ): string { + const link = linkResolver.resolveRelativeLinkTo(toPage.file); - return this.renderUrlLink(text, url); + return this.renderUrlLink(text, link); } } diff --git a/src/MentionedPageRenderer.ts b/src/MentionedPageRenderer.ts index fc0a3e8..7be6c59 100644 --- a/src/MentionedPageRenderer.ts +++ b/src/MentionedPageRenderer.ts @@ -1,13 +1,14 @@ -import { APIErrorCode, Client } from '@notionhq/client'; +import { APIErrorCode } from '@notionhq/client'; import { SyncConfig } from './'; import { lookupDatabaseConfig } from './config'; import { DeferredRenderer } from './DeferredRenderer'; +import { NotionApiFacade } from './NotionApiFacade'; import { RenderDatabasePageTask } from './RenderDatabasePageTask'; export class MentionedPageRenderer { constructor( - readonly publicApi: Client, + readonly publicApi: NotionApiFacade, readonly deferredRenderer: DeferredRenderer, readonly config: SyncConfig ) {} @@ -54,7 +55,7 @@ export class MentionedPageRenderer { private async tryFindPage(pageId: string) { try { - return await this.publicApi.pages.retrieve({ page_id: pageId }); + return await this.publicApi.retrievePage( pageId); } catch (error: any) { if (error.code === APIErrorCode.ObjectNotFound) { // this is an expected error, e.g. we do not have access to the page source @@ -64,7 +65,7 @@ export class MentionedPageRenderer { } } } - + private formatMentionedPage(pageId: string, mentionPlaintext: string) { const formattedId = pageId.replace(/-/g, ""); return `mentioned page '${mentionPlaintext}' with url https://notion.so/${formattedId}`; diff --git a/src/NotionApiFacade.ts b/src/NotionApiFacade.ts new file mode 100644 index 0000000..721c2d2 --- /dev/null +++ b/src/NotionApiFacade.ts @@ -0,0 +1,157 @@ +import { + APIErrorCode, + APIResponseError, + Client, + RequestTimeoutError, + UnknownHTTPResponseError, +} from "@notionhq/client"; +import { DatabasesQueryParameters } from "@notionhq/client/build/src/api-endpoints"; + +const debug = require("debug")("notion-api"); + +/** + * A common facade for interaction with notion API and handling common concerns (esp. retry on 502/rate limits). + * + * Note: considered splitting this up by consumer, but + */ +export class NotionApiFacade { + private readonly client: Client; + + private readonly stats = { + totalRequests: 0, + totalRetries: 0, + retriesByErrorCode: new Map(), + }; + + constructor(notionApiToken: string) { + this.client = new Client({ + auth: notionApiToken, + }); + } + + async retrieveDatabase(databaseId: string) { + return await this.withRetry(async () => { + return this.client.databases.retrieve({ + database_id: databaseId, + }); + }); + } + + async queryDatabase(query: DatabasesQueryParameters) { + const results = []; + + let next_cursor: string | null = null; + + do { + const response = await this.withRetry( + async () => + await this.client.databases.query({ + ...query, + start_cursor: next_cursor || undefined, + }) + ); + + results.push(...response.results); + + next_cursor = response.next_cursor; + } while (next_cursor); + + return results; + } + + async retrievePage(pageId: string) { + return await this.withRetry( + async () => await this.client.pages.retrieve({ page_id: pageId }) + ); + } + + async listBlockChildren(blockId: string) { + const results = []; + + let next_cursor: string | null = null; + + do { + const response = await this.withRetry( + async () => + await this.client.blocks.children.list({ + block_id: blockId, + start_cursor: next_cursor || undefined, + }) + ); + + results.push(...response.results); + + next_cursor = response.next_cursor; + } while (next_cursor); + + return results; + } + + printStats() { + console.log("Notion API request statistics", this.stats); + } + + private async withRetry( + f: () => Promise, + maxRetries: number = 3, + retriableApiErrorCodes: APIErrorCode[] = [ + APIErrorCode.ServiceUnavailable, + APIErrorCode.RateLimited, + ], + retriableUnknownHTTPStatusCodes: number[] = [502] + ): Promise { + let lastError: any; + + for (let i = 1; i <= maxRetries; i++) { + try { + this.stats.totalRequests++; + return await f(); + } catch (error: any) { + lastError = error; + + const apiError = APIResponseError.isAPIResponseError(error) && error; + const unknownError = + UnknownHTTPResponseError.isUnknownHTTPResponseError(error) && error; + const timeoutError = + RequestTimeoutError.isRequestTimeoutError(error) && error; + + const isRetriable = + (apiError && retriableApiErrorCodes.includes(error.code)) || + (unknownError && + retriableUnknownHTTPStatusCodes.includes(error.status)) || + timeoutError; + + if (!isRetriable) { + // throw any other error immediately + throw error; + } + + this.stats.totalRetries++; + const key = + (apiError && apiError.code) || + (unknownError && `${unknownError.code}.${unknownError.status}`) || + (timeoutError && `${timeoutError.code}`) || + "unknown"; + + const count = this.stats.retriesByErrorCode.get(key) || 0; + this.stats.retriesByErrorCode.set(key, count + 1); + + debug( + `Notion API request failed with error ${error.code}, ${ + maxRetries - i + } retries left` + ); + + await sleep(1000 * i); // chosen by fair dice roll + } + } + + throw new Error( + `Failed to execute Notion API request, even after ${maxRetries} retries. Original error was ${lastError}` + ); + } +} + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/src/PageLinkResolver.ts b/src/PageLinkResolver.ts new file mode 100644 index 0000000..21406ec --- /dev/null +++ b/src/PageLinkResolver.ts @@ -0,0 +1,19 @@ +import * as path from "path"; + +export class PageLinkResolver { + private readonly absoluteFromDir: string; + + constructor(sourceDir: string) { + this.absoluteFromDir = path.resolve(sourceDir); + } + + resolveRelativeLinkTo(file: string) { + const absoluteToDir = path.resolve(file); + + const relativePath = path.relative(this.absoluteFromDir, absoluteToDir); + + // normalize the rleative path to start with a ./ as that's the markdown convention for relative links + // at least how it's most commonly interpreted (e.g. by textlint) + return relativePath.startsWith(".") ? relativePath : "./" + relativePath; + } +} diff --git a/src/PropertiesParser.spec.ts b/src/PropertiesParser.spec.ts index 860ed8e..511b27b 100644 --- a/src/PropertiesParser.spec.ts +++ b/src/PropertiesParser.spec.ts @@ -1,8 +1,8 @@ -import { Page } from '@notionhq/client/build/src/api-types'; +import { Page } from "@notionhq/client/build/src/api-types"; +import { DatabasePageProperties } from "./DatabasePageProperties"; -import { PropertiesParser } from './PropertiesParser'; -import { RichTextRenderer } from './RichTextRenderer'; -import { DatabaseConfig } from './SyncConfig'; +import { PropertiesParser } from "./PropertiesParser"; +import { RichTextRenderer } from "./RichTextRenderer"; const page: Partial = { id: "123", @@ -33,72 +33,34 @@ const page: Partial = { }; describe("PropertiesParser", () => { - describe("parse", () => { + describe("parsePageProperties", () => { + test("preserves all properties and adds conventional sort with title coming first", async () => { + const sut = new PropertiesParser( + new RichTextRenderer({} as any, {} as any) + ); - test("preserves all properties and adds conventional with no include filter", async () => { - const sut = new PropertiesParser(new RichTextRenderer({} as any, {} as any)); + const result = await sut.parsePageProperties(page as any); - const config: DatabaseConfig = { - outDir: "db/", - renderAs: 'table', - entries: { - emitToIndex: false - } - }; - - const result = await sut.parseProperties(page as any, config); - - const expected = { - category: null, - order: 30, - title: "Terraform", - keys: new Map([ - ["order", "order"], - ["Category", "category"], - ["Name", "name"], - ]), - properties: { - order: 30, - category: "Tools", - name: "Terraform", + const expected: DatabasePageProperties = { + meta: { + id: page.id!!, + url: page.url!!, + title: "Terraform", }, + properties: new Map([ + ["Name", "Terraform"], + ["order", 30], + ["Category", "Tools"], + ]), }; expect(result).toEqual(expected); // explicitly test key ordering - expect(Array.from(result.keys.keys())).toEqual(["Name", "order", "Category"]); - }); - - test("filters according to include filter", async () => { - const sut = new PropertiesParser(new RichTextRenderer({} as any, {} as any)); - - const config: DatabaseConfig = { - outDir: "db/", - renderAs: "table", - properties: { - include: ["Name", "Category"], - }, - entries: { - emitToIndex: false - } - }; - - const result = await sut.parseProperties(page as any, config); - - const expected = { - category: null, - order: 30, - title: "Terraform", - keys: new Map([ - ["Category", "category"], - ["Name", "name"], - ]), - properties: { - category: "Tools", - name: "Terraform", - }, - }; - expect(result).toEqual(expected); + expect(Array.from(result.properties.keys())).toEqual([ + "Name", + "order", + "Category", + ]); }); }); }); diff --git a/src/PropertiesParser.ts b/src/PropertiesParser.ts index b3a5312..333716e 100644 --- a/src/PropertiesParser.ts +++ b/src/PropertiesParser.ts @@ -1,10 +1,8 @@ -import { Page, PropertyValue } from '@notionhq/client/build/src/api-types'; +import { Page, PropertyValue } from "@notionhq/client/build/src/api-types"; -import { DatabasePageProperties } from './DatabasePageProperties'; -import { RenderingLoggingContext } from './logger'; -import { RichTextRenderer } from './RichTextRenderer'; -import { slugify } from './slugify'; -import { DatabaseConfig, DatabaseConfigRenderPages } from './SyncConfig'; +import { DatabasePageProperties } from "./DatabasePageProperties"; +import { RenderingContextLogger } from "./RenderingContextLogger"; +import { RichTextRenderer } from "./RichTextRenderer"; const debug = require("debug")("properties"); @@ -12,131 +10,83 @@ export class PropertiesParser { constructor(private readonly richText: RichTextRenderer) {} public async parsePageProperties( - page: Page, - config: DatabaseConfigRenderPages + page: Page ): Promise { - const { title, category, order, properties, keys } = - await this.parseProperties(page, config); + const { title, properties } = await this.parseProperties(page); if (!title) { throw this.errorMissingRequiredProperty("of type 'title'", page); } - const theCategory = category || config.pages.frontmatter.category.static; - - if (!theCategory) { - throw this.errorMissingRequiredProperty( - config.pages.frontmatter.category.property || "static category", - page - ); - } - return { meta: { id: page.id, url: page.url, - title: title, // notion API always calls it name - category: theCategory, - order: order, - ...config.pages.frontmatter.extra, + title: title, }, - values: properties, - keys: keys, + properties, }; } - public async parseProperties(page: Page, config: DatabaseConfig) { - /** - * Design: we always lookup the properties on the page object itself. - * This way we only parse properties once and avoid any problems coming from - * e.g. category properties being filtered via include filters. - */ - + private async parseProperties(page: Page) { /** * Terminology: * * property: Notion API property name - * key: slugified Notion API property name, used to later build frontmatter * value: Notion API property value */ /** - * A record of key->value + * A record of property->value */ - const properties: Record = {}; - - /** - * A map of proprety -> key - */ - const keys = new Map(); + const properties: Map = new Map(); let title: string | null = null; let titleProperty: string | null = null; - let category: string | null = null; - let order: number | undefined = undefined; - const categoryProperty = - config.renderAs === "pages+views" && - config.pages.frontmatter.category.property; - - const context = new RenderingLoggingContext(page.url); + const context = new RenderingContextLogger(page.url); for (const [name, value] of Object.entries(page.properties)) { const parsedValue = await this.parsePropertyValue(value, context); - - if ( - !config.properties?.include || - config.properties.include.indexOf(name) >= 0 - ) { - const slug = slugify(name); - properties[slug] = parsedValue; - keys.set(name, slug); - } + properties.set(name, parsedValue); if (value.type === "title") { title = parsedValue; titleProperty = name; } - - if (categoryProperty && name === categoryProperty) { - category = parsedValue; - } - - if (name === "order") { - order = parsedValue; - } } - if (!titleProperty) { + if (!title || !titleProperty) { throw this.errorMissingRequiredProperty("of type 'title'", page); } // no explicit ordering specified, so we make sure to put the title property first - const includes = config.properties?.include || [ + const keyOrder = [ titleProperty, - ...Array.from(keys.keys()).filter((x) => x != titleProperty), + ...Array.from(properties.keys()).filter((x) => x != titleProperty), ]; + // maps preserve insertion order + const sortedProperties = new Map(); + keyOrder.forEach(x => sortedProperties.set(x, properties.get(x))); + return { title, - category, - order, - properties, - keys: PropertiesParser.filterIncludedKeys(keys, includes), + properties: sortedProperties, }; } private async parsePropertyValue( value: PropertyValue, - context: RenderingLoggingContext + context: RenderingContextLogger ): Promise { switch (value.type) { case "number": return value.number; case "title": - return await this.richText.renderMarkdown(value.title, context); + return await this.richText.renderPlainText(value.title); case "rich_text": - return await this.richText.renderMarkdown(value.rich_text, context); + return await this.richText.renderPlainText(value.rich_text); case "select": return value.select?.name; case "multi_select": @@ -159,9 +109,10 @@ export class PropertiesParser { return value.last_edited_time; case "last_edited_by": return value.last_edited_by.name; + case "people": + return value.people.map((person) => person.name).join(", "); case "formula": case "rollup": - case "people": case "files": case "checkbox": const notSupported = "unsupported property type: " + value.type; @@ -172,21 +123,6 @@ export class PropertiesParser { } } - public static filterIncludedKeys( - keys: Map, - includes: string[] | undefined - ): Map { - if (!includes) { - return keys; - } - - // Maps iterate in insertion order, so preserve the correct ordering of keys according to includes ordering - const filtered = new Map(); - includes.forEach((i) => filtered.set(i, keys.get(i)!!)); // todo: should probably handle undefined here - - return filtered; - } - private errorMissingRequiredProperty(propertyName: string, page: Page) { // todo: should this use context? const msg = `Page ${page.url} is missing required property ${propertyName}`; diff --git a/src/RecursiveBodyRenderer.ts b/src/RecursiveBodyRenderer.ts index 17ba316..251b9e3 100644 --- a/src/RecursiveBodyRenderer.ts +++ b/src/RecursiveBodyRenderer.ts @@ -1,32 +1,27 @@ -import { Client } from '@notionhq/client'; import { Block, Page } from '@notionhq/client/build/src/api-types'; -import { AssetWriter } from './AssetWriter'; import { BlockRenderer } from './BlockRenderer'; -import { RenderingLoggingContext } from './logger'; +import { NotionApiFacade } from './NotionApiFacade'; +import { RenderingContext } from './RenderingContext'; const debug = require("debug")("body"); export class RecursiveBodyRenderer { constructor( - readonly publicApi: Client, + readonly publicApi: NotionApiFacade, readonly blockRenderer: BlockRenderer - ) { } + ) {} async renderBody( page: Page, - assets: AssetWriter, - context: RenderingLoggingContext, + context: RenderingContext ): Promise { debug("begin rendering body of page " + page.id, page.properties); - const childs = await this.publicApi.blocks.children.list({ - block_id: page.id, - }); + const childs = await this.publicApi.listBlockChildren(page.id); - // todo: paging - const renderChilds = childs.results.map( - async (x) => await this.renderBlock(x, "", assets, context) + const renderChilds = childs.map( + async (x) => await this.renderBlock(x, "", context) ); const blocks = await Promise.all(renderChilds); const body = blocks.join("\n\n"); @@ -39,27 +34,28 @@ export class RecursiveBodyRenderer { async renderBlock( block: Block, indent: string, - assets: AssetWriter, - context: RenderingLoggingContext + context: RenderingContext ): Promise { - const parentBlock = await this.blockRenderer.renderBlock(block, assets, context); - const parentLines = this.indent(parentBlock.lines, indent); + const parentBlock = await this.blockRenderer.renderBlock( + block, + context + ); + const parentLines = parentBlock && this.indent(parentBlock.lines, indent); // due to the way the Notion API is built, we need to recurisvely retrieve child // blocks, see https://developers.notion.com/reference/retrieve-a-block // "If a block contains the key has_children: true, use the Retrieve block children endpoint to get the list of children" const children = block.has_children - ? (await this.publicApi.blocks.children.list({ block_id: block.id })) - .results + ? (await this.publicApi.listBlockChildren(block.id)) : []; - const childIndent = indent + " ".repeat(parentBlock.childIndent || 0); + const childIndent = indent + " ".repeat(parentBlock?.childIndent || 0); const renderChilds = children.map( - async (x) => await this.renderBlock(x, childIndent, assets, context) + async (x) => await this.renderBlock(x, childIndent, context) ); const childLines = await Promise.all(renderChilds); - return [parentLines, ...childLines].join("\n\n"); + return [parentLines, ...childLines].filter((x) => !!x).join("\n\n"); } private indent(content: string, indent: string) { diff --git a/src/RenderDatabaseEntryTask.ts b/src/RenderDatabaseEntryTask.ts index 34d0538..23e5b87 100644 --- a/src/RenderDatabaseEntryTask.ts +++ b/src/RenderDatabaseEntryTask.ts @@ -1,18 +1,7 @@ +import { DatabasePageProperties } from "./DatabasePageProperties"; export interface RenderDatabaseEntryTask { - id: string; - url: string; - properties: { - /** - * A mapping of property object keys -> property values - */ - values: Record; - - /** - * A mapping of Notion API property names -> property object keys - */ - keys: Map; - }; - + properties: DatabasePageProperties + frontmatter?: Record // note: there's nothing to do to render an individual database entry, they are always rendered as part of tables } diff --git a/src/RenderDatabasePageTask.ts b/src/RenderDatabasePageTask.ts index a39b5b3..cda9757 100644 --- a/src/RenderDatabasePageTask.ts +++ b/src/RenderDatabasePageTask.ts @@ -1,8 +1,7 @@ -import { DatabasePageProperties } from './DatabasePageProperties'; +import { RenderDatabaseEntryTask } from "./RenderDatabaseEntryTask"; -export interface RenderDatabasePageTask { - id: string; - file: string; - properties: DatabasePageProperties; - render: () => Promise; +export interface RenderDatabasePageTask extends RenderDatabaseEntryTask { + file: string; + frontmatter: Record + render: () => Promise; } diff --git a/src/RenderedDatabaseEntry.ts b/src/RenderedDatabaseEntry.ts index 0223692..eda71ab 100644 --- a/src/RenderedDatabaseEntry.ts +++ b/src/RenderedDatabaseEntry.ts @@ -2,5 +2,5 @@ import { DatabaseEntryMeta } from './DatabaseEntryMeta'; export interface RenderedDatabaseEntry { meta: DatabaseEntryMeta, - properties: Record; + frontmatter?: Record; } diff --git a/src/RenderedDatabasePage.ts b/src/RenderedDatabasePage.ts index b4acb82..671f5ea 100644 --- a/src/RenderedDatabasePage.ts +++ b/src/RenderedDatabasePage.ts @@ -4,4 +4,5 @@ import { RenderedDatabaseEntry } from './RenderedDatabaseEntry'; export interface RenderedDatabasePage extends RenderedDatabaseEntry { meta: DatabasePageMeta; file: string; + frontmatter: Record; } diff --git a/src/RenderingContext.ts b/src/RenderingContext.ts new file mode 100644 index 0000000..99468e1 --- /dev/null +++ b/src/RenderingContext.ts @@ -0,0 +1,27 @@ +import * as path from "path"; + +import { AssetWriter } from "./AssetWriter"; +import { PageLinkResolver } from "./PageLinkResolver"; +import { RenderingContextLogger as RenderingContextLogger } from "./RenderingContextLogger"; + +/** + * Unit of work for rendering a specific page. + * Note: this is a bit of a service locator, be careful about not breaking SRP + */ +export class RenderingContext { + readonly assetWriter: AssetWriter; + readonly logger: RenderingContextLogger; + readonly linkResolver: PageLinkResolver; + + constructor(notionUrl: string, file: string) { + this.logger = new RenderingContextLogger(notionUrl, file); + + const dir = path.dirname(file); + + // write all assets right next to the page's markdown file + this.assetWriter = new AssetWriter(dir, this.logger); + + // resolve all links relative to the page's markdown file dir + this.linkResolver = new PageLinkResolver(dir); + } +} diff --git a/src/RenderingContextLogger.ts b/src/RenderingContextLogger.ts new file mode 100644 index 0000000..7a085d0 --- /dev/null +++ b/src/RenderingContextLogger.ts @@ -0,0 +1,34 @@ +import * as chalk from "chalk"; +import { performance } from "perf_hooks"; +import { logger } from "./logger"; + + +export class RenderingContextLogger { + private readonly start = performance.now(); + + constructor( + public readonly notionUrl: string, + public readonly file?: string + ) { } + + info(message: string) { + return logger.info(this.garnish(message)); + } + + warn(message: string) { + return logger.warn(this.garnish(message)); + } + + error(err: unknown) { + return logger.error(this.garnish(err as any)); // bah + } + + complete() { + const elapsed = performance.now() - this.start; + this.info("rendered page in " + Math.round(elapsed) + "ms"); + } + + private garnish(message: string) { + return `${message} ${chalk.gray(this.file || this.notionUrl)}`; + } +} diff --git a/src/RichTextRenderer.spec.ts b/src/RichTextRenderer.spec.ts index a6e35cd..34e31f6 100644 --- a/src/RichTextRenderer.spec.ts +++ b/src/RichTextRenderer.spec.ts @@ -1,6 +1,6 @@ import { Annotations, RichText } from '@notionhq/client/build/src/api-types'; +import { RenderingContext } from './RenderingContext'; -import { RenderingLoggingContext } from './logger'; import { RichTextRenderer } from './RichTextRenderer'; function annotations(x: Partial): Annotations { @@ -15,7 +15,7 @@ function annotations(x: Partial): Annotations { }; } -const context = new RenderingLoggingContext(''); +const context = new RenderingContext("", ""); describe("RichTextRenderer", () => { let sut: RichTextRenderer; @@ -143,5 +143,38 @@ describe("RichTextRenderer", () => { expect(result).toEqual("**Hello** \n\tWorld\n"); }); + + test("handles annotated whitespace", async () => { + const text: RichText[] = [ + { + type: "text", + plain_text: "Hello", + text: { + content: "Hello", + }, + annotations: annotations({}), + }, + { + type: "text", + plain_text: " ", + text: { + content: " ", + }, + annotations: annotations({ bold: true, italic: true }), + }, + { + type: "text", + plain_text: "World", + text: { + content: "World", + }, + annotations: annotations({}), + }, + ]; + + const result = await sut.renderMarkdown(text, context); + + expect(result).toEqual("Hello World"); + }); }); }); diff --git a/src/RichTextRenderer.ts b/src/RichTextRenderer.ts index bb15634..eeb0531 100644 --- a/src/RichTextRenderer.ts +++ b/src/RichTextRenderer.ts @@ -1,8 +1,9 @@ -import { RichText } from '@notionhq/client/build/src/api-types'; +import { RichText } from "@notionhq/client/build/src/api-types"; -import { LinkRenderer } from './LinkRenderer'; -import { RenderingLoggingContext } from './logger'; -import { MentionedPageRenderer } from './MentionedPageRenderer'; +import { LinkRenderer } from "./LinkRenderer"; +import { RenderingContextLogger } from "./RenderingContextLogger"; +import { MentionedPageRenderer } from "./MentionedPageRenderer"; +import { RenderingContext } from "./RenderingContext"; const debug = require("debug")("richtext"); @@ -15,12 +16,12 @@ export class RichTextRenderer { ) {} public async renderPlainText(text: RichText[]): Promise { - return text.map((rt) => rt.plain_text).join(" "); + return text.map((rt) => rt.plain_text).join(""); } public async renderMarkdown( text: RichText[], - context: RenderingLoggingContext + context: RenderingContext ): Promise { const result: string[] = []; @@ -35,7 +36,7 @@ export class RichTextRenderer { private async renderMarkdownCode( rt: RichText, - context: RenderingLoggingContext + context: RenderingContext ) { const mod = this.modifier(rt); @@ -44,7 +45,7 @@ export class RichTextRenderer { return this.renderUnsupported( `unsupported rich text type: ${rt.type}`, rt, - context + context.logger ); case "mention": switch (rt.mention.type) { @@ -54,14 +55,14 @@ export class RichTextRenderer { rt.plain_text ); const text = this.wrap(mod, page.properties.meta.title); - return this.linkRenderer.renderPageLink(text, page); + return this.linkRenderer.renderPageLink(text, page, context.linkResolver); case "database": case "date": case "user": return this.renderUnsupported( `unsupported rich text mention type: ${rt.mention.type}`, rt, - context + context.logger ); } case "text": @@ -120,15 +121,22 @@ export class RichTextRenderer { `Content failed parsing the whitespace test: '${content}'` ); } + const [_input, leading, core, trailing] = matchGroups; + if (!core) { + // this can happen e.g. if the formatted content is all whitespace (e.g. a "bold whitespace") + // this is something that can easily happen in a range based RTF editor, but does not make sense in markdown output + return [leading, trailing].join(""); + } + return [leading, modifier, core, reversedMod, trailing].join(""); } private renderUnsupported( msg: string, obj: any, - context: RenderingLoggingContext + context: RenderingContextLogger ): string { context.warn(msg); debug(msg + "\n%O", obj); diff --git a/src/SyncConfig.ts b/src/SyncConfig.ts index 9f36b06..5f96d5e 100644 --- a/src/SyncConfig.ts +++ b/src/SyncConfig.ts @@ -1,4 +1,5 @@ import { Sort } from "@notionhq/client/build/src/api-types"; +import { DatabasePageProperties } from "./DatabasePageProperties"; export interface SyncConfig { /** @@ -14,11 +15,9 @@ export interface SyncConfig { cmsDatabaseId: string; /** - * The output directory where the sync will place pages. - * - * Example: "docs/" + * Configuration options for the rendered pages */ - outDir: string; + pages: PagesConfig; /** * Configuration options for any database encountered while traversing the block graph. @@ -32,66 +31,64 @@ export type DatabaseConfig = | DatabaseConfigRenderTable; export interface DatabaseConfigBase { - /** - * The output directory where the sync will place pages of this database. - * - * Example: docs/mydb" - */ - outDir: string; - /** * Notion API https://developers.notion.com/reference/post-database-query#post-database-query-sort */ sorts?: Sort[]; - /** - * Configuration options for Notion API page properties - */ - properties?: { - /** - * A whitelist of Notion API page property names to include in the markdown page properties. - * Use this to select properties for export and control their ordering in rendered tables. - */ - include?: string[]; - }; - renderAs: "table" | "pages+views"; } export interface DatabaseConfigRenderTable extends DatabaseConfigBase { renderAs: "table"; - entries: { + /** + * Customize rendering of the table as one or multiple views. + * + * If not defined, will render a single view of the table with the Notion database property marked "title" + * as the first column. + * + * An empty array will supress rendering of the table (useful if you want to only emit the table to the index). + */ + views?: DatabaseView[]; + + entries?: { /** - * Controls whether to emit database entries to the index of rendered pages/entries + * Optional: Build frontmatter onject for index entries. + * If omitted, no index entries will be rendered for this table */ - emitToIndex: boolean; + frontmatterBuilder: (props: DatabasePageProperties) => Record; }; } +interface PagesConfig { + /** + * Build frontmatter object + */ + frontmatterBuilder: (props: DatabasePageProperties) => Record; + + /** + * Build the destination directory where to store the page. + * Final path will be $destinationDir/$filename.md + */ + destinationDirBuilder: (props: DatabasePageProperties) => string; + + /** + * Build the filename to store the page. + * Final path will be $destinationDir/$filename.md. + * + * default: slug of the meta.title + */ + filenameBuilder?: (props: DatabasePageProperties) => string; +} + export interface DatabaseConfigRenderPages extends DatabaseConfigBase { renderAs: "pages+views"; + /** - * Add custom data to the page frontmatter + * Configuration options for the rendered pages */ - pages: { - frontmatter: { - category: { - /** - * The Notion API page property that provides an optional sub-category value to use for the markdown page category. - * - * Example: "Cluster" - */ - property?: string; - /** - * A static category value to assign to every page - */ - static?: string; - }; - - extra?: Record; - }; - }; + pages: PagesConfig; /** * Configure "views" to render on the page where the child_database is encountered. @@ -108,10 +105,11 @@ export interface DatabaseConfigRenderPages extends DatabaseConfigBase { */ views: DatabaseView[]; } + export interface DatabaseView { - title: string; - properties: { - groupBy: string; + title?: string; + properties?: { + groupBy?: string; include?: string[]; }; } diff --git a/src/config.ts b/src/config.ts index 67244b3..31f2809 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,23 +10,12 @@ export function lookupDatabaseConfig( databaseId: string | null ): DatabaseConfig { const rootCmsDbConfig: DatabaseConfigRenderPages = { - outDir: config.outDir, renderAs: "pages+views", - pages: { - frontmatter: { - category: { - property: "Category", - }, - }, - }, + pages: config.pages, views: [], }; const defaultDbConfig: DatabaseConfigRenderTable = { - outDir: config.outDir + "/" + databaseId, renderAs: "table", - entries: { - emitToIndex: false, - }, }; const fallbackDbConfig: DatabaseConfig = diff --git a/src/index.ts b/src/index.ts index de86d5b..3469419 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,12 @@ -export { RenderedDatabaseEntry } from './RenderedDatabaseEntry'; -export { RenderedDatabasePage } from './RenderedDatabasePage'; -export { sync } from './sync'; +export { RenderedDatabaseEntry } from "./RenderedDatabaseEntry"; +export { RenderedDatabasePage } from "./RenderedDatabasePage"; +export { sync } from "./sync"; +export { slugify } from "./slugify"; export { - DatabaseConfig, DatabaseConfigRenderPages, DatabaseConfigRenderTable, SyncConfig -} from './SyncConfig'; - + DatabaseConfig, + DatabaseConfigRenderPages, + DatabaseConfigRenderTable, + SyncConfig, +} from "./SyncConfig"; +export { DatabasePageProperties } from "./DatabasePageProperties"; +export { DatabasePageMeta } from "./DatabasePageMeta"; diff --git a/src/logger.ts b/src/logger.ts index 182103a..875cdc2 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,5 +1,4 @@ import * as chalk from 'chalk'; -import { performance } from 'perf_hooks'; const info = (...args: any[]): void => { console.log(chalk.cyan("info"), ...args); @@ -13,38 +12,10 @@ const error = (...args: any[]): void => { console.error(chalk.red("error"), ...args); }; -const logger = { +export const logger = { info, warn, error, }; -export class RenderingLoggingContext { - private readonly start = performance.now(); - constructor( - public readonly notionUrl: string, - public readonly file?: string - ) {} - - info(message: string) { - return logger.info(this.garnish(message)); - } - - warn(message: string) { - return logger.warn(this.garnish(message)); - } - - error(err: unknown) { - return logger.error(this.garnish(err as any)); // bah - } - - complete() { - const elapsed = performance.now() - this.start; - this.info("rendered page in " + Math.round(elapsed) + "ms"); - } - - private garnish(message: string) { - return `${message} ${chalk.gray(this.file || this.notionUrl)}`; - } -} diff --git a/src/sync.ts b/src/sync.ts index a5e5ed5..4bbeda9 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1,42 +1,42 @@ -import { Client } from "@notionhq/client"; - import { BlockRenderer } from "./BlockRenderer"; import { ChildDatabaseRenderer } from "./ChildDatabaseRenderer"; +import { DatabaseEntryRenderer } from "./DatabaseEntryRenderer"; +import { DatabasePageRenderer } from "./DatabasePageRenderer"; import { DatabaseViewRenderer } from "./DatabaseViewRenderer"; import { DeferredRenderer } from "./DeferredRenderer"; import { FrontmatterRenderer } from "./FrontmatterRenderer"; import { LinkRenderer } from "./LinkRenderer"; import { MentionedPageRenderer } from "./MentionedPageRenderer"; -import { DatabasePageRenderer } from "./DatabasePageRenderer"; +import { NotionApiFacade } from "./NotionApiFacade"; +import { PageLinkResolver } from "./PageLinkResolver"; import { PropertiesParser } from "./PropertiesParser"; import { RecursiveBodyRenderer } from "./RecursiveBodyRenderer"; import { RichTextRenderer } from "./RichTextRenderer"; import { SyncConfig } from "./SyncConfig"; -import { DatabaseTableRenderer } from "./DatabaseTableRenderer"; -import { DatabaseEntryRenderer } from "./DatabaseEntryRenderer"; export async function sync(notionApiToken: string, config: SyncConfig) { - const publicApi = new Client({ - auth: notionApiToken, - }); + const publicApi = new NotionApiFacade(notionApiToken); const deferredRenderer = new DeferredRenderer(); const frontmatterRenderer = new FrontmatterRenderer(); - const tableRenderer = new DatabaseTableRenderer(); const mentionedPageRenderer = new MentionedPageRenderer( publicApi, deferredRenderer, config ); - const linkRenderer = new LinkRenderer(config); + const linkRenderer = new LinkRenderer(); const viewRenderer = new DatabaseViewRenderer(linkRenderer); const richTextRenderer = new RichTextRenderer( mentionedPageRenderer, linkRenderer ); const propertiesParser = new PropertiesParser(richTextRenderer); - const blockRenderer = new BlockRenderer(richTextRenderer, deferredRenderer); + const blockRenderer = new BlockRenderer( + richTextRenderer, + deferredRenderer, + linkRenderer + ); const bodyRenderer = new RecursiveBodyRenderer(publicApi, blockRenderer); const entryRenderer = new DatabaseEntryRenderer(propertiesParser); const pageRenderer = new DatabasePageRenderer( @@ -49,17 +49,22 @@ export async function sync(notionApiToken: string, config: SyncConfig) { config, publicApi, deferredRenderer, - tableRenderer, viewRenderer ); deferredRenderer.initialize(dbRenderer, pageRenderer, entryRenderer); // seed it with the root database - await deferredRenderer.renderChildDatabase(config.cmsDatabaseId); + const rootLinkResolver = new PageLinkResolver("."); + await deferredRenderer.renderChildDatabase( + config.cmsDatabaseId, + rootLinkResolver + ); await deferredRenderer.process(); const rendered = deferredRenderer.getRenderedPages(); + publicApi.printStats(); + return rendered; } diff --git a/yarn.lock b/yarn.lock index 3a68c08..f29b531 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,32 +2,32 @@ # yarn lockfile v1 -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== - dependencies: - "@babel/highlight" "^7.16.0" - -"@babel/compat-data@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.0.tgz#ea269d7f78deb3a7826c39a4048eecda541ebdaa" - integrity sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew== - -"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.7.5": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" - integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.0" - "@babel/helper-compilation-targets" "^7.16.0" - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helpers" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" +"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.16.4": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" + integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== + +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.12" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -35,144 +35,127 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.16.0", "@babel/generator@^7.7.2": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" - integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== +"@babel/generator@^7.16.8", "@babel/generator@^7.7.2": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.8" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-compilation-targets@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.0.tgz#01d615762e796c17952c29e3ede9d6de07d235a8" - integrity sha512-S7iaOT1SYlqK0sQaCi21RX4+13hmdmnxIEAnQUB/eh7GeAnRjOUgTYpLkUOiRXzD+yog1JxP0qyAQZ7ZxVxLVg== +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-function-name@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" - integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== - dependencies: - "@babel/helper-get-function-arity" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-get-function-arity@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" - integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-hoist-variables@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" - integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-member-expression-to-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" - integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-module-imports@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" - integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-module-transforms@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" - integrity sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA== - dependencies: - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-replace-supers" "^7.16.0" - "@babel/helper-simple-access" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-optimise-call-expression@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" - integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-replace-supers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" - integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.16.0" - "@babel/helper-optimise-call-expression" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-simple-access@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" - integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" - integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helpers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.0.tgz#875519c979c232f41adfbd43a3b0398c2e388183" - integrity sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ== - dependencies: - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.0", "@babel/parser@^7.7.2": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.0.tgz#cf147d7ada0a3655e79bf4b08ee846f00a00a295" - integrity sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" + integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -259,42 +242,43 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz#2feeb13d9334cc582ea9111d3506f773174179bb" - integrity sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/template@^7.16.0", "@babel/template@^7.3.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" - integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.16.0", "@babel/traverse@^7.7.2": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.0.tgz#965df6c6bfc0a958c1e739284d3c9fa4a6e3c45b" - integrity sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.0" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-hoist-variables" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" + integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/template@^7.16.7", "@babel/template@^7.3.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.7.2": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" + integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.10" + "@babel/types" "^7.16.8" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" - integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== +"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" + "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -330,93 +314,93 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.3.1.tgz#e8ea3a475d3f8162f23d69efbfaa9cbe486bee93" - integrity sha512-RkFNWmv0iui+qsOr/29q9dyfKTTT5DCuP31kUwg7rmOKPT/ozLeGLKJKVIiOfbiKyleUZKIrHwhmiZWVe8IMdw== +"@jest/console@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.4.6.tgz#0742e6787f682b22bdad56f9db2a8a77f6a86107" + integrity sha512-jauXyacQD33n47A44KrlOVeiXHEXDqapSdfb9kTekOchH/Pd18kBIO1+xxJQRLuG+LUuljFCwTG92ra4NW7SpA== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^27.3.1" - jest-util "^27.3.1" + jest-message-util "^27.4.6" + jest-util "^27.4.2" slash "^3.0.0" -"@jest/core@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.3.1.tgz#04992ef1b58b17c459afb87ab56d81e63d386925" - integrity sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg== +"@jest/core@^27.4.7": + version "27.4.7" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.4.7.tgz#84eabdf42a25f1fa138272ed229bcf0a1b5e6913" + integrity sha512-n181PurSJkVMS+kClIFSX/LLvw9ExSb+4IMtD6YnfxZVerw9ANYtW0bPrm0MJu2pfe9SY9FJ9FtQ+MdZkrZwjg== dependencies: - "@jest/console" "^27.3.1" - "@jest/reporters" "^27.3.1" - "@jest/test-result" "^27.3.1" - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/console" "^27.4.6" + "@jest/reporters" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^27.3.0" - jest-config "^27.3.1" - jest-haste-map "^27.3.1" - jest-message-util "^27.3.1" - jest-regex-util "^27.0.6" - jest-resolve "^27.3.1" - jest-resolve-dependencies "^27.3.1" - jest-runner "^27.3.1" - jest-runtime "^27.3.1" - jest-snapshot "^27.3.1" - jest-util "^27.3.1" - jest-validate "^27.3.1" - jest-watcher "^27.3.1" + jest-changed-files "^27.4.2" + jest-config "^27.4.7" + jest-haste-map "^27.4.6" + jest-message-util "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-resolve-dependencies "^27.4.6" + jest-runner "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + jest-validate "^27.4.6" + jest-watcher "^27.4.6" micromatch "^4.0.4" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.3.1.tgz#2182defbce8d385fd51c5e7c7050f510bd4c86b1" - integrity sha512-BCKCj4mOVLme6Tanoyc9k0ultp3pnmuyHw73UHRPeeZxirsU/7E3HC4le/VDb/SMzE1JcPnto+XBKFOcoiJzVw== +"@jest/environment@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.4.6.tgz#1e92885d64f48c8454df35ed9779fbcf31c56d8b" + integrity sha512-E6t+RXPfATEEGVidr84WngLNWZ8ffCPky8RqqRK6u1Bn0LK92INe0MDttyPl/JOzaq92BmDzOeuqk09TvM22Sg== dependencies: - "@jest/fake-timers" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.3.0" + jest-mock "^27.4.6" -"@jest/fake-timers@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.3.1.tgz#1fad860ee9b13034762cdb94266e95609dfce641" - integrity sha512-M3ZFgwwlqJtWZ+QkBG5NmC23A9w+A6ZxNsO5nJxJsKYt4yguBd3i8TpjQz5NfCX91nEve1KqD9RA2Q+Q1uWqoA== +"@jest/fake-timers@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.4.6.tgz#e026ae1671316dbd04a56945be2fa251204324e8" + integrity sha512-mfaethuYF8scV8ntPpiVGIHQgS0XIALbpY2jt2l7wb/bvq4Q5pDLk4EP4D7SAvYT1QrPOPVZAtbdGAOOyIgs7A== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@sinonjs/fake-timers" "^8.0.1" "@types/node" "*" - jest-message-util "^27.3.1" - jest-mock "^27.3.0" - jest-util "^27.3.1" + jest-message-util "^27.4.6" + jest-mock "^27.4.6" + jest-util "^27.4.2" -"@jest/globals@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.3.1.tgz#ce1dfb03d379237a9da6c1b99ecfaca1922a5f9e" - integrity sha512-Q651FWiWQAIFiN+zS51xqhdZ8g9b88nGCobC87argAxA7nMfNQq0Q0i9zTfQYgLa6qFXk2cGANEqfK051CZ8Pg== +"@jest/globals@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.4.6.tgz#3f09bed64b0fd7f5f996920258bd4be8f52f060a" + integrity sha512-kAiwMGZ7UxrgPzu8Yv9uvWmXXxsy0GciNejlHvfPIfWkSxChzv6bgTS3YqBkGuHcis+ouMFI2696n2t+XYIeFw== dependencies: - "@jest/environment" "^27.3.1" - "@jest/types" "^27.2.5" - expect "^27.3.1" + "@jest/environment" "^27.4.6" + "@jest/types" "^27.4.2" + expect "^27.4.6" -"@jest/reporters@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.3.1.tgz#28b5c1f5789481e23788048fa822ed15486430b9" - integrity sha512-m2YxPmL9Qn1emFVgZGEiMwDntDxRRQ2D58tiDQlwYTg5GvbFOKseYCcHtn0WsI8CG4vzPglo3nqbOiT8ySBT/w== +"@jest/reporters@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.4.6.tgz#b53dec3a93baf9b00826abf95b932de919d6d8dd" + integrity sha512-+Zo9gV81R14+PSq4wzee4GC2mhAN9i9a7qgJWL90Gpx7fHYkWpTBvwWNZUXvJByYR9tAVBdc8VxDWqfJyIUrIQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.3.1" - "@jest/test-result" "^27.3.1" - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/console" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" @@ -424,74 +408,74 @@ glob "^7.1.2" graceful-fs "^4.2.4" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^4.0.3" + istanbul-lib-instrument "^5.1.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.0.2" - jest-haste-map "^27.3.1" - jest-resolve "^27.3.1" - jest-util "^27.3.1" - jest-worker "^27.3.1" + istanbul-reports "^3.1.3" + jest-haste-map "^27.4.6" + jest-resolve "^27.4.6" + jest-util "^27.4.2" + jest-worker "^27.4.6" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" -"@jest/source-map@^27.0.6": - version "27.0.6" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f" - integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g== +"@jest/source-map@^27.4.0": + version "27.4.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.4.0.tgz#2f0385d0d884fb3e2554e8f71f8fa957af9a74b6" + integrity sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.3.1.tgz#89adee8b771877c69b3b8d59f52f29dccc300194" - integrity sha512-mLn6Thm+w2yl0opM8J/QnPTqrfS4FoXsXF2WIWJb2O/GBSyResL71BRuMYbYRsGt7ELwS5JGcEcGb52BNrumgg== +"@jest/test-result@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.4.6.tgz#b3df94c3d899c040f602cea296979844f61bdf69" + integrity sha512-fi9IGj3fkOrlMmhQqa/t9xum8jaJOOAi/lZlm6JXSc55rJMXKHxNDN1oCP39B0/DhNOa2OMupF9BcKZnNtXMOQ== dependencies: - "@jest/console" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/console" "^27.4.6" + "@jest/types" "^27.4.2" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.3.1.tgz#4b3bde2dbb05ee74afdae608cf0768e3354683b1" - integrity sha512-siySLo07IMEdSjA4fqEnxfIX8lB/lWYsBPwNFtkOvsFQvmBrL3yj3k3uFNZv/JDyApTakRpxbKLJ3CT8UGVCrA== +"@jest/test-sequencer@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.4.6.tgz#447339b8a3d7b5436f50934df30854e442a9d904" + integrity sha512-3GL+nsf6E1PsyNsJuvPyIz+DwFuCtBdtvPpm/LMXVkBJbdFvQYCDpccYT56qq5BGniXWlE81n2qk1sdXfZebnw== dependencies: - "@jest/test-result" "^27.3.1" + "@jest/test-result" "^27.4.6" graceful-fs "^4.2.4" - jest-haste-map "^27.3.1" - jest-runtime "^27.3.1" + jest-haste-map "^27.4.6" + jest-runtime "^27.4.6" -"@jest/transform@^27.3.1": - version "27.3.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.3.1.tgz#ff80eafbeabe811e9025e4b6f452126718455220" - integrity sha512-3fSvQ02kuvjOI1C1ssqMVBKJpZf6nwoCiSu00zAKh5nrp3SptNtZy/8s5deayHnqxhjD9CWDJ+yqQwuQ0ZafXQ== +"@jest/transform@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.4.6.tgz#153621940b1ed500305eacdb31105d415dc30231" + integrity sha512-9MsufmJC8t5JTpWEQJ0OcOOAXaH5ioaIX6uHVBLBMoCZPfKKQF+EqP8kACAvCZ0Y1h2Zr3uOccg8re+Dr5jxyw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^27.2.5" - babel-plugin-istanbul "^6.0.0" + "@jest/types" "^27.4.2" + babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^27.3.1" - jest-regex-util "^27.0.6" - jest-util "^27.3.1" + jest-haste-map "^27.4.6" + jest-regex-util "^27.4.0" + jest-util "^27.4.2" micromatch "^4.0.4" - pirates "^4.0.1" + pirates "^4.0.4" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^27.2.5": - version "27.2.5" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.2.5.tgz#420765c052605e75686982d24b061b4cbba22132" - integrity sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ== +"@jest/types@^27.4.2": + version "27.4.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" + integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -508,9 +492,9 @@ node-fetch "^2.6.1" "@sindresorhus/is@^4.0.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.2.0.tgz#667bfc6186ae7c9e0b45a08960c551437176e1ca" - integrity sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.4.0.tgz#e277e5bdbdf7cb1e20d320f02f5e2ed113cd3185" + integrity sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ== "@sinonjs/commons@^1.7.0": version "1.8.3" @@ -520,9 +504,9 @@ type-detect "4.0.8" "@sinonjs/fake-timers@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz#1c1c9a91419f804e59ae8df316a07dd1c3a76b94" - integrity sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew== + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== dependencies: "@sinonjs/commons" "^1.7.0" @@ -559,9 +543,9 @@ integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" - integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== + version "7.1.18" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" + integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -570,9 +554,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" @@ -614,9 +598,9 @@ integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" @@ -633,17 +617,17 @@ "@types/istanbul-lib-report" "*" "@types/jest@^27.0.2": - version "27.0.2" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.2.tgz#ac383c4d4aaddd29bbf2b916d8d105c304a5fcd7" - integrity sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA== + version "27.4.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" + integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ== dependencies: jest-diff "^27.0.0" pretty-format "^27.0.0" "@types/js-yaml@^4.0.3": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.4.tgz#cc38781257612581a1a0eb25f1709d2b06812fce" - integrity sha512-AuHubXUmg0AzkXH0Mx6sIxeY/1C110mm/EkE/gB1sTRz3h2dao2W/63q42SlVST+lICxz5Oki2hzYA6+KnnieQ== + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" + integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== "@types/keyv@*": version "3.1.3" @@ -666,14 +650,14 @@ form-data "^3.0.0" "@types/node@*": - version "16.11.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" - integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== + version "17.0.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.14.tgz#33b9b94f789a8fedd30a68efdbca4dbb06b61f20" + integrity sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng== "@types/prettier@^2.1.5": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" - integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== + version "2.4.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" + integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" @@ -728,9 +712,9 @@ acorn@^7.1.1: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.2.4, acorn@^8.4.1: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== agent-base@6: version "6.0.2" @@ -800,21 +784,21 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -babel-jest@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.3.1.tgz#0636a3404c68e07001e434ac4956d82da8a80022" - integrity sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ== +babel-jest@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.4.6.tgz#4d024e69e241cdf4f396e453a07100f44f7ce314" + integrity sha512-qZL0JT0HS1L+lOuH+xC2DVASR3nunZi/ozGhpgauJHgmI7f8rudxf6hUjEHympdQ/J64CdKmPkgfJ+A3U6QCrg== dependencies: - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^27.2.0" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^27.4.0" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" -babel-plugin-istanbul@^6.0.0: +babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== @@ -825,10 +809,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.2.0.tgz#79f37d43f7e5c4fdc4b2ca3e10cc6cf545626277" - integrity sha512-TOux9khNKdi64mW+0OIhcmbAn75tTlzKhxmiNXevQaPbrBYK7YKjP1jl6NHTJ6XR5UgUrJbCnWlKVnJn29dfjw== +babel-plugin-jest-hoist@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz#d7831fc0f93573788d80dee7e682482da4c730d6" + integrity sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -853,12 +837,12 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.2.0.tgz#556bbbf340608fed5670ab0ea0c8ef2449fba885" - integrity sha512-z7MgQ3peBwN5L5aCqBKnF6iqdlvZvFUQynEhu0J+X9nHLU72jO3iY331lcYrg+AssJ8q7xsv5/3AICzVmJ/wvg== +babel-preset-jest@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz#70d0e676a282ccb200fbabd7f415db5fdf393bca" + integrity sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg== dependencies: - babel-plugin-jest-hoist "^27.2.0" + babel-plugin-jest-hoist "^27.4.0" babel-preset-current-node-syntax "^1.0.0" balanced-match@^1.0.0: @@ -886,13 +870,13 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.16.6: - version "4.17.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.5.tgz#c827bbe172a4c22b123f5e337533ceebadfdd559" - integrity sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA== +browserslist@^4.17.5: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== dependencies: - caniuse-lite "^1.0.30001271" - electron-to-chromium "^1.3.878" + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" escalade "^3.1.1" node-releases "^2.0.1" picocolors "^1.0.0" @@ -921,7 +905,7 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== -cacheable-request@^7.0.1: +cacheable-request@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== @@ -945,14 +929,14 @@ camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001271: - version "1.0.30001272" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001272.tgz#8e9790ff995e9eb6e1f4c45cd07ddaa87cddbb14" - integrity sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw== +caniuse-lite@^1.0.30001286: + version "1.0.30001304" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz#38af55ed3fc8220cb13e35e6e7309c8c65a05559" + integrity sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ== chalk@^2.0.0: version "2.4.2" @@ -977,9 +961,9 @@ char-regex@^1.0.2: integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== ci-info@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== + version "3.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== cjs-module-lexer@^1.0.0: version "1.2.2" @@ -1096,9 +1080,9 @@ data-urls@^2.0.0: whatwg-url "^8.0.0" debug@4, debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" @@ -1144,10 +1128,10 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -diff-sequences@^27.0.6: - version "27.0.6" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" - integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== +diff-sequences@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" + integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== diff@^4.0.1: version "4.0.2" @@ -1161,10 +1145,10 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" -electron-to-chromium@^1.3.878: - version "1.3.885" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.885.tgz#c8cec32fbc61364127849ae00f2395a1bae7c454" - integrity sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg== +electron-to-chromium@^1.4.17: + version "1.4.59" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz#657f2588c048fb95975779f8fea101fad854de89" + integrity sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg== emittery@^0.8.1: version "0.8.1" @@ -1245,17 +1229,15 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expect@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.3.1.tgz#d0f170b1f5c8a2009bab0beffd4bb94f043e38e7" - integrity sha512-MrNXV2sL9iDRebWPGOGFdPQRl2eDQNu/uhxIMShjjx74T6kC6jFIkmQ6OqXDtevjGUkyB2IT56RzDBqXf/QPCg== +expect@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.4.6.tgz#f335e128b0335b6ceb4fcab67ece7cbd14c942e6" + integrity sha512-1M/0kAALIaj5LaG66sFJTbRsWTADnylly82cu4bspI0nl+pgP4E6Bh/aqdHlTUjul06K7xQnnrAoqfxVU0+/ag== dependencies: - "@jest/types" "^27.2.5" - ansi-styles "^5.0.0" - jest-get-type "^27.3.1" - jest-matcher-utils "^27.3.1" - jest-message-util "^27.3.1" - jest-regex-util "^27.0.6" + "@jest/types" "^27.4.2" + jest-get-type "^27.4.0" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -1367,16 +1349,16 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== got@^11.8.2: - version "11.8.2" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" - integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== + version "11.8.3" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" + integrity sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg== dependencies: "@sindresorhus/is" "^4.0.0" "@szmarczak/http-timer" "^4.0.5" "@types/cacheable-request" "^6.0.1" "@types/responselike" "^1.0.0" cacheable-lookup "^5.0.3" - cacheable-request "^7.0.1" + cacheable-request "^7.0.2" decompress-response "^6.0.0" http2-wrapper "^1.0.0-beta.5.2" lowercase-keys "^2.0.0" @@ -1384,9 +1366,9 @@ got@^11.8.2: responselike "^2.0.0" graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== has-flag@^3.0.0: version "3.0.0" @@ -1460,9 +1442,9 @@ iconv-lite@0.4.24: safer-buffer ">= 2.1.2 < 3" import-local@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" - integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -1485,10 +1467,10 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -is-core-module@^2.2.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: has "^1.0.3" @@ -1532,17 +1514,7 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== - dependencies: - "@babel/core" "^7.7.5" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" - semver "^6.3.0" - -istanbul-lib-instrument@^5.0.4: +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== @@ -1571,234 +1543,234 @@ istanbul-lib-source-maps@^4.0.0: istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" -istanbul-reports@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.5.tgz#a2580107e71279ea6d661ddede929ffc6d693384" - integrity sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ== +istanbul-reports@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" + integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^27.3.0: - version "27.3.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.3.0.tgz#22a02cc2b34583fc66e443171dc271c0529d263c" - integrity sha512-9DJs9garMHv4RhylUMZgbdCJ3+jHSkpL9aaVKp13xtXAD80qLTLrqcDZL1PHA9dYA0bCI86Nv2BhkLpLhrBcPg== +jest-changed-files@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.4.2.tgz#da2547ea47c6e6a5f6ed336151bd2075736eb4a5" + integrity sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" execa "^5.0.0" throat "^6.0.1" -jest-circus@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.3.1.tgz#1679e74387cbbf0c6a8b42de963250a6469e0797" - integrity sha512-v1dsM9II6gvXokgqq6Yh2jHCpfg7ZqV4jWY66u7npz24JnhP3NHxI0sKT7+ZMQ7IrOWHYAaeEllOySbDbWsiXw== +jest-circus@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.4.6.tgz#d3af34c0eb742a967b1919fbb351430727bcea6c" + integrity sha512-UA7AI5HZrW4wRM72Ro80uRR2Fg+7nR0GESbSI/2M+ambbzVuA63mn5T1p3Z/wlhntzGpIG1xx78GP2YIkf6PhQ== dependencies: - "@jest/environment" "^27.3.1" - "@jest/test-result" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/environment" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.3.1" + expect "^27.4.6" is-generator-fn "^2.0.0" - jest-each "^27.3.1" - jest-matcher-utils "^27.3.1" - jest-message-util "^27.3.1" - jest-runtime "^27.3.1" - jest-snapshot "^27.3.1" - jest-util "^27.3.1" - pretty-format "^27.3.1" + jest-each "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + pretty-format "^27.4.6" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.3.1.tgz#b576f9d146ba6643ce0a162d782b40152b6b1d16" - integrity sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q== +jest-cli@^27.4.7: + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.4.7.tgz#d00e759e55d77b3bcfea0715f527c394ca314e5a" + integrity sha512-zREYhvjjqe1KsGV15mdnxjThKNDgza1fhDT+iUsXWLCq3sxe9w5xnvyctcYVT5PcdLSjv7Y5dCwTS3FCF1tiuw== dependencies: - "@jest/core" "^27.3.1" - "@jest/test-result" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/core" "^27.4.7" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" - jest-config "^27.3.1" - jest-util "^27.3.1" - jest-validate "^27.3.1" + jest-config "^27.4.7" + jest-util "^27.4.2" + jest-validate "^27.4.6" prompts "^2.0.1" yargs "^16.2.0" -jest-config@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.3.1.tgz#cb3b7f6aaa8c0a7daad4f2b9573899ca7e09bbad" - integrity sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg== +jest-config@^27.4.7: + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.4.7.tgz#4f084b2acbd172c8b43aa4cdffe75d89378d3972" + integrity sha512-xz/o/KJJEedHMrIY9v2ParIoYSrSVY6IVeE4z5Z3i101GoA5XgfbJz+1C8EYPsv7u7f39dS8F9v46BHDhn0vlw== dependencies: - "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^27.3.1" - "@jest/types" "^27.2.5" - babel-jest "^27.3.1" + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.4.6" + "@jest/types" "^27.4.2" + babel-jest "^27.4.6" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-circus "^27.3.1" - jest-environment-jsdom "^27.3.1" - jest-environment-node "^27.3.1" - jest-get-type "^27.3.1" - jest-jasmine2 "^27.3.1" - jest-regex-util "^27.0.6" - jest-resolve "^27.3.1" - jest-runner "^27.3.1" - jest-util "^27.3.1" - jest-validate "^27.3.1" + jest-circus "^27.4.6" + jest-environment-jsdom "^27.4.6" + jest-environment-node "^27.4.6" + jest-get-type "^27.4.0" + jest-jasmine2 "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-runner "^27.4.6" + jest-util "^27.4.2" + jest-validate "^27.4.6" micromatch "^4.0.4" - pretty-format "^27.3.1" + pretty-format "^27.4.6" + slash "^3.0.0" -jest-diff@^27.0.0, jest-diff@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.3.1.tgz#d2775fea15411f5f5aeda2a5e02c2f36440f6d55" - integrity sha512-PCeuAH4AWUo2O5+ksW4pL9v5xJAcIKPUPfIhZBcG1RKv/0+dvaWTQK1Nrau8d67dp65fOqbeMdoil+6PedyEPQ== +jest-diff@^27.0.0, jest-diff@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d" + integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w== dependencies: chalk "^4.0.0" - diff-sequences "^27.0.6" - jest-get-type "^27.3.1" - pretty-format "^27.3.1" + diff-sequences "^27.4.0" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-docblock@^27.0.6: - version "27.0.6" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" - integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA== +jest-docblock@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.4.0.tgz#06c78035ca93cbbb84faf8fce64deae79a59f69f" + integrity sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg== dependencies: detect-newline "^3.0.0" -jest-each@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.3.1.tgz#14c56bb4f18dd18dc6bdd853919b5f16a17761ff" - integrity sha512-E4SwfzKJWYcvOYCjOxhZcxwL+AY0uFMvdCOwvzgutJiaiodFjkxQQDxHm8FQBeTqDnSmKsQWn7ldMRzTn2zJaQ== +jest-each@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.4.6.tgz#e7e8561be61d8cc6dbf04296688747ab186c40ff" + integrity sha512-n6QDq8y2Hsmn22tRkgAk+z6MCX7MeVlAzxmZDshfS2jLcaBlyhpF3tZSJLR+kXmh23GEvS0ojMR8i6ZeRvpQcA== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" chalk "^4.0.0" - jest-get-type "^27.3.1" - jest-util "^27.3.1" - pretty-format "^27.3.1" - -jest-environment-jsdom@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.3.1.tgz#63ac36d68f7a9303494df783494856222b57f73e" - integrity sha512-3MOy8qMzIkQlfb3W1TfrD7uZHj+xx8Olix5vMENkj5djPmRqndMaXtpnaZkxmxM+Qc3lo+yVzJjzuXbCcZjAlg== - dependencies: - "@jest/environment" "^27.3.1" - "@jest/fake-timers" "^27.3.1" - "@jest/types" "^27.2.5" + jest-get-type "^27.4.0" + jest-util "^27.4.2" + pretty-format "^27.4.6" + +jest-environment-jsdom@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.4.6.tgz#c23a394eb445b33621dfae9c09e4c8021dea7b36" + integrity sha512-o3dx5p/kHPbUlRvSNjypEcEtgs6LmvESMzgRFQE6c+Prwl2JLA4RZ7qAnxc5VM8kutsGRTB15jXeeSbJsKN9iA== + dependencies: + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.3.0" - jest-util "^27.3.1" + jest-mock "^27.4.6" + jest-util "^27.4.2" jsdom "^16.6.0" -jest-environment-node@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.3.1.tgz#af7d0eed04edafb740311b303f3fe7c8c27014bb" - integrity sha512-T89F/FgkE8waqrTSA7/ydMkcc52uYPgZZ6q8OaZgyiZkJb5QNNCF6oPZjH9IfPFfcc9uBWh1574N0kY0pSvTXw== +jest-environment-node@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.4.6.tgz#ee8cd4ef458a0ef09d087c8cd52ca5856df90242" + integrity sha512-yfHlZ9m+kzTKZV0hVfhVu6GuDxKAYeFHrfulmy7Jxwsq4V7+ZK7f+c0XP/tbVDMQW7E4neG2u147hFkuVz0MlQ== dependencies: - "@jest/environment" "^27.3.1" - "@jest/fake-timers" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.3.0" - jest-util "^27.3.1" + jest-mock "^27.4.6" + jest-util "^27.4.2" -jest-get-type@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.3.1.tgz#a8a2b0a12b50169773099eee60a0e6dd11423eff" - integrity sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg== +jest-get-type@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" + integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== -jest-haste-map@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.3.1.tgz#7656fbd64bf48bda904e759fc9d93e2c807353ee" - integrity sha512-lYfNZIzwPccDJZIyk9Iz5iQMM/MH56NIIcGj7AFU1YyA4ewWFBl8z+YPJuSCRML/ee2cCt2y3W4K3VXPT6Nhzg== +jest-haste-map@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.4.6.tgz#c60b5233a34ca0520f325b7e2cc0a0140ad0862a" + integrity sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-regex-util "^27.0.6" - jest-serializer "^27.0.6" - jest-util "^27.3.1" - jest-worker "^27.3.1" + jest-regex-util "^27.4.0" + jest-serializer "^27.4.0" + jest-util "^27.4.2" + jest-worker "^27.4.6" micromatch "^4.0.4" walker "^1.0.7" optionalDependencies: fsevents "^2.3.2" -jest-jasmine2@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.3.1.tgz#df6d3d07c7dafc344feb43a0072a6f09458d32b0" - integrity sha512-WK11ZUetDQaC09w4/j7o4FZDUIp+4iYWH/Lik34Pv7ukL+DuXFGdnmmi7dT58J2ZYKFB5r13GyE0z3NPeyJmsg== +jest-jasmine2@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.4.6.tgz#109e8bc036cb455950ae28a018f983f2abe50127" + integrity sha512-uAGNXF644I/whzhsf7/qf74gqy9OuhvJ0XYp8SDecX2ooGeaPnmJMjXjKt0mqh1Rl5dtRGxJgNrHlBQIBfS5Nw== dependencies: - "@babel/traverse" "^7.1.0" - "@jest/environment" "^27.3.1" - "@jest/source-map" "^27.0.6" - "@jest/test-result" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/environment" "^27.4.6" + "@jest/source-map" "^27.4.0" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^27.3.1" + expect "^27.4.6" is-generator-fn "^2.0.0" - jest-each "^27.3.1" - jest-matcher-utils "^27.3.1" - jest-message-util "^27.3.1" - jest-runtime "^27.3.1" - jest-snapshot "^27.3.1" - jest-util "^27.3.1" - pretty-format "^27.3.1" + jest-each "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + pretty-format "^27.4.6" throat "^6.0.1" -jest-leak-detector@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.3.1.tgz#7fb632c2992ef707a1e73286e1e704f9cc1772b2" - integrity sha512-78QstU9tXbaHzwlRlKmTpjP9k4Pvre5l0r8Spo4SbFFVy/4Abg9I6ZjHwjg2QyKEAMg020XcjP+UgLZIY50yEg== +jest-leak-detector@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.4.6.tgz#ed9bc3ce514b4c582637088d9faf58a33bd59bf4" + integrity sha512-kkaGixDf9R7CjHm2pOzfTxZTQQQ2gHTIWKY/JZSiYTc90bZp8kSZnUMS3uLAfwTZwc0tcMRoEX74e14LG1WapA== dependencies: - jest-get-type "^27.3.1" - pretty-format "^27.3.1" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-matcher-utils@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.3.1.tgz#257ad61e54a6d4044e080d85dbdc4a08811e9c1c" - integrity sha512-hX8N7zXS4k+8bC1Aj0OWpGb7D3gIXxYvPNK1inP5xvE4ztbz3rc4AkI6jGVaerepBnfWB17FL5lWFJT3s7qo8w== +jest-matcher-utils@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.6.tgz#53ca7f7b58170638590e946f5363b988775509b8" + integrity sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA== dependencies: chalk "^4.0.0" - jest-diff "^27.3.1" - jest-get-type "^27.3.1" - pretty-format "^27.3.1" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-message-util@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.3.1.tgz#f7c25688ad3410ab10bcb862bcfe3152345c6436" - integrity sha512-bh3JEmxsTZ/9rTm0jQrPElbY2+y48Rw2t47uMfByNyUVR+OfPh4anuyKsGqsNkXk/TI4JbLRZx+7p7Hdt6q1yg== +jest-message-util@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.6.tgz#9fdde41a33820ded3127465e1a5896061524da31" + integrity sha512-0p5szriFU0U74czRSFjH6RyS7UYIAkn/ntwMuOwTGWrQIOh5NzXXrq72LOqIkJKKvFbPq+byZKuBz78fjBERBA== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.4" - pretty-format "^27.3.1" + pretty-format "^27.4.6" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^27.3.0: - version "27.3.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.3.0.tgz#ddf0ec3cc3e68c8ccd489bef4d1f525571a1b867" - integrity sha512-ziZiLk0elZOQjD08bLkegBzv5hCABu/c8Ytx45nJKkysQwGaonvmTxwjLqEA4qGdasq9o2I8/HtdGMNnVsMTGw== +jest-mock@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.4.6.tgz#77d1ba87fbd33ccb8ef1f061697e7341b7635195" + integrity sha512-kvojdYRkst8iVSZ1EJ+vc1RRD9llueBjKzXzeCytH3dMM7zvPV/ULcfI2nr0v0VUgm3Bjt3hBCQvOeaBz+ZTHw== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -1806,188 +1778,182 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^27.0.6: - version "27.0.6" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" - integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== +jest-regex-util@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" + integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== -jest-resolve-dependencies@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.3.1.tgz#85b99bdbdfa46e2c81c6228fc4c91076f624f6e2" - integrity sha512-X7iLzY8pCiYOnvYo2YrK3P9oSE8/3N2f4pUZMJ8IUcZnT81vlSonya1KTO9ZfKGuC+svE6FHK/XOb8SsoRUV1A== +jest-resolve-dependencies@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.6.tgz#fc50ee56a67d2c2183063f6a500cc4042b5e2327" + integrity sha512-W85uJZcFXEVZ7+MZqIPCscdjuctruNGXUZ3OHSXOfXR9ITgbUKeHj+uGcies+0SsvI5GtUfTw4dY7u9qjTvQOw== dependencies: - "@jest/types" "^27.2.5" - jest-regex-util "^27.0.6" - jest-snapshot "^27.3.1" + "@jest/types" "^27.4.2" + jest-regex-util "^27.4.0" + jest-snapshot "^27.4.6" -jest-resolve@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.3.1.tgz#0e5542172a1aa0270be6f66a65888647bdd74a3e" - integrity sha512-Dfzt25CFSPo3Y3GCbxynRBZzxq9AdyNN+x/v2IqYx6KVT5Z6me2Z/PsSGFSv3cOSUZqJ9pHxilao/I/m9FouLw== +jest-resolve@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.4.6.tgz#2ec3110655e86d5bfcfa992e404e22f96b0b5977" + integrity sha512-SFfITVApqtirbITKFAO7jOVN45UgFzcRdQanOFzjnbd+CACDoyeX7206JyU92l4cRr73+Qy/TlW51+4vHGt+zw== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" chalk "^4.0.0" graceful-fs "^4.2.4" - jest-haste-map "^27.3.1" + jest-haste-map "^27.4.6" jest-pnp-resolver "^1.2.2" - jest-util "^27.3.1" - jest-validate "^27.3.1" + jest-util "^27.4.2" + jest-validate "^27.4.6" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.3.1.tgz#1d594dcbf3bd8600a7e839e790384559eaf96e3e" - integrity sha512-r4W6kBn6sPr3TBwQNmqE94mPlYVn7fLBseeJfo4E2uCTmAyDFm2O5DYAQAFP7Q3YfiA/bMwg8TVsciP7k0xOww== +jest-runner@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.4.6.tgz#1d390d276ec417e9b4d0d081783584cbc3e24773" + integrity sha512-IDeFt2SG4DzqalYBZRgbbPmpwV3X0DcntjezPBERvnhwKGWTW7C5pbbA5lVkmvgteeNfdd/23gwqv3aiilpYPg== dependencies: - "@jest/console" "^27.3.1" - "@jest/environment" "^27.3.1" - "@jest/test-result" "^27.3.1" - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/console" "^27.4.6" + "@jest/environment" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-docblock "^27.0.6" - jest-environment-jsdom "^27.3.1" - jest-environment-node "^27.3.1" - jest-haste-map "^27.3.1" - jest-leak-detector "^27.3.1" - jest-message-util "^27.3.1" - jest-resolve "^27.3.1" - jest-runtime "^27.3.1" - jest-util "^27.3.1" - jest-worker "^27.3.1" + jest-docblock "^27.4.0" + jest-environment-jsdom "^27.4.6" + jest-environment-node "^27.4.6" + jest-haste-map "^27.4.6" + jest-leak-detector "^27.4.6" + jest-message-util "^27.4.6" + jest-resolve "^27.4.6" + jest-runtime "^27.4.6" + jest-util "^27.4.2" + jest-worker "^27.4.6" source-map-support "^0.5.6" throat "^6.0.1" -jest-runtime@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.3.1.tgz#80fa32eb85fe5af575865ddf379874777ee993d7" - integrity sha512-qtO6VxPbS8umqhEDpjA4pqTkKQ1Hy4ZSi9mDVeE9Za7LKBo2LdW2jmT+Iod3XFaJqINikZQsn2wEi0j9wPRbLg== - dependencies: - "@jest/console" "^27.3.1" - "@jest/environment" "^27.3.1" - "@jest/globals" "^27.3.1" - "@jest/source-map" "^27.0.6" - "@jest/test-result" "^27.3.1" - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" - "@types/yargs" "^16.0.0" +jest-runtime@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.4.6.tgz#83ae923818e3ea04463b22f3597f017bb5a1cffa" + integrity sha512-eXYeoR/MbIpVDrjqy5d6cGCFOYBFFDeKaNWqTp0h6E74dK0zLHzASQXJpl5a2/40euBmKnprNLJ0Kh0LCndnWQ== + dependencies: + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/globals" "^27.4.6" + "@jest/source-map" "^27.4.0" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" - exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-haste-map "^27.3.1" - jest-message-util "^27.3.1" - jest-mock "^27.3.0" - jest-regex-util "^27.0.6" - jest-resolve "^27.3.1" - jest-snapshot "^27.3.1" - jest-util "^27.3.1" - jest-validate "^27.3.1" + jest-haste-map "^27.4.6" + jest-message-util "^27.4.6" + jest-mock "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" slash "^3.0.0" strip-bom "^4.0.0" - yargs "^16.2.0" -jest-serializer@^27.0.6: - version "27.0.6" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1" - integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA== +jest-serializer@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.4.0.tgz#34866586e1cae2388b7d12ffa2c7819edef5958a" + integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== dependencies: "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.3.1.tgz#1da5c0712a252d70917d46c037054f5918c49ee4" - integrity sha512-APZyBvSgQgOT0XumwfFu7X3G5elj6TGhCBLbBdn3R1IzYustPGPE38F51dBWMQ8hRXa9je0vAdeVDtqHLvB6lg== +jest-snapshot@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.4.6.tgz#e2a3b4fff8bdce3033f2373b2e525d8b6871f616" + integrity sha512-fafUCDLQfzuNP9IRcEqaFAMzEe7u5BF7mude51wyWv7VRex60WznZIC7DfKTgSIlJa8aFzYmXclmN328aqSDmQ== dependencies: "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" - "@babel/parser" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.0.0" - "@jest/transform" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.3.1" + expect "^27.4.6" graceful-fs "^4.2.4" - jest-diff "^27.3.1" - jest-get-type "^27.3.1" - jest-haste-map "^27.3.1" - jest-matcher-utils "^27.3.1" - jest-message-util "^27.3.1" - jest-resolve "^27.3.1" - jest-util "^27.3.1" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + jest-haste-map "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-util "^27.4.2" natural-compare "^1.4.0" - pretty-format "^27.3.1" + pretty-format "^27.4.6" semver "^7.3.2" -jest-util@^27.0.0, jest-util@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.3.1.tgz#a58cdc7b6c8a560caac9ed6bdfc4e4ff23f80429" - integrity sha512-8fg+ifEH3GDryLQf/eKZck1DEs2YuVPBCMOaHQxVVLmQwl/CDhWzrvChTX4efLZxGrw+AA0mSXv78cyytBt/uw== +jest-util@^27.0.0, jest-util@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.4.2.tgz#ed95b05b1adfd761e2cda47e0144c6a58e05a621" + integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" graceful-fs "^4.2.4" picomatch "^2.2.3" -jest-validate@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.3.1.tgz#3a395d61a19cd13ae9054af8cdaf299116ef8a24" - integrity sha512-3H0XCHDFLA9uDII67Bwi1Vy7AqwA5HqEEjyy934lgVhtJ3eisw6ShOF1MDmRPspyikef5MyExvIm0/TuLzZ86Q== +jest-validate@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.4.6.tgz#efc000acc4697b6cf4fa68c7f3f324c92d0c4f1f" + integrity sha512-872mEmCPVlBqbA5dToC57vA3yJaMRfIdpCoD3cyHWJOMx+SJwLNw0I71EkWs41oza/Er9Zno9XuTkRYCPDUJXQ== dependencies: - "@jest/types" "^27.2.5" + "@jest/types" "^27.4.2" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^27.3.1" + jest-get-type "^27.4.0" leven "^3.1.0" - pretty-format "^27.3.1" + pretty-format "^27.4.6" -jest-watcher@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.3.1.tgz#ba5e0bc6aa843612b54ddb7f009d1cbff7e05f3e" - integrity sha512-9/xbV6chABsGHWh9yPaAGYVVKurWoP3ZMCv6h+O1v9/+pkOroigs6WzZ0e9gLP/njokUwM7yQhr01LKJVMkaZA== +jest-watcher@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.4.6.tgz#673679ebeffdd3f94338c24f399b85efc932272d" + integrity sha512-yKQ20OMBiCDigbD0quhQKLkBO+ObGN79MO4nT7YaCuQ5SM+dkBNWE8cZX0FjU6czwMvWw6StWbe+Wv4jJPJ+fw== dependencies: - "@jest/test-result" "^27.3.1" - "@jest/types" "^27.2.5" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^27.3.1" + jest-util "^27.4.2" string-length "^4.0.1" -jest-worker@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.3.1.tgz#0def7feae5b8042be38479799aeb7b5facac24b2" - integrity sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g== +jest-worker@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" + integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" jest@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.3.1.tgz#b5bab64e8f56b6f7e275ba1836898b0d9f1e5c8a" - integrity sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng== + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.4.7.tgz#87f74b9026a1592f2da05b4d258e57505f28eca4" + integrity sha512-8heYvsx7nV/m8m24Vk26Y87g73Ba6ueUd0MWed/NXMhSZIm62U/llVbS0PJe1SHunbyXjJ/BqG1z9bFjGUIvTg== dependencies: - "@jest/core" "^27.3.1" + "@jest/core" "^27.4.7" import-local "^3.0.2" - jest-cli "^27.3.1" + jest-cli "^27.4.7" js-tokens@^4.0.0: version "4.0.0" @@ -2076,9 +2042,9 @@ keyv-file@^0.2.0: tslib "^1.9.3" keyv@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254" - integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA== + version "4.0.5" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.5.tgz#bb12b467aba372fab2a44d4420c00d3c4ebd484c" + integrity sha512-531pkGLqV3BMg0eDqqJFI0R1mkK1Nm5xIP2mM6keP5P8WfFtCkg2IOwplTUmlGoTgIg9yQYZ/kdihhz89XH3vA== dependencies: json-buffer "3.0.1" @@ -2161,17 +2127,17 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.50.0: - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== mime-types@^2.1.12, mime-types@^2.1.32: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== dependencies: - mime-db "1.50.0" + mime-db "1.51.0" mimic-fn@^2.1.0: version "2.1.0" @@ -2211,9 +2177,9 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= node-fetch@^2.6.1: - version "2.6.5" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" - integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" @@ -2222,11 +2188,6 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - node-releases@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" @@ -2324,7 +2285,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -2335,16 +2296,14 @@ picocolors@^1.0.0: integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.0.4, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== pkg-dir@^4.2.0: version "4.2.0" @@ -2358,12 +2317,11 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -pretty-format@^27.0.0, pretty-format@^27.3.1: - version "27.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.3.1.tgz#7e9486365ccdd4a502061fa761d3ab9ca1b78df5" - integrity sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA== +pretty-format@^27.0.0, pretty-format@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7" + integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g== dependencies: - "@jest/types" "^27.2.5" ansi-regex "^5.0.1" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -2432,12 +2390,13 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" responselike@^2.0.0: version "2.0.0" @@ -2495,9 +2454,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== sisteransi@^1.0.5: version "1.0.5" @@ -2510,14 +2469,14 @@ slash@^3.0.0: integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slugify@^1.6.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.1.tgz#a5fcaef29f4e57c6e932ce7044b6ffd9cf81b641" - integrity sha512-5ofqMTbetNhxlzjYYLBaZFQd6oiTuSkQlyfPEFIMwgUABlZQ0hbk5xIV9Ydd5jghWeRoO7GkiJliUvTpLOjNRA== + version "1.6.5" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.5.tgz#c8f5c072bf2135b80703589b39a3d41451fbe8c8" + integrity sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ== source-map-support@^0.5.6: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -2612,6 +2571,11 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -2678,9 +2642,9 @@ tr46@~0.0.3: integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= ts-jest@^27.0.7: - version "27.0.7" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.0.7.tgz#fb7c8c8cb5526ab371bc1b23d06e745652cca2d0" - integrity sha512-O41shibMqzdafpuP+CkrOL7ykbmLh+FqQrXEmV9CydQ5JBk0Sj0uAEF5TNNe94fZWKm3yYvWa/IbyV4Yg1zK2Q== + version "27.1.3" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.3.tgz#1f723e7e74027c4da92c0ffbd73287e8af2b2957" + integrity sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA== dependencies: bs-logger "0.x" fast-json-stable-stringify "2.x" @@ -2739,9 +2703,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typescript@^4.4.3: - version "4.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" @@ -2749,9 +2713,9 @@ universalify@^0.1.0, universalify@^0.1.2: integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== v8-to-istanbul@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" - integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" @@ -2859,9 +2823,9 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.4.6: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== xml-name-validator@^3.0.0: version "3.0.0"