mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-03-30 04:23:03 -04:00
Add pretty formatting (#29)
* Test * Add pretty formatting * Fix Tests * Fix Tests * Fix Tests * Fix * Add pretty formatting fix * Fix * Test * Fix tests * Clean typeckech * Add prettier check * Fix api tsconfig * Fix api tsconfig * Fix tsconfig * Fix * Fix * Prettier
This commit is contained in:
@@ -1,8 +1,4 @@
|
||||
export function binarySearch(
|
||||
min: number,
|
||||
max: number,
|
||||
comparator: (x: number) => number
|
||||
) {
|
||||
export function binarySearch(min: number, max: number, comparator: (x: number) => number) {
|
||||
let mid = 0
|
||||
let i = 0
|
||||
while (true) {
|
||||
@@ -22,8 +18,7 @@ export function binarySearch(
|
||||
i++
|
||||
if (i > 100000) {
|
||||
throw new Error(
|
||||
'Binary search exceeded max iterations' +
|
||||
JSON.stringify({ min, max, mid, i }, null, 2)
|
||||
'Binary search exceeded max iterations' + JSON.stringify({min, max, mid, i}, null, 2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { API, APIParams, APIPath, APIResponse } from 'common/api/schema'
|
||||
import { APIError, getApiUrl } from 'common/api/utils'
|
||||
import { forEach } from 'lodash'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { User } from 'firebase/auth'
|
||||
import {API, APIParams, APIPath, APIResponse} from 'common/api/schema'
|
||||
import {APIError, getApiUrl} from 'common/api/utils'
|
||||
import {removeUndefinedProps} from 'common/util/object'
|
||||
import {User} from 'firebase/auth'
|
||||
import {forEach} from 'lodash'
|
||||
|
||||
export function unauthedApi<P extends APIPath>(path: P, params: APIParams<P>) {
|
||||
return typedAPICall(path, params, null)
|
||||
@@ -11,7 +11,7 @@ export function unauthedApi<P extends APIPath>(path: P, params: APIParams<P>) {
|
||||
export const typedAPICall = <P extends APIPath>(
|
||||
path: P,
|
||||
params: APIParams<P>,
|
||||
user: User | null
|
||||
user: User | null,
|
||||
) => {
|
||||
// parse any params that should part of the path (like market/:id)
|
||||
const newParams: any = {}
|
||||
@@ -51,7 +51,7 @@ export async function baseApiCall(props: {
|
||||
params: any
|
||||
user: User | null
|
||||
}) {
|
||||
const { url, method, params, user } = props
|
||||
const {url, method, params, user} = props
|
||||
|
||||
const actualUrl = method === 'POST' ? url : appendQuery(url, params)
|
||||
const headers: HeadersInit = {
|
||||
@@ -64,12 +64,11 @@ export async function baseApiCall(props: {
|
||||
const req = new Request(actualUrl, {
|
||||
headers,
|
||||
method: method,
|
||||
body:
|
||||
params == null || method === 'GET' ? undefined : JSON.stringify(params),
|
||||
body: params == null || method === 'GET' ? undefined : JSON.stringify(params),
|
||||
})
|
||||
// console.log('Request', req)
|
||||
return fetch(req).then(async (resp) => {
|
||||
const json = (await resp.json()) as { [k: string]: any }
|
||||
const json = (await resp.json()) as {[k: string]: any}
|
||||
if (!resp.ok) {
|
||||
throw new APIError(resp.status as any, json?.message, json?.details)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { compact, flattenDeep, isEqual } from 'lodash'
|
||||
import {compact, flattenDeep, isEqual} from 'lodash'
|
||||
|
||||
export const arrify = <T>(maybeArr: T | T[]) =>
|
||||
Array.isArray(maybeArr) ? maybeArr : [maybeArr]
|
||||
export const arrify = <T>(maybeArr: T | T[]) => (Array.isArray(maybeArr) ? maybeArr : [maybeArr])
|
||||
|
||||
export function filterDefined<T>(array: (T | null | undefined)[]) {
|
||||
return array.filter((item) => item !== null && item !== undefined) as T[]
|
||||
@@ -19,12 +18,12 @@ export function groupConsecutive<T, U>(xs: T[], key: (x: T) => U) {
|
||||
return []
|
||||
}
|
||||
const result = []
|
||||
let curr = { key: key(xs[0]), items: [xs[0]] }
|
||||
let curr = {key: key(xs[0]), items: [xs[0]]}
|
||||
for (const x of xs.slice(1)) {
|
||||
const k = key(x)
|
||||
if (!isEqual(k, curr.key)) {
|
||||
result.push(curr)
|
||||
curr = { key: k, items: [x] }
|
||||
curr = {key: k, items: [x]}
|
||||
} else {
|
||||
curr.items.push(x)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const cleanUsername = (name: string, maxLength = 25) => {
|
||||
// Test guidance: do not mock this method (pure, deterministic transformations with no side effects)
|
||||
return name
|
||||
.replace(/\s+/g, '')
|
||||
.normalize('NFD') // split an accented letter in the base letter and the accent
|
||||
@@ -8,5 +9,6 @@ export const cleanUsername = (name: string, maxLength = 25) => {
|
||||
}
|
||||
|
||||
export const cleanDisplayName = (displayName: string, maxLength = 30) => {
|
||||
// Test guidance: do not mock this method (pure, deterministic transformations with no side effects)
|
||||
return displayName.replace(/\s+/g, ' ').substring(0, maxLength).trim()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { sortBy, sum } from 'lodash'
|
||||
import {sortBy, sum} from 'lodash'
|
||||
|
||||
export const logInterpolation = (min: number, max: number, value: number) => {
|
||||
if (value <= min) return 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { max, sumBy } from 'lodash'
|
||||
import {max, sumBy} from 'lodash'
|
||||
|
||||
// each row has [column, value] pairs
|
||||
type SparseMatrix = [number, number][][]
|
||||
@@ -23,7 +23,7 @@ export function factorizeMatrix(
|
||||
ITERS = 5000,
|
||||
LEARNING_RATE = 0.0002,
|
||||
REGULARIZATION_RATE = 0.02,
|
||||
THRESHOLD = 0.001
|
||||
THRESHOLD = 0.001,
|
||||
) {
|
||||
const initCell = () => (2 * Math.random()) / FEATURES
|
||||
const m = TARGET_MATRIX.length
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isEqual, mapValues, union } from 'lodash'
|
||||
import {isEqual, mapValues, union} from 'lodash'
|
||||
|
||||
export const removeUndefinedProps = <T extends object>(obj: T): T => {
|
||||
const newObj: any = {}
|
||||
@@ -9,10 +9,7 @@ export const removeUndefinedProps = <T extends object>(obj: T): T => {
|
||||
|
||||
return newObj
|
||||
}
|
||||
export const removeNullOrUndefinedProps = <T extends object>(
|
||||
obj: T,
|
||||
exceptions?: string[]
|
||||
): T => {
|
||||
export const removeNullOrUndefinedProps = <T extends object>(obj: T, exceptions?: string[]): T => {
|
||||
const newObj: any = {}
|
||||
|
||||
for (const key of Object.keys(obj)) {
|
||||
@@ -25,10 +22,7 @@ export const removeNullOrUndefinedProps = <T extends object>(
|
||||
return newObj
|
||||
}
|
||||
|
||||
export const addObjects = <T extends { [key: string]: number }>(
|
||||
obj1: T,
|
||||
obj2: T
|
||||
) => {
|
||||
export const addObjects = <T extends {[key: string]: number}>(obj1: T, obj2: T) => {
|
||||
const keys = union(Object.keys(obj1), Object.keys(obj2))
|
||||
const newObj = {} as any
|
||||
|
||||
@@ -39,10 +33,7 @@ export const addObjects = <T extends { [key: string]: number }>(
|
||||
return newObj as T
|
||||
}
|
||||
|
||||
export const subtractObjects = <T extends { [key: string]: number }>(
|
||||
obj1: T,
|
||||
obj2: T
|
||||
) => {
|
||||
export const subtractObjects = <T extends {[key: string]: number}>(obj1: T, obj2: T) => {
|
||||
const keys = union(Object.keys(obj1), Object.keys(obj2))
|
||||
const newObj = {} as any
|
||||
|
||||
@@ -61,18 +52,14 @@ export const hasChanges = <T extends object>(obj: T, partial: Partial<T>) => {
|
||||
export const hasSignificantDeepChanges = <T extends object>(
|
||||
obj: T,
|
||||
partial: Partial<T>,
|
||||
epsilonForNumbers: number
|
||||
epsilonForNumbers: number,
|
||||
): boolean => {
|
||||
const compareValues = (currValue: any, partialValue: any): boolean => {
|
||||
if (typeof currValue === 'number' && typeof partialValue === 'number') {
|
||||
return Math.abs(currValue - partialValue) > epsilonForNumbers
|
||||
}
|
||||
if (typeof currValue === 'object' && typeof partialValue === 'object') {
|
||||
return hasSignificantDeepChanges(
|
||||
currValue,
|
||||
partialValue,
|
||||
epsilonForNumbers
|
||||
)
|
||||
return hasSignificantDeepChanges(currValue, partialValue, epsilonForNumbers)
|
||||
}
|
||||
return !isEqual(currValue, partialValue)
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import {DOMAIN} from 'common/envs/constants'
|
||||
export function buildOgUrl<P extends Record<string, string>>(
|
||||
props: P,
|
||||
endpoint: string,
|
||||
domain?: string
|
||||
domain?: string,
|
||||
) {
|
||||
const generateUrlParams = (params: P) =>
|
||||
new URLSearchParams(params).toString()
|
||||
const generateUrlParams = (params: P) => new URLSearchParams(params).toString()
|
||||
|
||||
return `https://${domain ?? DOMAIN}/api/og/${endpoint}?` + generateUrlParams(props)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import {getSchema, getText, getTextSerializersFromSchema, JSONContent,} from '@tiptap/core'
|
||||
import {Node as ProseMirrorNode} from '@tiptap/pm/model'
|
||||
import {StarterKit} from '@tiptap/starter-kit'
|
||||
import {getSchema, getText, getTextSerializersFromSchema, JSONContent} from '@tiptap/core'
|
||||
import {Image} from '@tiptap/extension-image'
|
||||
import {Link} from '@tiptap/extension-link'
|
||||
import {Mention} from '@tiptap/extension-mention'
|
||||
import Iframe from './tiptap-iframe'
|
||||
import {Node as ProseMirrorNode} from '@tiptap/pm/model'
|
||||
import {StarterKit} from '@tiptap/starter-kit'
|
||||
import {find} from 'linkifyjs'
|
||||
import {uniq} from 'lodash'
|
||||
import {compareTwoStrings} from 'string-similarity'
|
||||
|
||||
import Iframe from './tiptap-iframe'
|
||||
|
||||
/** get first url in text. like "notion.so " -> "http://notion.so" "notion" -> null */
|
||||
export function getUrl(text: string) {
|
||||
const results = find(text, 'url')
|
||||
@@ -46,8 +47,7 @@ export const extensions = [
|
||||
Image.extend({renderText: () => '[image]'}),
|
||||
Mention, // user @mention
|
||||
Iframe.extend({
|
||||
renderText: ({node}) =>
|
||||
'[embed]' + node.attrs.src ? `(${node.attrs.src})` : '',
|
||||
renderText: ({node}) => ('[embed]' + node.attrs.src ? `(${node.attrs.src})` : ''),
|
||||
}),
|
||||
]
|
||||
|
||||
@@ -76,7 +76,7 @@ export function urlBase64ToUint8Array(base64String: string) {
|
||||
const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
|
||||
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
|
||||
const rawData = window.atob(base64)
|
||||
return new Uint8Array([...rawData].map(c => c.charCodeAt(0)))
|
||||
return new Uint8Array([...rawData].map((c) => c.charCodeAt(0)))
|
||||
}
|
||||
|
||||
export function cleanDoc(doc: JSONContent) {
|
||||
@@ -89,52 +89,53 @@ export function cleanDoc(doc: JSONContent) {
|
||||
}
|
||||
|
||||
function _cleanDoc(doc: JSONContent) {
|
||||
if (!doc || !Array.isArray(doc.content)) return doc;
|
||||
if (!doc || !Array.isArray(doc.content)) return doc
|
||||
|
||||
let content = [...doc.content];
|
||||
let content = [...doc.content]
|
||||
|
||||
const isEmptyParagraph = (node: JSONContent) =>
|
||||
node.type === "paragraph" &&
|
||||
(!node.content || node.content.length === 0);
|
||||
node.type === 'paragraph' && (!node.content || node.content.length === 0)
|
||||
|
||||
// Remove empty paragraphs at the start
|
||||
while (content.length > 0 && isEmptyParagraph(content[0])) {
|
||||
content.shift();
|
||||
content.shift()
|
||||
}
|
||||
|
||||
// Remove empty paragraphs at the end
|
||||
while (content.length > 0 && isEmptyParagraph(content[content.length - 1])) {
|
||||
content.pop();
|
||||
content.pop()
|
||||
}
|
||||
|
||||
// Trim leading/trailing hardBreaks within first and last paragraphs
|
||||
const trimHardBreaks = (paragraph: JSONContent, start: boolean, end: boolean) => {
|
||||
if (!paragraph.content) return paragraph;
|
||||
if (!paragraph.content) return paragraph
|
||||
|
||||
const nodes = [...paragraph.content];
|
||||
const nodes = [...paragraph.content]
|
||||
|
||||
// Remove hardBreaks at the start
|
||||
while (start && nodes.length > 0 && nodes[0].type === "hardBreak") {
|
||||
nodes.shift();
|
||||
while (start && nodes.length > 0 && nodes[0].type === 'hardBreak') {
|
||||
nodes.shift()
|
||||
}
|
||||
|
||||
// Remove hardBreaks at the end
|
||||
while (end && nodes.length > 0 && nodes[nodes.length - 1].type === "hardBreak") {
|
||||
nodes.pop();
|
||||
while (end && nodes.length > 0 && nodes[nodes.length - 1].type === 'hardBreak') {
|
||||
nodes.pop()
|
||||
}
|
||||
|
||||
return { ...paragraph, content: nodes };
|
||||
};
|
||||
return {...paragraph, content: nodes}
|
||||
}
|
||||
|
||||
if (content.length > 0) {
|
||||
content[0] = trimHardBreaks(content[0], true, false);
|
||||
content[0] = trimHardBreaks(content[0], true, false)
|
||||
if (content.length > 1) {
|
||||
content[content.length - 1] = trimHardBreaks(content[content.length - 1], false, true);
|
||||
content[content.length - 1] = trimHardBreaks(content[content.length - 1], false, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any now-empty paragraphs created by hardBreak trimming
|
||||
content = content.filter(node => !(node.type === "paragraph" && (!node.content || node.content.length === 0)));
|
||||
content = content.filter(
|
||||
(node) => !(node.type === 'paragraph' && (!node.content || node.content.length === 0)),
|
||||
)
|
||||
|
||||
return { ...doc, content };
|
||||
return {...doc, content}
|
||||
}
|
||||
|
||||
@@ -29,15 +29,13 @@ export async function withRetries<T>(q: PromiseLike<T>, policy?: RetryPolicy) {
|
||||
export const mapAsyncChunked = async <T, U>(
|
||||
items: T[],
|
||||
f: (item: T, index: number) => Promise<U>,
|
||||
chunkSize = 100
|
||||
chunkSize = 100,
|
||||
) => {
|
||||
const results: U[] = []
|
||||
|
||||
for (let i = 0; i < items.length; i += chunkSize) {
|
||||
const chunk = items.slice(i, i + chunkSize)
|
||||
const chunkResults = await Promise.all(
|
||||
chunk.map((item, index) => f(item, i + index))
|
||||
)
|
||||
const chunkResults = await Promise.all(chunk.map((item, index) => f(item, i + index)))
|
||||
results.push(...chunkResults)
|
||||
}
|
||||
|
||||
@@ -47,7 +45,7 @@ export const mapAsyncChunked = async <T, U>(
|
||||
export const mapAsync = <T, U>(
|
||||
items: T[],
|
||||
f: (item: T, index: number) => Promise<U>,
|
||||
maxConcurrentRequests = 100
|
||||
maxConcurrentRequests = 100,
|
||||
) => {
|
||||
let index = 0
|
||||
let currRequests = 0
|
||||
|
||||
@@ -7,7 +7,7 @@ export function genHash(str: string) {
|
||||
// xmur3
|
||||
|
||||
// Route around compiler bug by using object?
|
||||
const o = { h: 1779033703 ^ str.length }
|
||||
const o = {h: 1779033703 ^ str.length}
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let h = o.h
|
||||
@@ -51,4 +51,4 @@ export const shuffle = (array: unknown[], rand: () => number) => {
|
||||
const swapIndex = i + Math.floor(rand() * (array.length - i))
|
||||
;[array[i], array[swapIndex]] = [array[swapIndex], array[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
export const slugify = (
|
||||
text: string,
|
||||
separator = '-',
|
||||
maxLength = 35
|
||||
): string => {
|
||||
export const slugify = (text: string, separator = '-', maxLength = 35): string => {
|
||||
return text
|
||||
.toString()
|
||||
.normalize('NFD') // split an accented letter in the base letter and the acent
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {MAX_INT} from "common/constants";
|
||||
import {MAX_INT} from 'common/constants'
|
||||
|
||||
export function getSortedOptions(options: string[], order: string[] | Record<string, string>) {
|
||||
let parsedOrder: string[]
|
||||
@@ -7,14 +7,12 @@ export function getSortedOptions(options: string[], order: string[] | Record<str
|
||||
} else {
|
||||
parsedOrder = Object.keys(order)
|
||||
}
|
||||
return options
|
||||
.slice()
|
||||
.sort((a, b) => {
|
||||
const ia = parsedOrder.indexOf(a as any)
|
||||
const ib = parsedOrder.indexOf(b as any)
|
||||
const sa = ia === -1 ? MAX_INT : ia
|
||||
const sb = ib === -1 ? MAX_INT : ib
|
||||
if (sa !== sb) return sa - sb
|
||||
return String(a).localeCompare(String(b))
|
||||
});
|
||||
}
|
||||
return options.slice().sort((a, b) => {
|
||||
const ia = parsedOrder.indexOf(a as any)
|
||||
const ib = parsedOrder.indexOf(b as any)
|
||||
const sa = ia === -1 ? MAX_INT : ia
|
||||
const sb = ib === -1 ? MAX_INT : ib
|
||||
if (sa !== sb) return sa - sb
|
||||
return String(a).localeCompare(String(b))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export function removeEmojis(str: string) {
|
||||
return str.replace(
|
||||
// eslint-disable-next-line no-misleading-character-class
|
||||
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{2300}-\u{23FF}\u{2B50}\u{2B55}\u{2934}\u{2935}\u{2B05}\u{2B06}\u{2B07}\u{2B1B}\u{2B1C}\u{2B50}\u{2B55}\u{3030}\u{303D}\u{3297}\u{3299}\u{FE0F}]/gu,
|
||||
''
|
||||
'',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,4 @@ export const MONTH_MS = 30 * DAY_MS
|
||||
export const YEAR_MS = 365 * DAY_MS
|
||||
export const HOUR_SECONDS = 60 * 60
|
||||
|
||||
export const sleep = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms))
|
||||
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Adopted from https://github.com/ueberdosis/tiptap/blob/main/demos/src/Experiments/Embeds/Vue/iframe.ts
|
||||
|
||||
import { Node, mergeAttributes } from '@tiptap/core'
|
||||
import {mergeAttributes, Node} from '@tiptap/core'
|
||||
|
||||
export interface IframeOptions {
|
||||
HTMLAttributes: {
|
||||
@@ -11,7 +11,7 @@ export interface IframeOptions {
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
iframe: {
|
||||
setIframe: (options: { src: string }) => ReturnType
|
||||
setIframe: (options: {src: string}) => ReturnType
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,15 +46,12 @@ export default Node.create<IframeOptions>({
|
||||
},
|
||||
|
||||
parseHTML() {
|
||||
return [{ tag: 'iframe' }]
|
||||
return [{tag: 'iframe'}]
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
const iframeAttributes = mergeAttributes(
|
||||
this.options.HTMLAttributes,
|
||||
HTMLAttributes
|
||||
)
|
||||
const { src } = HTMLAttributes
|
||||
renderHTML({HTMLAttributes}) {
|
||||
const iframeAttributes = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
|
||||
const {src} = HTMLAttributes
|
||||
|
||||
// This is a hack to prevent native from opening the iframe in an in-app browser
|
||||
// and mobile in another tab. In native, links with target='_blank' open in the in-app browser.
|
||||
@@ -93,9 +90,9 @@ export default Node.create<IframeOptions>({
|
||||
addCommands() {
|
||||
return {
|
||||
setIframe:
|
||||
(options: { src: string }) =>
|
||||
({ tr, dispatch }) => {
|
||||
const { selection } = tr
|
||||
(options: {src: string}) =>
|
||||
({tr, dispatch}) => {
|
||||
const {selection} = tr
|
||||
const node = this.type.create(options)
|
||||
|
||||
if (dispatch) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const tryCatch = async <T, E = Error>(promise: Promise<T>) => {
|
||||
try {
|
||||
return { data: await promise, error: null }
|
||||
return {data: await promise, error: null}
|
||||
} catch (e) {
|
||||
return { data: null, error: e as E }
|
||||
return {data: null, error: e as E}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
export function assertUnreachable(x: never, message?: string): never {
|
||||
if (message) throw new Error(message)
|
||||
throw new Error(
|
||||
`Expected unreachable value, instead got: ${JSON.stringify(x)}`
|
||||
)
|
||||
throw new Error(`Expected unreachable value, instead got: ${JSON.stringify(x)}`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user