class CustomError extends Error {
name = 'CustomError'
constructor(message?: string) {
super(message)
Object.setPrototypeOf(this, CustomError.prototype)
}
}
try {
throw new CustomError('This is a custom error message.')
} catch (error) {
if (error instanceof CustomError) {
console.log('CustomError occurred:', error.message)
console.log('Error name:', error.name)
} else {
console.log('An error occurred:', error)
}
}
A practical functional library for JavaScript programmers.
Footnotes
-
자바스크립트에서 객체는 항상 참조를 통해 전달되므로 전달된 객체는 안전하지 않은 문제가 있어서 함수형 프로그래밍을 도입하고 ramda를 이용해서 읽기 쉽고 유지 관리하기 쉬운 코드를 작성한 예를 보여주고 있다. ↩
A toolkit for building rich-text editors on the web
Footnotes
-
NYT 편집기 Oak 팀이 React 와 ProseMirror 를 붙이다 겪은 문제와 해법. React 는 render → commit 2단계, ProseMirror 는 동기로 한 번에 DOM 을 고치고 브라우저 편집을 읽어 들이는 양방향이라,
useLayoutEffect로view.updateState()하면 좌표가 낡고 state tearing 이 난다. 결국EditorView를 상속해setProps를 부수효과 없는pureSetProps와runPendingEffects로 쪼개고 렌더러를 React 로 다시 썼다 (@handlewithcare/react-prosemirror). ↩ -
Oak 팀 교육 자료. ProseMirror 를 Redux + React 에 대응시킨다 —
EditorView= store, transaction = action(대부분 ProseMirror 가 입력에서 만든다), plugin = reducer 확장·subscribe,dispatchTransaction= middleware, node spec 의toDOM= 컴포넌트(0이 children 자리). ↩
enum LogLevel {
DEBUG = 'debug',
INFO = 'info',
WARN = 'warn',
ERROR = 'error',
}
type Message = string
class Logger {
private level: LogLevel
constructor(level: LogLevel = LogLevel.DEBUG) {
this.level = level
}
private log(level: LogLevel, message: Message) {
if (this.level === LogLevel.DEBUG || level !== LogLevel.DEBUG) {
const label = level.toUpperCase()
console.log(`[${label}] ${message}`)
}
}
/**
* - 개발 혹은 테스트 단계
* - 운영 환경에서는 남기고 싶지 않은 로그 메세지
*/
public debug(message: Message) {
this.log(LogLevel.DEBUG, message)
}
/**
* - 정상 작동에 대한 정보
* - 시스템을 파악하는데 유익한 정보
*/
public info(message: Message) {
this.log(LogLevel.INFO, message)
}
/**
* - 잠재적으로 문제가 될 수 있는 상황
* - 언제든 발생할 수 있는 일반적인 문제 상황
* - 사용자에게 노출되는 메세지에 상세한 가이드가 필요
*/
public warn(message: Message) {
this.log(LogLevel.WARN, message)
}
/**
* - 심각한 오류나 예외 상황
* - 즉시 조치가 필요할때
*/
public error(message: Message) {
this.log(LogLevel.ERROR, message)
}
}
import z from 'zod'
const envSchema = z.object({
REACT_APP_FEATURE_VAC_ASK: z.string(),
REACT_APP_FEATURE_RECORDS: z.string(),
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
})
const windowSchema = z.object({
SOMETHING_COOL: z.string()
})
export const ENV = envSchema.parse(process.env)
export const WINDOW = windowSchema.parse(window)
type Props = {
popover: 'auto' | 'manual'
popovertarget: string
popovertargetaction: 'hide' | 'show' | 'toggle'
}
type State = {
hasBackdrop: boolean
isPopoverOpen: boolean
}
type Methods = {
hidePopover: () => void
showPopover: () => void
togglePopover: () => void
}
type Events = {
beforetoggle: () => void
toggle: () => void
}
zodios는 ZodError를 ZodiosError.cause에 담아 던진다 — instanceof z.ZodError로는 안 잡힌다.
if (err instanceof ZodiosError && err.cause instanceof ZodError) {
console.log(fromZodError(err.cause).toString())
}
Swagger 2.0 스펙은 바로 못 먹인다. OpenAPI 3으로 바꾼 다음 zod 클라이언트를 만든다.
{
"scripts": {
"convert": "swagger2openapi ./spec.json -o ./spec.yaml",
"zod": "openapi-zod-client -a \"./spec.yaml\" -o \"./spec.ts\""
}
}
올린 뒤 배포물에서 지운다 — Datadog은 이미 받았고 브라우저에는 노출되지 않는다.
VERSION=$(git log --pretty=format:'%h' -n 1)
yarn datadog-ci sourcemaps upload ./build \
--service "$SERVICE" \
--minified-path-prefix "$MINIFIED_PATH_PREFIX" \
--release-version "$VERSION"
rm ./build/static/js/*.map
버스 팩터 — 한꺼번에 빠지면 프로젝트가 멈추는 최소 인원 수. 1이면 그 사람이 곧 단일 장애점.