Skip to content

Commit

Permalink
Merge pull request #13 from crashmax-dev/feat/logger
Browse files Browse the repository at this point in the history
feat(packages): add `@stenodb/logger`
  • Loading branch information
crashmax-dev authored Feb 8, 2023
2 parents 3c0fd92 + 0fb4731 commit 58aba3e
Show file tree
Hide file tree
Showing 36 changed files with 532 additions and 112 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
.env
.DS_Store
**/database
**/logs
**/temp
12 changes: 12 additions & 0 deletions examples/with-logger/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>with-logger</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/index.ts"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions examples/with-logger/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "with-logger",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"typescript": "4.9.5",
"vite": "4.1.1"
},
"dependencies": {
"@stenodb/browser": "workspace:*",
"@stenodb/logger": "workspace:*",
"@zero-dependency/dom": "0.12.0",
"class-transformer": "0.5.1",
"reflect-metadata": "0.1.13"
}
}
32 changes: 32 additions & 0 deletions examples/with-logger/src/entities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Type } from 'class-transformer'

export class Users {
@Type(() => User)
users: User[]

constructor(...users: User[]) {
this.users = users
}

addUser(user: User): void {
this.users.push(user)
}

getLastUserId(): number {
return this.users!.at(-1)!.id
}
}

export class User {
id: number
username: string

constructor(id: number, username: string) {
this.id = id
this.username = username
}

changeUsername(username: string): void {
this.username = username
}
}
72 changes: 72 additions & 0 deletions examples/with-logger/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'reflect-metadata'
import { el } from '@zero-dependency/dom'
import { User } from './entities.js'
import { storage } from './storage.js'

const app = document.querySelector('#app')!

const userIdInput = el('input', {
type: 'number',
name: 'id',
disabled: true
})

const usernameInput = el('input', {
type: 'text',
name: 'username',
placeholder: 'Username'
})

const submitButton = el(
'button',
{
type: 'submit'
},
'Submit'
)

const resetButton = el(
'button',
{
onclick: () => {
storage.reset()
render()
}
},
'Reset'
)

const form = el(
'form',
{
onsubmit: (event: Event) => {
event.preventDefault()
const formData = new FormData(form)
const username = formData.get('username')?.toString()
if (!username) {
usernameInput.focus()
return
}
const user = new User(storage.data!.getLastUserId() + 1, username)
storage.data!.addUser(user)
storage.write()
render()
}
},
userIdInput,
usernameInput,
submitButton,
resetButton
)

const storagePreview = el('pre')

function render() {
form.reset()
usernameInput.focus()
userIdInput.value = storage.data!.getLastUserId().toString()
storagePreview.textContent = JSON.stringify(storage.data, null, 2)
}

render()
app.append(form, storagePreview)
10 changes: 10 additions & 0 deletions examples/with-logger/src/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BrowserProvider, LocalStorage } from '@stenodb/browser'
import { createLogger } from '@stenodb/logger'
import { User, Users } from './entities.js'

const initialData = new Users(new User(1, 'John'))
const adapter = new LocalStorage('users', Users, initialData)
const provider = new BrowserProvider({ logger: createLogger() })

export const storage = provider.create(adapter)
storage.read()
1 change: 1 addition & 0 deletions examples/with-logger/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
22 changes: 22 additions & 0 deletions examples/with-logger/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true,
"strictPropertyInitialization": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src"]
}
1 change: 1 addition & 0 deletions examples/with-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build": "del-cli dist && tsc"
},
"dependencies": {
"@stenodb/logger": "workspace:*",
"@stenodb/node": "workspace:*",
"class-transformer": "0.5.1",
"reflect-metadata": "0.1.13"
Expand Down
13 changes: 12 additions & 1 deletion examples/with-node/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import 'reflect-metadata'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { createLogger } from '@stenodb/logger'
import { createRotation } from '@stenodb/logger/rotation'
import { AsyncAdapter, NodeProvider } from '@stenodb/node'
import { Post, User, Users } from './entities.js'

const path = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'database')
const logger = createLogger({
rotation: createRotation({
path: 'logs',
size: '10M', // rotate every 10 MegaBytes written
interval: '1d', // rotate daily
compress: 'gzip' // compress rotated files
})
})

const initialData = new Users(new User('John Doe'))
const adapter = new AsyncAdapter('users', Users, initialData)
const provider = new NodeProvider(path)
const provider = new NodeProvider(path, { logger })

