New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@chatally/core

Package Overview
Dependencies
Maintainers
0
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chatally/core - npm Package Compare versions

Comparing version
0.0.6
to
0.0.7
+224
lib/index.d.ts
import type { Level, Logger } from "@chatally/logger";
import { EventEmitter } from "node:events";
import type { Message } from "./messages.d.ts";
/**
* ChatAlly Application Class
*
* Dispatches incoming requests to registered middleware.
*/
export declare class Application<D extends Object> extends EventEmitter<
ApplicationEvents<D>
> {
/**
* Create a Chatally application that dispatches incoming chat requests from
* all registered servers to all registered middleware.
*/
constructor(options?: ApplicationOptions<D>);
/**
* Register a Middleware or a Server
*
* Middlewares are executed in order of registration, but can `await next()`
* to wait for the following middlewares to finish.
*
* It is preferrable to use a named function over an arrow function, because
* the name is used to identify child loggers. Optionally, you can provide a
* name for the middleware.
*
* @param m Middleware or server.
* @param name [Optional] Name for the registered module.
* @returns `this`
*/
use(m: Middleware<D> | Server, name?: string): this;
/**
* Start all registered servers in parallel.
*
* @returns never
*/
listen(): void;
/**
* Asynchronous Method to Trigger Request Handling
*
* The application will pass request and response as context to each
* middleware. The application will handle all uncaught errors within a
* callback. The callback will resolve after the last middleware finished,
* but a server could send responses earlier, by registering the
* `on("finish")` event on the response.
*
* @returns a bound dispatch method
*/
get dispatch(): Dispatch;
/**
* Get a child logger.
*
* @param name Name of the child logger
* @param level [Optional] Log level other than parent level
* @returns A child logger
*/
getLogger(name: string, level?: Level): Logger;
}
type ApplicationEvents<D> = {
error: [Error & Record<string, unknown>, Omit<Context<D>, "next">];
};
export interface ApplicationOptions<D> {
/**
* [Optional] Arbitrary data to put into the context for each request
* [`default=undefined`]
*/
data?: D;
/**
* [Optional] Custom logger or flag if you want to use a default logger
* [`default=new BaseLogger()`]
*/
log?: Logger | boolean;
/**
* [Optional] Flag to run application in development mode
* [`default=false`]
*/
dev?: boolean;
}
/**
* Sync or async middleware.
*/
export type Middleware<D> =
| ((params: Context<D>) => void | unknown)
| ((params: Context<D>) => Promise<void | unknown>);
export interface Context<D> {
/** Request that triggered the handling */
readonly req: IRequest;
/** Response for the request */
readonly res: IResponse;
/** Trigger dispatching to the next middleware. */
readonly next: () => Promise<void>;
/** Context-specific logger for the middleware */
readonly log: Logger;
/** Arbitrary data storage */
readonly data: D & Record<string, unknown>;
}
/**
* Dispatch function provided by ChatAlly application.
*/
export type Dispatch =
| ((req: IRequest, res: IResponse) => Promise<void>)
| ((req: IRequest, res: IResponse) => void);
/**
* Chat server
*
* A chat server receives incoming chat messages and dispatches them to the
* application.
*/
export interface Server {
/** The server's name */
name: string;
/** Registers the application as dispatcher */
set dispatch(d: Dispatch);
/**
* The logger to use during runtime. Set this explicitly to false or NoLogger,
* if the registered server shall not log, otherwise the application will
* register a child logger.
*/
log: Logger | boolean | undefined;
/** Starts the server */
listen: () => void;
}
/**
* Chat request with incoming message
*/
export declare class Request implements IRequest {
/**
* Create a chat request for an incoming message.
*
* @param message Fully typed message or a string that can optionally contain
* a "sender:" before a colon
*/
constructor(message: string | IncomingMessage);
get message(): IncomingMessage;
get text(): string;
}
/**
* Chat request with incoming message.
*/
export interface IRequest {
/** Incoming message */
readonly message: IncomingMessage;
/** Textual content of incoming message */
readonly text: string;
}
/**
* Incoming message.
*/
export type IncomingMessage = Message & {
/** Arrival time of message */
timestamp: number;
/** Id of message */
id: string;
/** Id of sender */
from: string;
/** [Optional] id of message that this message is a reply to */
replyTo?: string;
};
/**
* Chat response.
*/
export declare class Response
extends EventEmitter<ResponseEvents>
implements IResponse
{
/**
* Create a new chat response.
*
* @param onFinished
* [Optional] Handler to be called, when response `end()` is called.
*/
constructor(onFinished?: (r: Response) => void);
messages: OutgoingMessage[];
isWritable: Readonly<boolean>;
text: readonly string[];
write: (msg: string | OutgoingMessage) => void;
end: (msg?: string | OutgoingMessage | undefined) => void;
}
type ResponseEvents = {
finished: [Response];
write: [OutgoingMessage];
};
/**
* Chat response.
*/
export interface IResponse {
/** Messages to send as response. */
messages: OutgoingMessage[];
/** True if no middleware called end. */
isWritable: Readonly<boolean>;
/** Textual representation of all messages. */
text: Readonly<string[]>;
/** Write a message. */
write: (msg: string | OutgoingMessage) => void;
/** End the response, optionally with a message. */
end: (msg?: string | OutgoingMessage) => void;
}
/**
* Incoming message
*/
export type OutgoingMessage = Message & {
/** [Optional] Id of message that this message is a reply to. */
replyTo?: string;
};
/**
* @param {any} object
* @returns {object is import("./index.d.ts").Server}
*/
export function isServer(object) {
if (!object) return false;
if (typeof object.listen !== "function") return false;
const dispatch =
Object.getOwnPropertyDescriptor(object, "dispatch") ||
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(object), "dispatch");
if (!dispatch) return false;
if (!dispatch.set && !dispatch.writable) return false;
return true;
}
+8
-2
> @chatally/core@0.0.6 lint
> @chatally/core@0.0.7 lint
> eslint .

