diff --git a/packages/mono-dev b/packages/mono-dev index a2b269b..96307f3 160000 --- a/packages/mono-dev +++ b/packages/mono-dev @@ -1 +1 @@ -Subproject commit a2b269ba8b8e188a2e334a51e7af83c75ae375a4 +Subproject commit 96307f3f4f13a53281b4bac27601f04301b9182e diff --git a/packages/pure-i18next/package.json b/packages/pure-i18next/package.json index 2a42243..d348945 100644 --- a/packages/pure-i18next/package.json +++ b/packages/pure-i18next/package.json @@ -1,6 +1,6 @@ { "name": "@pistonite/pure-i18next", - "version": "0.4.5", + "version": "0.4.6", "type": "module", "description": "I18next binding for pure library", "homepage": "https://github.com/Pistonite/pure", diff --git a/packages/pure-i18next/src/backend.ts b/packages/pure-i18next/src/backend.ts index 101a8b2..ce87dbb 100644 --- a/packages/pure-i18next/src/backend.ts +++ b/packages/pure-i18next/src/backend.ts @@ -2,6 +2,7 @@ import type { BackendModule } from "i18next"; import { convertToSupportedLocale } from "@pistonite/pure/pref"; import type { LoadLanguageFn } from "./types.ts"; +import { log } from "./util.ts"; /** Create an i18next backend module given the loader functions */ export const createBackend = ( @@ -27,9 +28,7 @@ export const createBackend = ( if (namespace !== "translation" || !hasNonDefaultNamespace) { // only log an error if the namespace is not the default // if there are non-default namespaces - console.error( - `[pure-i18next] no loader found for namespace ${namespace}`, - ); + log.error(`no loader found for namespace ${namespace}`); } return undefined; } @@ -39,16 +38,14 @@ export const createBackend = ( return strings; } } catch (e) { - console.error(e); + log.error(e); } if (locale === fallbackLocale) { - console.warn( - `[pure-i18next] failed to load ${namespace} for ${locale}`, - ); + log.warn(`failed to load ${namespace} for ${locale}`); return undefined; } - console.warn( - `[pure-i18next] failed to load ${namespace} for ${locale}, falling back to ${fallbackLocale}`, + log.warn( + `failed to load ${namespace} for ${locale}, falling back to ${fallbackLocale}`, ); try { const strings = await loader(fallbackLocale); @@ -56,10 +53,10 @@ export const createBackend = ( return strings; } } catch (e) { - console.error(e); + log.error(e); } - console.warn( - `[pure-i18next] failed to load ${namespace} for fallback locale ${fallbackLocale}`, + log.warn( + `failed to load ${namespace} for fallback locale ${fallbackLocale}`, ); return undefined; }, diff --git a/packages/pure-i18next/src/util.ts b/packages/pure-i18next/src/util.ts new file mode 100644 index 0000000..e579410 --- /dev/null +++ b/packages/pure-i18next/src/util.ts @@ -0,0 +1,3 @@ +import { logger } from "@pistonite/pure/log"; + +export const log = logger("pure-i18next", "gray").default(); diff --git a/packages/pure-react/package.json b/packages/pure-react/package.json index ef90779..04c0a30 100644 --- a/packages/pure-react/package.json +++ b/packages/pure-react/package.json @@ -1,6 +1,6 @@ { "name": "@pistonite/pure-react", - "version": "0.7.10", + "version": "0.7.11", "type": "module", "description": "React binding for pure library", "homepage": "https://github.com/Pistonite/pure", diff --git a/packages/pure/package.json b/packages/pure/package.json index c1de40c..fcf638f 100644 --- a/packages/pure/package.json +++ b/packages/pure/package.json @@ -1,6 +1,6 @@ { "name": "@pistonite/pure", - "version": "0.26.5", + "version": "0.26.6", "type": "module", "description": "Pure TypeScript libraries for my projects", "homepage": "https://github.com/Pistonite/pure", diff --git a/packages/pure/src/fs/FsFileStandaloneImplFileAPI.ts b/packages/pure/src/fs/FsFileStandaloneImplFileAPI.ts index 52ff0e0..4fa4dee 100644 --- a/packages/pure/src/fs/FsFileStandaloneImplFileAPI.ts +++ b/packages/pure/src/fs/FsFileStandaloneImplFileAPI.ts @@ -1,3 +1,4 @@ +import { ilog } from "../log/internal.ts"; import { errstr } from "../result"; import { fsErr, FsErr, fsFail, type FsVoid, type FsResult } from "./FsError.ts"; @@ -29,7 +30,7 @@ export class FsFileStandaloneImplFileAPI implements FsFileStandalone { const data = await this.file.arrayBuffer(); return { val: new Uint8Array(data) }; } catch (e) { - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } @@ -41,7 +42,7 @@ export class FsFileStandaloneImplFileAPI implements FsFileStandalone { const data = await this.file.text(); return { val: data }; } catch (e) { - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } diff --git a/packages/pure/src/fs/FsFileStandaloneImplHandleAPI.ts b/packages/pure/src/fs/FsFileStandaloneImplHandleAPI.ts index 2fefce3..15f8347 100644 --- a/packages/pure/src/fs/FsFileStandaloneImplHandleAPI.ts +++ b/packages/pure/src/fs/FsFileStandaloneImplHandleAPI.ts @@ -1,3 +1,4 @@ +import { ilog } from "../log/internal.ts"; import { errstr } from "../result"; import { fsErr, FsErr, fsFail, type FsVoid, type FsResult } from "./FsError.ts"; @@ -39,7 +40,7 @@ export class FsFileStandaloneImplHandleAPI implements FsFileStandalone { }); return requestedPermission === "granted"; } catch (e) { - console.error(e); + ilog.error(e); return false; } } @@ -58,7 +59,7 @@ export class FsFileStandaloneImplHandleAPI implements FsFileStandalone { return { err: fsErr(FsErr.NotFound, "File not found") }; } } - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } @@ -79,7 +80,7 @@ export class FsFileStandaloneImplHandleAPI implements FsFileStandalone { const data = await file.val.arrayBuffer(); return { val: new Uint8Array(data) }; } catch (e) { - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } @@ -99,7 +100,7 @@ export class FsFileStandaloneImplHandleAPI implements FsFileStandalone { const data = await file.val.text(); return { val: data }; } catch (e) { - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } @@ -145,7 +146,7 @@ export class FsFileStandaloneImplHandleAPI implements FsFileStandalone { }; } } - console.error(e); + ilog.error(e); return { err: fsFail(errstr(e)) }; } } diff --git a/packages/pure/src/fs/FsImplEntryAPI.ts b/packages/pure/src/fs/FsImplEntryAPI.ts index c9549b7..38e5297 100644 --- a/packages/pure/src/fs/FsImplEntryAPI.ts +++ b/packages/pure/src/fs/FsImplEntryAPI.ts @@ -25,10 +25,7 @@ export class FsImplEntryAPI constructor(root: string, rootEntry: FileSystemDirectoryEntry) { this.root = root; this.rootEntry = rootEntry; - this.capabilities = { - write: false, - live: true, - }; + this.capabilities = { write: false, live: true }; this.mgr = new FsFileMgr(); } diff --git a/packages/pure/src/fs/FsImplFileAPI.ts b/packages/pure/src/fs/FsImplFileAPI.ts index e277e09..fbcad11 100644 --- a/packages/pure/src/fs/FsImplFileAPI.ts +++ b/packages/pure/src/fs/FsImplFileAPI.ts @@ -1,3 +1,5 @@ +import { ilog } from "../log/internal.ts"; + import type { FsFile } from "./FsFile.ts"; import type { FsFileSystem, @@ -28,10 +30,7 @@ export class FsImplFileAPI constructor(files: FileList) { // this seems to also work for windows this.root = files[0].webkitRelativePath.split("/", 1)[0]; - this.capabilities = { - write: false, - live: false, - }; + this.capabilities = { write: false, live: false }; this.files = {}; this.directories = {}; this.mgr = new FsFileMgr(); @@ -43,7 +42,7 @@ export class FsImplFileAPI const normalized = fsNormalize(path); if (normalized.err) { // shouldn't happen since the path is from the File API - console.error("Invalid path: " + path); + ilog.error("invalid path: " + path); continue; } this.files[normalized.val] = file; diff --git a/packages/pure/src/fs/FsImplHandleAPI.ts b/packages/pure/src/fs/FsImplHandleAPI.ts index 6a274dc..d6486f7 100644 --- a/packages/pure/src/fs/FsImplHandleAPI.ts +++ b/packages/pure/src/fs/FsImplHandleAPI.ts @@ -49,10 +49,7 @@ export class FsImplHandleAPI this.rootHandle = rootHandle; this.writeMode = write; this.permissionStatus = "prompt"; - this.capabilities = { - write, - live: true, - }; + this.capabilities = { write, live: true }; this.mgr = new FsFileMgr(); } diff --git a/packages/pure/src/fs/FsOpenFile.ts b/packages/pure/src/fs/FsOpenFile.ts index 948ed36..804f9d4 100644 --- a/packages/pure/src/fs/FsOpenFile.ts +++ b/packages/pure/src/fs/FsOpenFile.ts @@ -160,10 +160,7 @@ const fsOpenFileWithFileSystemAccessAPI = async ( if (anyMimeType.length) { convertedAccept["*/*"] = anyMimeType; } - return { - description, - accept: convertedAccept, - }; + return { description, accept: convertedAccept }; }); try { // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/pure/src/fs/FsSave.ts b/packages/pure/src/fs/FsSave.ts index 8e77891..d2fa75e 100644 --- a/packages/pure/src/fs/FsSave.ts +++ b/packages/pure/src/fs/FsSave.ts @@ -1,3 +1,5 @@ +import { ilog } from "../log/internal.ts"; + import { fsFail, type FsVoid } from "./FsError.ts"; /** Save (download) a file using Blob */ @@ -11,7 +13,7 @@ export function fsSave(content: string | Uint8Array, filename: string): FsVoid { saveAs(blob, filename); return {}; } catch (e) { - console.error(e); + ilog.error(e); return { err: fsFail("save failed") }; } } @@ -35,9 +37,7 @@ type SaveAsFn = ( filename?: string, options?: SaveAsFnOptions, ) => void; -type SaveAsFnOptions = { - autoBom: boolean; -}; +type SaveAsFnOptions = { autoBom: boolean }; /* eslint-disable @typescript-eslint/no-explicit-any */ diff --git a/packages/pure/src/log/index.ts b/packages/pure/src/log/index.ts index 407870d..2bba94f 100644 --- a/packages/pure/src/log/index.ts +++ b/packages/pure/src/log/index.ts @@ -1,154 +1,13 @@ -/** - * Client side log util - * - * This is rather simple logging stuff with the primary focus - * being easy to debug. - * - * Use {@link logger} to create a logger with a name and a color, - * then use one of the {@link LoggerFactory} methods to setup the logging level. - * - * There are 3 levels of logging: - * 1. (Default) Warnings and Errors only - * 2. Also log info messages - * 3. Also log debug messages. - * - * Each logger can turn on info and debug logging separately, or it can - * be turned on at the global level for debugging. - * - * You can also turn off each logger individually or at global level for debugging. - * - * Due to the nature of JS, all logging calls, even when turned off, will incur - * some small runtime overhead. While we could remove debug calls - * for release build, that's currently not done (and it would require - * bundler to inline the call to remove the call completely, which might - * not be the case) - * - * @module - */ - -import { errstr } from "../result/index.ts"; - -export const LogLevel = { - Off: 0, - High: 1, - Info: 2, - Debug: 3, -} as const; -export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel]; - -let globalLevel: LogLevel = LogLevel.High; -/** - * Suppress ALL logging. - * - * This overrides logger-level settings - */ -export const globalLogOff = () => (globalLevel = 0); -/** - * Enable +info logging for ALL loggers - * - * This overrides logger-level settings - */ -export const globalLogInfo = () => (globalLevel = 2); -/** - * Enable +debug logging for ALL loggers - * - * This overrides logger-level settings - */ -export const globalLogDebug = () => (globalLevel = 3); - -/** Create a logger creator. Use the factory methods to finish making the logger */ -export const logger = (name: string, color?: string): LoggerFactory => { - return { - default: () => new LoggerImpl(name, color, LogLevel.High), - debug: () => new LoggerImpl(name, color, LogLevel.Debug), - info: () => new LoggerImpl(name, color, LogLevel.Info), - off: () => new LoggerImpl(name, color, LogLevel.Off), - }; -}; - -export type LoggerFactory = { - /** Standard important logger (warning and errors) */ - default(): Logger; - /** Enable +info +debug logging for this logger */ - debug(): Logger; - /** Enable +info logging for this logger */ - info(): Logger; - /** Stop all logging, including warn and error */ - off(): Logger; -}; - -export type Logger = { - /** Log a debug message */ - debug(obj: unknown): void; - /** Log an info message */ - info(obj: unknown): void; - /** Log a warning message */ - warn(obj: unknown): void; - /** Log an error message */ - error(obj: unknown): void; -}; - -class LoggerImpl implements Logger { - name: string; - color: string | undefined; - level: LogLevel; - - constructor(name: string, color: string | undefined, level: LogLevel) { - this.name = name; - this.color = - "padding:0 3x;color:white" + (color ? `;background:${color}` : ""); - this.level = level; - } - - debug(obj: unknown) { - if (globalLevel !== LogLevel.Debug && this.level !== LogLevel.Debug) { - return; - } - console.log( - `%cDEBUG%c${this.name}%c ${obj}`, - "background:gray;color:white;padding:0 3px", - this.color, - "color:inherit;background:inherit", - ); - } - - info(obj: unknown) { - if (globalLevel < LogLevel.Info && this.level < LogLevel.Info) { - return; - } - console.log( - `%cINFO%c${this.name}%c ${obj}`, - "background:green;color:white;padding:0 3px", - this.color, - "color:inherit;background:inherit", - ); - } - - warn(obj: unknown) { - if (globalLevel < LogLevel.High || this.level < LogLevel.High) { - return; - } - console.warn( - `%cWARN%c${this.name}%c ${obj}`, - "background:orange;color:white;padding:0 3px", - this.color, - "color:inherit;background:inherit", - ); - } - - error(obj: unknown) { - if (globalLevel < LogLevel.High || this.level < LogLevel.High) { - return; - } - const msg = errstr(obj); - console.error( - `%cERROR%c${this.name}%c ${msg}`, - "background:orange;color:white;padding:0 3px", - this.color, - "color:inherit;background:inherit", - ); - if (msg !== obj) { - console.error(obj); - } - } -} +export { + globalLogOff, + globalLogInfo, + globalLogDebug, + logger, + type LoggerFactory, + type Logger, +} from "./logger.ts"; +export { + internalLogOff, + internalLogDebug, + internalLogInfo, +} from "./internal.ts"; diff --git a/packages/pure/src/log/internal.ts b/packages/pure/src/log/internal.ts new file mode 100644 index 0000000..b9f7f4f --- /dev/null +++ b/packages/pure/src/log/internal.ts @@ -0,0 +1,18 @@ +import { LoggerImpl, LogLevel } from "./logger.ts"; + +export const ilog: LoggerImpl = new LoggerImpl("pure", "gray", LogLevel.High); + +/** Set the internal log level of calls in this library to off */ +export const internalLogOff = () => { + ilog.level = LogLevel.Off; +}; + +/** Set the internal log level of calls in this library to debug */ +export const internalLogDebug = () => { + ilog.level = LogLevel.Debug; +}; + +/** Set the internal log level of calls in this library to info */ +export const internalLogInfo = () => { + ilog.level = LogLevel.Info; +}; diff --git a/packages/pure/src/log/logger.ts b/packages/pure/src/log/logger.ts new file mode 100644 index 0000000..258c369 --- /dev/null +++ b/packages/pure/src/log/logger.ts @@ -0,0 +1,149 @@ +/** + * Client side log util + * + * This is rather simple logging stuff with the primary focus + * being easy to debug. + * + * Use {@link logger} to create a logger with a name and a color, + * then use one of the {@link LoggerFactory} methods to setup the logging level. + * + * There are 3 levels of logging: + * 1. (Default) Warnings and Errors only + * 2. Also log info messages + * 3. Also log debug messages. + * + * Each logger can turn on info and debug logging separately, or it can + * be turned on at the global level for debugging. + * + * You can also turn off each logger individually or at global level for debugging. + * + * Due to the nature of JS, all logging calls, even when turned off, will incur + * some small runtime overhead. While we could remove debug calls + * for release build, that's currently not done (and it would require + * bundler to inline the call to remove the call completely, which might + * not be the case) + * + * @module + */ + +import { errstr } from "../result/index.ts"; + +export const LogLevel = { Off: 0, High: 1, Info: 2, Debug: 3 } as const; +export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel]; + +let globalLevel: LogLevel = LogLevel.High; +/** + * Suppress ALL logging. + * + * This overrides logger-level settings + */ +export const globalLogOff = () => (globalLevel = 0); +/** + * Enable +info logging for ALL loggers + * + * This overrides logger-level settings + */ +export const globalLogInfo = () => (globalLevel = 2); +/** + * Enable +debug logging for ALL loggers + * + * This overrides logger-level settings + */ +export const globalLogDebug = () => (globalLevel = 3); + +/** Create a logger creator. Use the factory methods to finish making the logger */ +export const logger = (name: string, color?: string): LoggerFactory => { + return { + default: () => new LoggerImpl(name, color, LogLevel.High), + debug: () => new LoggerImpl(name, color, LogLevel.Debug), + info: () => new LoggerImpl(name, color, LogLevel.Info), + off: () => new LoggerImpl(name, color, LogLevel.Off), + }; +}; + +export type LoggerFactory = { + /** Standard important logger (warning and errors) */ + default(): Logger; + /** Enable +info +debug logging for this logger */ + debug(): Logger; + /** Enable +info logging for this logger */ + info(): Logger; + /** Stop all logging, including warn and error */ + off(): Logger; +}; + +export type Logger = { + /** Log a debug message */ + debug(obj: unknown): void; + /** Log an info message */ + info(obj: unknown): void; + /** Log a warning message */ + warn(obj: unknown): void; + /** Log an error message */ + error(obj: unknown): void; +}; + +export class LoggerImpl implements Logger { + name: string; + color: string | undefined; + level: LogLevel; + + constructor(name: string, color: string | undefined, level: LogLevel) { + this.name = name; + this.color = + "padding:0 3x;color:white" + (color ? `;background:${color}` : ""); + this.level = level; + } + + debug(obj: unknown) { + if (globalLevel !== LogLevel.Debug && this.level !== LogLevel.Debug) { + return; + } + console.debug( + `%cDEBUG%c${this.name}%c ${obj}`, + "background:gray;color:white;padding:0 3px", + this.color, + "color:inherit;background:inherit", + ); + } + + info(obj: unknown) { + if (globalLevel < LogLevel.Info && this.level < LogLevel.Info) { + return; + } + console.info( + `%cINFO%c${this.name}%c ${obj}`, + "background:green;color:white;padding:0 3px", + this.color, + "color:inherit;background:inherit", + ); + } + + warn(obj: unknown) { + if (globalLevel < LogLevel.High || this.level < LogLevel.High) { + return; + } + console.warn( + `%cWARN%c${this.name}%c ${obj}`, + "background:orange;color:white;padding:0 3px", + this.color, + "color:inherit;background:inherit", + ); + } + + error(obj: unknown) { + if (globalLevel < LogLevel.High || this.level < LogLevel.High) { + return; + } + const msg = errstr(obj); + console.error( + `%cERROR%c${this.name}%c ${msg}`, + "background:darkred;color:white;padding:0 3px", + this.color, + "color:inherit;background:inherit", + ); + if (msg !== obj) { + console.error(obj); + } + } +} diff --git a/packages/pure/src/memory/erc.test.ts b/packages/pure/src/memory/erc.test.ts index ff83ffa..4aa0e31 100644 --- a/packages/pure/src/memory/erc.test.ts +++ b/packages/pure/src/memory/erc.test.ts @@ -2,10 +2,7 @@ import { describe, afterEach, expect, it } from "vitest"; import { type Erc, makeErcType } from "./erc.ts"; -type Rc = { - value: string; - refCount: number; -}; +type Rc = { value: string; refCount: number }; const Marker = Symbol("test"); type Marker = typeof Marker; class Allocator { @@ -74,10 +71,7 @@ class Allocator { } allocValue(value: string): number { - const rc: Rc = { - value, - refCount: 1, - }; + const rc: Rc = { value, refCount: 1 }; for (let i = 0; i < this.mockMemory.length; i++) { if (this.mockMemory[i] === undefined) { this.mockMemory[i] = rc; diff --git a/packages/pure/src/memory/idgen.ts b/packages/pure/src/memory/idgen.ts index 4080158..dacb38f 100644 --- a/packages/pure/src/memory/idgen.ts +++ b/packages/pure/src/memory/idgen.ts @@ -6,7 +6,7 @@ export const safeidgen = (n: number): (() => number) => { let x = 1; return () => { x += 1; - if (x === n) { + if (x >= n) { x = 1; } return x; diff --git a/packages/pure/src/sync/batch.ts b/packages/pure/src/sync/batch.ts index 41e41a0..9cff805 100644 --- a/packages/pure/src/sync/batch.ts +++ b/packages/pure/src/sync/batch.ts @@ -166,12 +166,7 @@ class BatchImpl { return this.execute(...args); } const { promise, resolve, reject } = makePromise>(); - this.scheduled.push({ - input: args, - promise, - resolve, - reject, - }); + this.scheduled.push({ input: args, promise, resolve, reject }); return promise; } diff --git a/packages/pure/src/sync/debounce.ts b/packages/pure/src/sync/debounce.ts index 9f05dd0..39bc470 100644 --- a/packages/pure/src/sync/debounce.ts +++ b/packages/pure/src/sync/debounce.ts @@ -120,9 +120,7 @@ export type DebounceConstructor = { class DebounceImpl { private idle: boolean; - private next?: PromiseHandle> & { - args: Parameters; - }; + private next?: PromiseHandle> & { args: Parameters }; constructor( private fn: TFn, private interval: number, diff --git a/packages/pure/src/sync/serial.test.ts b/packages/pure/src/sync/serial.test.ts index d398a4d..83d4cec 100644 --- a/packages/pure/src/sync/serial.test.ts +++ b/packages/pure/src/sync/serial.test.ts @@ -47,9 +47,7 @@ test("passing in arguments", async () => { }); test("current serial number", async () => { - const execute = serial({ - fn: (_, serial) => () => serial, - }); + const execute = serial({ fn: (_, serial) => () => serial }); const one = await execute(); expect(one).toStrictEqual({ val: 1n }); diff --git a/packages/pure/src/sync/util.ts b/packages/pure/src/sync/util.ts index afb4bf1..dede0e9 100644 --- a/packages/pure/src/sync/util.ts +++ b/packages/pure/src/sync/util.ts @@ -14,11 +14,7 @@ export const makePromise = (): { "Promise callbacks not set. This is a bug in the JS engine!", ); } - return { - promise, - resolve, - reject, - }; + return { promise, resolve, reject }; }; export type PromiseHandle = ReturnType>;