const database = provider.createAsync(adapter)
await database.read()
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"nodemon": "2.0.20",
"ts-node": "10.9.1",
"tsx": "3.12.3",
"turbo": "1.7.3",
"turbo": "1.7.4",
"typescript": "4.9.5"
},
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
"prepublishOnly": "pnpm build"
},
"dependencies": {
"@stenodb/utils": "workspace:3.0.0",
"class-transformer": "0.5.1"
"@stenodb/logger": "workspace:3.0.0",
"@stenodb/utils": "workspace:3.0.0"
},
"peerDependencies": {
"class-transformer": ">=0.5.0"
Expand Down
30 changes: 16 additions & 14 deletions packages/browser/src/adapter/WebStorage.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { parseData } from '@stenodb/utils'
import { plainToClass } from 'class-transformer'
import { dataTransformer, entityTransformer } from '@stenodb/utils'
import type { Steno } from '../types.js'
import type { BaseLogger } from '@stenodb/logger'
import type { DataTransformer, EntityTransformer } from '@stenodb/utils'

export class BrowserStorage<T> {
name: string
storage: Storage
entity: Steno.Entity<T>
logger: BaseLogger | undefined

entityTransformer: EntityTransformer<T>
dataTransformer: DataTransformer<T>

data: T | null = null
initialData: T | null = null
Expand All @@ -18,34 +22,32 @@ export class BrowserStorage<T> {
) {
this.name = name
this.storage = storage
this.entity = entity
this.entityTransformer = entityTransformer(entity)
this.dataTransformer = dataTransformer(this.entityTransformer)

if (initialData) {
this.initialData = initialData
}
}

plainData(data: T | string | null = this.data): T | null {
if (!data) return null

const parsedData =
typeof data === 'string' ? parseData<T>(data).toJSON() : data

return plainToClass(this.entity, parsedData)
registerLogger(logger: BaseLogger): void {
this.logger = logger
}

read(): void {
const data = this.storage.getItem(this.name)
this.data = data ? this.plainData(data) : null
this.data = this.dataTransformer.toJSON(data)
this.logger?.info('Read data:', this.data)
}

write(): void {
this.storage.setItem(this.name, parseData(this.data).toString())
this.storage.setItem(this.name, this.dataTransformer.toString(this.data))
this.logger?.info('Write data:', this.data)
}

reset(): void {
if (!this.initialData) return
this.data = plainToClass(this.entity, this.initialData)
this.data = this.entityTransformer(this.initialData)
this.write()
}

Expand Down
16 changes: 16 additions & 0 deletions packages/browser/src/provider/BrowserProvider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import { StorageProvider } from './StorageProvider.js'
import type { Steno } from '../types.js'
import type { CreateLogger } from '@stenodb/logger'

export class BrowserProvider {
#options: Steno.BrowserProviderOptions | undefined
#logger: CreateLogger

constructor(options?: Steno.BrowserProviderOptions) {
this.#options = options
this.#logger = options?.logger
}

private registerAdapterModules<T>(adapter: Steno.BrowserAdapter<T>) {
if (!this.#logger) return
const logger = this.#logger(adapter.name)
adapter.registerLogger(logger)
}

create<T>(adapter: Steno.BrowserAdapter<T>): StorageProvider<T> {
this.registerAdapterModules(adapter)
return new StorageProvider(adapter)
}
}
2 changes: 0 additions & 2 deletions packages/browser/src/provider/StorageProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export class StorageProvider<T> extends BaseProvider<T> {

if (!this.data) {
this.reset()
} else {
this.data = this.#adapter.plainData()
}

return this.data
Expand Down
5 changes: 5 additions & 0 deletions packages/browser/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import type { LocalStorage } from './adapter/LocalStorage.js'
import type { SessionStorage } from './adapter/SessionStorage.js'
import type { StorageProvider } from './provider/StorageProvider.js'
import type { CreateLogger } from '@stenodb/logger'
import type { ClassConstructor } from 'class-transformer'

export namespace Steno {
export type Entity<T> = ClassConstructor<T>
export type BrowserAdapter<T> = LocalStorage<T> | SessionStorage<T>
export type BrowserProvider<T> = StorageProvider<T>

export interface BrowserProviderOptions {
logger?: CreateLogger
}
}
35 changes: 35 additions & 0 deletions packages/logger/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@stenodb/logger",
"version": "3.0.0",
"type": "module",
"files": [
"dist"
],
"types": "dist",
"typesVersions": {
"*": {
"rotation": [
"./dist/rotation.d.ts"
]
}
},
"exports": {
".": "./dist/index.js",
"./rotation": "./dist/rotation.js"
},
"scripts": {
"dev": "tsc --watch",
"build": "del-cli dist && tsc",
"prepublishOnly": "pnpm build"
},
"devDependencies": {
"@types/node": "18.11.19"
},
"engines": {
"node": ">=14.16"
},
"dependencies": {
"rotating-file-stream": "3.0.4",
"tslog": "4.7.2"
}
}
2 changes: 2 additions & 0 deletions packages/logger/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './logger.js'
export * from './types.js'
Loading

0 comments on commit 58aba3e

Please sign in to comment.