@@ -9,6 +9,12 @@

/home/runner/work/chatally/chatally/packages/core/lib/index.d.ts
10:44 warning Don't use `Object` as a type. The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.
- If you want a type meaning "any object", you probably want `object` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead @typescript-eslint/ban-types
/home/runner/work/chatally/chatally/packages/core/lib/messages.d.ts
46:20 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
✖ 1 problem (0 errors, 1 warning)
✖ 2 problems (0 errors, 2 warnings)
+4
-4
> @chatally/core@0.0.6 test
> @chatally/core@0.0.7 test
> vitest run

@@ -8,8 +8,8 @@

✓ lib/application.test.js  (7 tests) 11ms
✓ lib/application.test.js  (7 tests) 24ms
 Test Files  1 passed (1)
 Tests  7 passed (7)
 Start at  14:32:46
 Duration  971ms (transform 218ms, setup 0ms, collect 221ms, tests 11ms, environment 0ms, prepare 214ms)
 Start at  12:30:08
 Duration  871ms (transform 166ms, setup 1ms, collect 139ms, tests 24ms, environment 0ms, prepare 199ms)
# @chatally/core
## 0.0.7
### Patch Changes
- 795d1ac: Improved types for all packages
- Updated dependencies [795d1ac]
- @chatally/logger@0.0.5
## 0.0.6

@@ -4,0 +12,0 @@

import { BaseLogger, NoLogger } from "@chatally/logger";
import { EventEmitter } from "node:events";
import { isServer } from "./server.js";
import { isServer } from "./is-server.js";

@@ -9,4 +9,4 @@ /**

*
* @template {Object} D
* @extends {EventEmitter<{error: [Error & Record<string, unknown>, Omit<import("./middleware.d.ts").Context<D>, "next">]}>}
* @template {object} D
* @type {import("./index.d.ts").Application<D>}
*/

