npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

scribere

v1.1.5

Published

Logger core to be used in Javascript application

Downloads

8

Readme

scribere

Release Version License Downloads

🇪🇸 Lee la documentación en español aquí

scribĕre, to write in latin

Core logger library to be used in Javascript projects.

How to use

The main interface of the library is the Logger class which should be instantiated. The singleton pattern is not implemented so, in a shared context, you can use multiple instances working together.

const logger = new Logger()

The logger works with 4 severity levels:

const levels = ['log', 'debug', 'warn', 'error']

Each instance has 4 methods (one per severity level) which allows you logging messages.

Furthermore, the logger has 3 additional properties:

  • prefix: It is the fragment before the logging message. It could be a string or a function which returns a string.
  • severity: Indicates the severity level of the instance of the logger. It's a number indicating the index of the array of severity levels that is used as minimum:
    • 0 -> 'log', 'debug', 'warn', 'error'
    • 1 -> 'debug', 'warn', 'error'
    • 2 -> 'warn', 'error'
    • 3 -> 'error'
  • strategy: Defines how the trace is really managed. The idea is to provide flexibility to use the strategy provided by the core or create a custom one which allows you to cover your requirements, for example, upload the traces to some remote server. It is an instance of a class which implements the LoggerStrategy interface. There is more information about it later on the text.

These 3 properties can be defined when the logger is instantiated, through the constructor:

  • options: Defines the prefix and severity. By default:
{
  prefix: new Date().toISOString(),
  severity: 0
}
  • strategy: Defines the strategy, by default ConsoleLoggerStrategy which mainly prints on browser console the trace, adjusting the severity and formatting it with: PREFIX :: LEVEL :: data
const loggerWithOptions = new Logger(options)

These properties can be changed once the logger is instantiated because they are accesibles.

Custom strategies

The logger uses the Strategy pattern, delegating what to do in the defined strategy.

By default, the ConsoleLoggerStrategy strategy is offered but you can code your own strategies following your needs.

You have to create a class implementing the LoggerStrategy strategy which forces you to implement the trace method that will be executed by the log, debug, warn and error method of the logger when the configured severity allows the print of the trace.

class CustomStrategy implements LoggerStrategy {

  trace(
    data: any,
    level: 'log' | 'debug' | 'warn' | 'error',
    instance: ILogger
  ) {
    // Implementation
    const prefix =
      typeof instance.prefix === 'function'
        ? instance.prefix()
        : instance.prefix
    alert(`${level} : ${prefix} - ${data})
  }

}

Once the strategy is created, you would select it in the instance process of the logger:

const loggerWithCustomStrategy = new Logger(options, new CustomStrategy())

Use it with SPA frameworks

The design of scribere tries to create a simple logger, agnostic of the SPA framework used. Following, some examples of integrations with SPA frameworks are provided:

React

In React, the use of scribere is straightforward; you can import it directly in the components and utilities which would use it.

Following, an implementation where the severity is retrieved from local storage is shown, but it is completely opcional.

- src
|-- logger
  |-- index.js

index.js

import {Logger} from 'scribere'

const ReactLogger = new Logger()

/* Starting Extra optional configuration */
const severity = localStorage.getItem('LOGGER')
let severityLevel
if (severity === null) {
  localStorage.setItem('LOGGER', '2')
  severityLevel = 2
} else {
  severityLevel = Number(severity)
}
ReactLogger.severity = severityLevel
/* Ending Extra optional configuration */

export default ReactLogger

From this point, importing ReactLogger where a log is required would be enough. This strategy of "pre-configuring" the logger should be followed when a configuration differ from the default one.

Vue

- src
|-- main.js
|-- logger
  |-- index.js
  |-- install.js

index.js

import install from './install'

const Log4Vue = {installed: false}
Log4Vue.install = install

export default Log4Vue

install.js

import {Logger} from 'scribere'

export default function install(Vue, options = undefined) {
  if (this.installed) return
  const logger = options ? new Logger(options) : new Logger()
  // The logger will be accesible in this.$console
  Vue.prototype.$console = logger
  Vue.console = logger
  window.logger = logger
  this.installed = true
}

This implementation of the logger follows the "plugin" pattern so the plugin should be declared before the application starts.

main.js

import Vue from 'vue'
import VueLogger from './logger'

Vue.use(VueLogger)

new Vue({
  //... options
})

Optionally, you can use custom options:

Vue.use(VueLogger, {
  severity: 2,
})

Angular

Although Angular could follow similar strategies to other frameworks (specially React), I think the service pattern is the closest to the "Angular philosophy".

For that:

import {Injectable} from '@angular/core'
import {Logger, ILogger, LoggerOptions} from 'scribere'

@Injectable({
  providedIn: 'root',
})
export class LoggerService {
  private _instance: ILogger

  constructor() {
    const options: LoggerOptions = {
      severity: 2,
    }
    this._instance = new Logger(options)
  }

  debug(...args: any[]) {
    return this._instance.debug(...args)
  }
  error(...args: any[]) {
    return this._instance.error(...args)
  }
  log(...args: any[]) {
    return this._instance.log(...args)
  }
  warn(...args: any[]) {
    return this._instance.warn(...args)
  }
}

Even though this is the most simple implementation, you could want to inject the options instead of define them in the constructor. For that, I think the best way would be to use the inject mechanism of Angular and its "providers".

This documentation does not try to deep on any specific implementation for any framework but, as reference, the implementation should be something similar to:

export const LOGGER_CONFIG = new InjectionToken<LoggerOptions>('app.logger');

@Injectable({
  providedIn: 'root',
})
export class LoggerService {
  ...

  constructor(@Inject(LOGGER_CONFIG) options: LoggerOptions) {
    this._instance = new Logger(options);
  }

  ...

}
@NgModule({
...
providers: [LoggerService, { provide: LOGGER_CONFIG, useValue: { /* options */ } }]
...
}

Starting 🚀

Following these steps you will have a copy of the project working on your local machine.

Check Deployment to know how to deploy the project.

Pre-requirements 📋

You will need Node (v10.15.3) and npm (v6.4.1) installed and Yarn. Upper versions could work but they aren't tested.

Install 🔧

In the root of the project, you should execute:

yarn

Testing ⚙️

yarn test

Under the hood, you will be executing jest so any parameter could be added following its documentation.

Linting ⌨️

The project is using eslint to ensure the code quality as well as the standardization of code between developers.

yarn lint

You can try to fix lint errors automatically using:

yarn lint:fix

Built with 🛠️

Contributing 🖇️

Please, read CONTRIBUTING.md which provides details about the code of conduct and the process to include pull requests.

Versioning 📌

The project uses SemVer for versioning. You can check all available versions in the tags of this repository.

Authors ✒️