@@ -21,3 +21,3 @@ export class Application extends EventEmitter {

* Middlewares in order of registration
* @type {import("./middleware.d.ts").Middleware<D>[]}
* @type {import("./index.d.ts").Middleware<D>[]}
*/

@@ -28,3 +28,3 @@ #middlewares = [];

* Servers
* @type {import("./server.js").Server[]}
* @type {import("./index.d.ts").Server[]}
*/

@@ -46,15 +46,6 @@ #servers = [];

/**
* Create an application that dispatches incoming chat requests from all
* registered servers to all registered middleware.
*
* @param {Object} [options={}]
* @param {D} [options.data]
* [Optional] Arbitrary data to put into the context for each request
* [`default=undefined`]
* @param {import("@chatally/logger").Logger | boolean} [options.log]
* [Optional] Custom logger or flag if you want to use a default logger
* [`default=new BaseLogger()`]
* @param {boolean} [options.dev]
* [Optional] Flag to run application in development mode
* [`default=false`]
*/

@@ -77,12 +68,3 @@ constructor(options = {}) {

/**
* Register a middleware function or a server
*
* Middlewares are executed in order of registration, but can `await next()`
* to wait for the following middlewares to finish.
*
* It is preferrable to use a named function over an arrow function, because
* the name is used to identify child loggers. Optionally, you can provide a
* name for the middleware.
*
* @param {import("./middleware.d.ts").Middleware<D> | import("./server.js").Server} m
* @param {import("./index.d.ts").Middleware<D> | import("./index.d.ts").Server} m
* @param {String} [name]

@@ -131,3 +113,3 @@ */

*
* @type {import("./server.js").Dispatch}
* @type {import("./index.d.ts").Dispatch}
*/

@@ -152,4 +134,4 @@ get dispatch() {

*
* @param {import("./request.js").IRequest} req
* @param {import("./response.js").IResponse} res
* @param {import("./index.d.ts").IRequest} req
* @param {import("./index.d.ts").IResponse} res
* @param {D & Record<string, unknown>} data

@@ -184,3 +166,3 @@ * @param {import("@chatally/logger").Logger} log

* @param {unknown} err
* @param {Omit<import("./middleware.d.ts").Context<D>, "next">} context
* @param {Omit<import("./index.d.ts").Context<D>, "next">} context
*/

@@ -190,3 +172,2 @@ #handleError(err, context) {

if (err instanceof Error) {
// @ts-expect-error For better DX, we pass down an error that behaves like "any"
if (!this.emit("error", err, context)) {

@@ -229,6 +210,6 @@ context.log.error(err);

dev || process.env.NODE_ENV === "development" ? "debug" : "info";
return BaseLogger.create({ level, name: "@chatally/core" });
return new BaseLogger({ level, name: "@chatally/core" });
} else {
return log || NoLogger.create();
return log || new NoLogger();
}
}
import { BaseLogger } from "@chatally/logger";
import { StringWritable, XError } from "@internal/utils";
import { StringWritable, TestError } from "@internal/test-utils";
import { Application } from "./application.js";

@@ -8,3 +8,3 @@ import { Request } from "./request.js";

/**
* @type {import("./middleware.js").Middleware<{}>}
* @type {import("./index.d.ts").Middleware<{}>}
*/

@@ -33,3 +33,3 @@ const echo = ({ req, res }) => {

function getLogger(options) {
return BaseLogger.create(options);
return new BaseLogger(options);
}

@@ -120,3 +120,3 @@

.use(function throws() {
throw new XError("Boom", { expose: true });
throw new TestError("Boom", { expose: true });
})

@@ -138,3 +138,3 @@ .on("error", (err, { res }) => {

log.out = out;
log.timestamps = false;
log.timestamp = false;

@@ -151,3 +151,3 @@ new Application({ log })

log.out = out;
log.timestamps = false;
log.timestamp = false;

@@ -154,0 +154,0 @@ const app = new Application({ log }) //

@@ -14,3 +14,3 @@ export type Message =

export type Action = {
type Action = {
id: string;

@@ -17,0 +17,0 @@ title: string;

@@ -5,37 +5,9 @@ import { nanoid } from "nanoid";

/**
* Chat request with incoming message
*
* @typedef IRequest
* @property {Readonly<IncomingMessage>} message Incoming message
* @property {Readonly<string>} text Textual content of incoming message
* @type {import("./index.d.ts").Request}
*/
/**
* Incoming message
*
* @typedef {(Incoming & import("./messages.d.ts").Message)} IncomingMessage
*
* @typedef {object} Incoming
* @property {number} IncomingMessage.timestamp Arrival time of message
* @property {string} IncomingMessage.id Id of message
* @property {string} IncomingMessage.from Id of sender
* @property {string} [IncomingMessage.replyTo] Id of message that this message
* is a reply to
*/
/**
* Chat request with incoming message
*
* @class
* @implements {IRequest}
*/
export class Request {
/** @type {IncomingMessage} */
/** @type {import("./index.d.ts").IncomingMessage} */
#message;
/**
*
* @param {IncomingMessage | string} message Fully typed message or a string
* that can optionally contain a "sender:" before a colon
*/
/** @param {import("./index.d.ts").IncomingMessage | string} message */
constructor(message) {

@@ -48,3 +20,3 @@ if (typeof message === "string") {

}
message = {
this.#message = {
type: "text",

@@ -56,4 +28,5 @@ text,

};
} else {
this.#message = message;
}
this.#message = message;
}

@@ -60,0 +33,0 @@

import { EventEmitter } from "node:events";
import { text } from "./text.js";
/**
* Chat response
* @typedef IResponse
* @property {OutgoingMessage[]} messages Messages to send as response
* @property {Readonly<boolean>} isWritable True if no middleware called end
* @property {Readonly<string[]>} text Textual representation of all messages
* @property {(msg: string | OutgoingMessage) => void} write Write a message
* @property {(msg?: string | OutgoingMessage) => void} end
* End the response, optionally with a message
* @template {keyof Events} E
* @property {(event: E, listener: Events[E]) => IResponse} on
*
* @typedef {object} Events
* @property {[Response]} finished
* @property {[OutgoingMessage]} write
*/
/**
* Outgoing message
* @typedef {(Outgoing & import("./messages.d.ts").Message)} OutgoingMessage
*
* @typedef {object} Outgoing
* @property {string} [OutgoingMessage.replyTo]
* id of message that this message is a reply to
*/
/**
* Chat response
*
* @class
* @extends {EventEmitter<Events>}
* @implements {IResponse}
*/
/** @type {import("./index.d.ts").Response} */
export class Response extends EventEmitter {
/** @type {OutgoingMessage[]} */
/** @type {import("./index.d.ts").OutgoingMessage[]} */
#messages = [];
#finished = false;
/**
* Create a new response
*
* @param {(() => void)} [onFinished]
* optional handler to be called, when response `end()` is called
*/
/** @param {((r: Response) => void)} [onFinished] */
constructor(onFinished) {

@@ -67,3 +30,3 @@ super();

/** @param {string | OutgoingMessage} [msg] */
/** @param {string | import("./index.d.ts").OutgoingMessage} [msg] */
end(msg) {

@@ -75,3 +38,3 @@ this.write(msg);

/** @param {string | OutgoingMessage} [msg] */
/** @param {string | import("./index.d.ts").OutgoingMessage} [msg] */
write(msg) {

@@ -78,0 +41,0 @@ if (!msg) return;

{
"name": "@chatally/core",
"version": "0.0.6",
"version": "0.0.7",
"description": "ChatAlly Core Modules",

@@ -5,0 +5,0 @@ "license": "MIT",

import type { Logger } from "@chatally/logger";
import type { IRequest } from "./request.js";
import type { IResponse } from "./response.js";
/**
* Sync or async middleware.
*/
export type Middleware<D> =
| ((params: Context<D>) => void | unknown)
| ((params: Context<D>) => Promise<void | unknown>);
export interface Context<D> {
/** Request that triggered the handling */
readonly req: IRequest;
/** Response for the request */
readonly res: IResponse;
/** Trigger dispatching to the next middleware. */
readonly next: () => Promise<void>;
/** Context-specific logger for the middleware */
readonly log: Logger;
/** Arbitrary data storage */
readonly data: D & Record<string, unknown>;
}
/**
* Dispatch function provided by ChatAlly application.
* @typedef {((req: import("./request.js").IRequest, res: import("./response.js").IResponse) => Promise<void>) | ((req: import("./request.js").IRequest, res: import("./response.js").IResponse) => void)} Dispatch
*/
/**
* Chat server
*
* A chat server receives incoming chat messages and dispatches them to the
* application.
*
* @typedef {object} Server
* @property {string} name The server's name
* @property {Dispatch} dispatch Registers the application as dispatcher
* @property {import("@chatally/logger").Logger | boolean | undefined} log
* The logger to use during runtime. Set this explicitly to false or
* NoLogger, if the registered server shall not log, otherwise the
* application will register a child logger
* @property {() => void} listen Starts the server
*/
/**
* @param {any} object
* @returns {object is Server}
*/
export function isServer(object) {
if (!object) return false;
if (typeof object.listen !== "function") return false;
const prop =
Object.getOwnPropertyDescriptor(object, "dispatch") ||
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(object), "dispatch");
if (!prop) return false;
if (!prop.set && !prop.writable) return false;
return true;
}
export * from "./index.js";
export type * from "./messages.d.ts";
export type { Context, Middleware } from "./middleware.js";
export type { IncomingMessage } from "./request.js";
export type { OutgoingMessage } from "./response.js";
export type { Dispatch, Server } from "./server.js";