@poppinss/utils
Advanced tools
Comparing version 6.5.0-3 to 6.5.0-4
@@ -1,19 +0,284 @@ | ||
/// <reference types="@types/node" resolution-mode="require"/> | ||
export { base64 } from './src/base64.js'; | ||
export { compose } from './src/compose.js'; | ||
export { importDefault } from './src/import_default.js'; | ||
export { defineStaticProperty } from './src/define_static_property.js'; | ||
export { Exception, createError } from './src/exception.js'; | ||
export { flatten } from './src/flatten.js'; | ||
export { fsImportAll } from './src/fs_import_all.js'; | ||
export { fsReadAll } from './src/fs_read_all.js'; | ||
export { isScriptFile } from './src/is_script_file.js'; | ||
export { MessageBuilder } from './src/message_builder.js'; | ||
export { naturalSort } from './src/natural_sort.js'; | ||
export { ObjectBuilder } from './src/object_builder.js'; | ||
export { safeEqual } from './src/safe_equal.js'; | ||
export { slash } from './src/slash.js'; | ||
export { RuntimeException } from './src/exceptions/runtime_exception.js'; | ||
export { InvalidArgumentsException } from './src/exceptions/invalid_arguments_exception.js'; | ||
export declare function getDirname(url: string | URL): string; | ||
export declare function getFilename(url: string | URL): string; | ||
import { Constructor as Constructor$1, ImportAllFilesOptions, ReadAllFilesOptions, OmitProperties } from './src/types.js'; | ||
export { default as slash } from 'slash'; | ||
/** | ||
* Helper class to base64 encode/decode values with option | ||
* for url encoding and decoding | ||
*/ | ||
declare class Base64 { | ||
/** | ||
* Base64 encode Buffer or string | ||
*/ | ||
encode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string; | ||
encode(data: string, encoding?: BufferEncoding): string; | ||
/** | ||
* Base64 decode a previously encoded string or Buffer. | ||
*/ | ||
decode(encode: string, encoding: BufferEncoding, strict: true): string; | ||
decode(encode: string, encoding: undefined, strict: true): string; | ||
decode(encode: string, encoding?: BufferEncoding, strict?: false): string | null; | ||
decode(encode: Buffer, encoding?: BufferEncoding): string; | ||
/** | ||
* Base64 encode Buffer or string to be URL safe. (RFC 4648) | ||
*/ | ||
urlEncode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string; | ||
urlEncode(data: string, encoding?: BufferEncoding): string; | ||
/** | ||
* Base64 URL decode a previously encoded string or Buffer. (RFC 4648) | ||
*/ | ||
urlDecode(encode: string, encoding: BufferEncoding, strict: true): string; | ||
urlDecode(encode: string, encoding: undefined, strict: true): string; | ||
urlDecode(encode: string, encoding?: BufferEncoding, strict?: false): string | null; | ||
urlDecode(encode: Buffer, encoding?: BufferEncoding): string; | ||
} | ||
declare const base64: Base64; | ||
interface UnaryFunction<T, R> { | ||
(source: T): R; | ||
} | ||
/** | ||
* Compose a class by applying mixins to it. | ||
* The code is inspired by https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/, its | ||
* just that I have added the support for static types too. | ||
*/ | ||
declare function compose<T extends Constructor$1, A>(superclass: T, mixin: UnaryFunction<T, A>): A; | ||
declare function compose<T extends Constructor$1, A, B>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>): B; | ||
declare function compose<T extends Constructor$1, A, B, C>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>): C; | ||
declare function compose<T extends Constructor$1, A, B, C, D>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>): D; | ||
declare function compose<T extends Constructor$1, A, B, C, D, E>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>, mixinE: UnaryFunction<D, E>): E; | ||
declare function compose<T extends Constructor$1, A, B, C, D, E, F>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>, mixinF: UnaryFunction<E, F>): F; | ||
declare function compose<T extends Constructor$1, A, B, C, D, E, F, G>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>, mixinF: UnaryFunction<E, F>, mixinG: UnaryFunction<F, G>): G; | ||
declare function compose<T extends Constructor$1, A, B, C, D, E, F, G, H>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>, mixinF: UnaryFunction<E, F>, mixinG: UnaryFunction<F, G>, mixinH: UnaryFunction<G, H>): H; | ||
declare function compose<T extends Constructor$1, A, B, C, D, E, F, G, H, I>(superclass: T, mixin: UnaryFunction<T, A>, mixinB: UnaryFunction<A, B>, mixinC: UnaryFunction<B, C>, mixinD: UnaryFunction<C, D>, mixinF: UnaryFunction<E, F>, mixinG: UnaryFunction<F, G>, mixinH: UnaryFunction<G, H>, mixinI: UnaryFunction<H, I>): I; | ||
/** | ||
* Dynamically import a module and ensure it has a default export | ||
*/ | ||
declare function importDefault<T extends object>(importFn: () => Promise<T>, filePath?: string): Promise<T extends { | ||
default: infer A; | ||
} ? A : never>; | ||
type Constructor = new (...args: any[]) => any; | ||
type AbstractConstructor = abstract new (...args: any[]) => any; | ||
/** | ||
* Define static properties on a class with inheritance in play. | ||
*/ | ||
declare function defineStaticProperty<T extends Constructor | AbstractConstructor, Prop extends keyof T>(self: T, propertyName: Prop, { initialValue, strategy, }: { | ||
initialValue: T[Prop]; | ||
strategy: 'inherit' | 'define' | ((value: T[Prop]) => T[Prop]); | ||
}): void; | ||
/** | ||
* Extended Error object with the option to set error `status` and `code`. | ||
* At AdonisJs, we prefer exceptions with proper error codes to handle | ||
* them without relying on message pattern matching. | ||
* | ||
* ```js | ||
* new Exception('message', 500, 'E_RUNTIME_EXCEPTION') | ||
* ``` | ||
*/ | ||
declare class Exception extends Error { | ||
/** | ||
* Static properties to defined on the exception once | ||
* and then re-use them | ||
*/ | ||
static help?: string; | ||
static code?: string; | ||
static status?: number; | ||
static message?: string; | ||
/** | ||
* Name of the class that raised the exception. | ||
*/ | ||
name: string; | ||
/** | ||
* Optional help description for the error. You can use it to define additional | ||
* human readable information for the error. | ||
*/ | ||
help?: string; | ||
/** | ||
* A machine readable error code. This will allow the error handling logic | ||
* to narrow down exceptions based upon the error code. | ||
*/ | ||
code?: string; | ||
/** | ||
* A status code for the error. Usually helpful when converting errors | ||
* to HTTP responses. | ||
*/ | ||
status: number; | ||
constructor(message?: string, options?: ErrorOptions & { | ||
code?: string; | ||
status?: number; | ||
}); | ||
get [Symbol.toStringTag](): string; | ||
toString(): string; | ||
} | ||
/** | ||
* Helper to create anonymous error classes | ||
*/ | ||
declare function createError<T extends any[] = never>(message: string, code: string, status?: number): typeof Exception & T extends never ? { | ||
new (args?: any, options?: ErrorOptions): Exception; | ||
} : { | ||
new (args: T, options?: ErrorOptions): Exception; | ||
}; | ||
/** | ||
* Recursively flatten an object/array. | ||
*/ | ||
declare function flatten<X = Record<string, any>, Y = unknown>(input: Y, glue?: string, keepNullish?: boolean): X; | ||
/** | ||
* Returns an array of file paths from the given location. You can | ||
* optionally filter and sort files by passing relevant options | ||
* | ||
* ```ts | ||
* await fsReadAll(new URL('./', import.meta.url)) | ||
* | ||
* await fsReadAll(new URL('./', import.meta.url), { | ||
* filter: (filePath) => filePath.endsWith('.js') | ||
* }) | ||
* await fsReadAll(new URL('./', import.meta.url), { | ||
* absolute: true, | ||
* unixPaths: true | ||
* }) | ||
* ``` | ||
*/ | ||
declare function fsImportAll(location: string | URL, options?: ImportAllFilesOptions): Promise<any>; | ||
/** | ||
* Returns an array of file paths from the given location. You can | ||
* optionally filter and sort files by passing relevant options | ||
* | ||
* ```ts | ||
* await fsReadAll(new URL('./', import.meta.url)) | ||
* | ||
* await fsReadAll(new URL('./', import.meta.url), { | ||
* filter: (filePath) => filePath.endsWith('.js') | ||
* }) | ||
* await fsReadAll(new URL('./', import.meta.url), { | ||
* absolute: true, | ||
* unixPaths: true | ||
* }) | ||
* ``` | ||
*/ | ||
declare function fsReadAll(location: string | URL, options?: ReadAllFilesOptions): Promise<string[]>; | ||
/** | ||
* Returns `true` when file ends with `.js`, `.json` or | ||
* `.ts` but not `.d.ts`. | ||
*/ | ||
declare function isScriptFile(filePath: string): boolean; | ||
/** | ||
* Message builder exposes an API to "JSON.stringify" values by | ||
* encoding purpose and expiry date inside them. | ||
* | ||
* The return value must be further encrypted to prevent tempering. | ||
*/ | ||
declare class MessageBuilder { | ||
#private; | ||
/** | ||
* Builds a message by encoding expiry date and purpose inside it. | ||
*/ | ||
build(message: any, expiresIn?: string | number, purpose?: string): string; | ||
/** | ||
* Verifies the message for expiry and purpose. | ||
*/ | ||
verify<T extends any>(message: any, purpose?: string): null | T; | ||
} | ||
/** | ||
* Perform natural sorting with "Array.sort()" method | ||
*/ | ||
declare function naturalSort(current: string, next: string): number; | ||
/** | ||
* A simple class to build an object incrementally. It is helpful when you | ||
* want to add properties to the object conditionally. | ||
* | ||
* Instead of writing | ||
* ``` | ||
* const obj = { | ||
* ...(user.id ? { id: user.id } : {}), | ||
* ...(user.firstName && user.lastName ? { name: `${user.firstName} ${user.lastName}` } : {}), | ||
* } | ||
* ``` | ||
* | ||
* You can write | ||
* | ||
* const obj = new ObjectBuilder() | ||
* .add('id', user.id) | ||
* .add( | ||
* 'fullName', | ||
* user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : undefined | ||
* ) | ||
* .toObject() | ||
*/ | ||
declare class ObjectBuilder<ReturnType extends Record<string, any>, IgnoreNull extends boolean = false> { | ||
#private; | ||
values: ReturnType; | ||
constructor(initialValue: ReturnType, ignoreNull?: IgnoreNull); | ||
/** | ||
* Add a key-value pair to the object | ||
* | ||
* - Undefined values are ignored | ||
* - Null values are ignored, when `ignoreNull` is set to true | ||
*/ | ||
add<Prop extends string>(key: Prop, value: undefined): this; | ||
add<Prop extends string, Value>(key: Prop, value: Value): ObjectBuilder<ReturnType & { | ||
[P in Prop]: Value; | ||
}, IgnoreNull>; | ||
/** | ||
* Remove key from the object | ||
*/ | ||
remove<K extends keyof ReturnType>(key: K): this; | ||
/** | ||
* Find if a value exists | ||
*/ | ||
has<K extends keyof ReturnType>(key: K): boolean; | ||
/** | ||
* Get the existing value for a given key | ||
*/ | ||
get<K extends keyof ReturnType>(key: K): ReturnType[K]; | ||
/** | ||
* Get the underlying constructed object | ||
*/ | ||
toObject(): IgnoreNull extends true ? { | ||
[K in keyof OmitProperties<ReturnType, null>]: ReturnType[K]; | ||
} : { | ||
[K in keyof ReturnType]: ReturnType[K]; | ||
}; | ||
} | ||
type BufferSafeValue = ArrayBuffer | SharedArrayBuffer | number[] | string | { | ||
valueOf(): string | object; | ||
} | { | ||
[Symbol.toPrimitive](hint: 'string'): string; | ||
}; | ||
/** | ||
* Compare two values to see if they are equal. The comparison is done in | ||
* a way to avoid timing-attacks. | ||
*/ | ||
declare function safeEqual<T extends BufferSafeValue, U extends BufferSafeValue>(trustedValue: T, userInput: U): boolean; | ||
declare class RuntimeException extends Exception { | ||
static code: string; | ||
static status: number; | ||
} | ||
declare class InvalidArgumentsException extends Exception { | ||
static code: string; | ||
static status: number; | ||
} | ||
/** | ||
* Get dirname for a given file path URL | ||
*/ | ||
declare function getDirname(url: string | URL): string; | ||
/** | ||
* Get filename for a given file path URL | ||
*/ | ||
declare function getFilename(url: string | URL): string; | ||
export { Exception, InvalidArgumentsException, MessageBuilder, ObjectBuilder, RuntimeException, base64, compose, createError, defineStaticProperty, flatten, fsImportAll, fsReadAll, getDirname, getFilename, importDefault, isScriptFile, naturalSort, safeEqual }; |
@@ -1,24 +0,373 @@ | ||
import { fileURLToPath } from 'node:url'; | ||
import { dirname as pathDirname } from 'node:path'; | ||
export { base64 } from './src/base64.js'; | ||
export { compose } from './src/compose.js'; | ||
export { importDefault } from './src/import_default.js'; | ||
export { defineStaticProperty } from './src/define_static_property.js'; | ||
export { Exception, createError } from './src/exception.js'; | ||
export { flatten } from './src/flatten.js'; | ||
export { fsImportAll } from './src/fs_import_all.js'; | ||
export { fsReadAll } from './src/fs_read_all.js'; | ||
export { isScriptFile } from './src/is_script_file.js'; | ||
export { MessageBuilder } from './src/message_builder.js'; | ||
export { naturalSort } from './src/natural_sort.js'; | ||
export { ObjectBuilder } from './src/object_builder.js'; | ||
export { safeEqual } from './src/safe_equal.js'; | ||
export { slash } from './src/slash.js'; | ||
export { RuntimeException } from './src/exceptions/runtime_exception.js'; | ||
export { InvalidArgumentsException } from './src/exceptions/invalid_arguments_exception.js'; | ||
export function getDirname(url) { | ||
return pathDirname(getFilename(url)); | ||
import { | ||
base64, | ||
milliseconds_default | ||
} from "./chunk-PWRXO3NF.js"; | ||
import { | ||
main_default | ||
} from "./chunk-XHQBV7AF.js"; | ||
// index.ts | ||
import { fileURLToPath as fileURLToPath3 } from "node:url"; | ||
import { dirname as pathDirname } from "node:path"; | ||
// src/compose.ts | ||
function compose(superclass, ...mixins) { | ||
return mixins.reduce((c, mixin) => mixin(c), superclass); | ||
} | ||
export function getFilename(url) { | ||
return fileURLToPath(url); | ||
// src/exception.ts | ||
import { format } from "node:util"; | ||
var Exception = class extends Error { | ||
/** | ||
* Name of the class that raised the exception. | ||
*/ | ||
name; | ||
/** | ||
* A status code for the error. Usually helpful when converting errors | ||
* to HTTP responses. | ||
*/ | ||
status; | ||
constructor(message, options) { | ||
super(message, options); | ||
const ErrorConstructor = this.constructor; | ||
this.name = ErrorConstructor.name; | ||
this.message = message || ErrorConstructor.message || ""; | ||
this.status = options?.status || ErrorConstructor.status || 500; | ||
const code = options?.code || ErrorConstructor.code; | ||
if (code !== void 0) { | ||
this.code = code; | ||
} | ||
const help = ErrorConstructor.help; | ||
if (help !== void 0) { | ||
this.help = help; | ||
} | ||
Error.captureStackTrace(this, ErrorConstructor); | ||
} | ||
get [Symbol.toStringTag]() { | ||
return this.constructor.name; | ||
} | ||
toString() { | ||
if (this.code) { | ||
return `${this.name} [${this.code}]: ${this.message}`; | ||
} | ||
return `${this.name}: ${this.message}`; | ||
} | ||
}; | ||
function createError(message, code, status) { | ||
return class extends Exception { | ||
static message = message; | ||
static code = code; | ||
static status = status; | ||
constructor(args, options) { | ||
super(format(message, ...args || []), options); | ||
} | ||
}; | ||
} | ||
// src/exceptions/runtime_exception.ts | ||
var RuntimeException = class extends Exception { | ||
static code = "E_RUNTIME_EXCEPTION"; | ||
static status = 500; | ||
}; | ||
// src/import_default.ts | ||
async function importDefault(importFn, filePath) { | ||
const moduleExports = await importFn(); | ||
if (!("default" in moduleExports)) { | ||
const errorMessage = filePath ? `Missing "export default" in module "${filePath}"` : `Missing "export default" from lazy import "${importFn}"`; | ||
throw new RuntimeException(errorMessage, { | ||
cause: { | ||
source: importFn | ||
} | ||
}); | ||
} | ||
return moduleExports.default; | ||
} | ||
// src/define_static_property.ts | ||
import lodash from "@poppinss/utils/lodash"; | ||
function defineStaticProperty(self, propertyName, { | ||
initialValue, | ||
strategy | ||
}) { | ||
if (!self.hasOwnProperty(propertyName)) { | ||
const value = self[propertyName]; | ||
if (strategy === "define" || value === void 0) { | ||
Object.defineProperty(self, propertyName, { | ||
value: initialValue, | ||
configurable: true, | ||
enumerable: true, | ||
writable: true | ||
}); | ||
return; | ||
} | ||
Object.defineProperty(self, propertyName, { | ||
value: typeof strategy === "function" ? strategy(value) : lodash.cloneDeep(value), | ||
configurable: true, | ||
enumerable: true, | ||
writable: true | ||
}); | ||
} | ||
} | ||
// src/flatten.ts | ||
import { flattie } from "flattie"; | ||
function flatten(input, glue, keepNullish) { | ||
return flattie(input, glue, keepNullish); | ||
} | ||
// src/fs_import_all.ts | ||
import { fileURLToPath as fileURLToPath2 } from "node:url"; | ||
import lodash2 from "@poppinss/utils/lodash"; | ||
import { extname as extname2, relative, sep } from "node:path"; | ||
// src/fs_read_all.ts | ||
import { join } from "node:path"; | ||
import { readdir, stat } from "node:fs/promises"; | ||
import { fileURLToPath, pathToFileURL } from "node:url"; | ||
// src/slash.ts | ||
import { default as default2 } from "slash"; | ||
// src/natural_sort.ts | ||
function naturalSort(current, next) { | ||
return current.localeCompare(next, void 0, { numeric: true, sensitivity: "base" }); | ||
} | ||
// src/fs_read_all.ts | ||
function filterDotFiles(fileName) { | ||
return fileName[0] !== "."; | ||
} | ||
async function readFiles(root, files, options, relativePath) { | ||
const location = join(root, relativePath); | ||
const stats = await stat(location); | ||
if (stats.isDirectory()) { | ||
let locationFiles = await readdir(location); | ||
await Promise.all( | ||
locationFiles.filter(filterDotFiles).map((file) => { | ||
return readFiles(root, files, options, join(relativePath, file)); | ||
}) | ||
); | ||
return; | ||
} | ||
const pathType = options.pathType || "relative"; | ||
switch (pathType) { | ||
case "relative": | ||
files.push(relativePath); | ||
break; | ||
case "absolute": | ||
files.push(location); | ||
break; | ||
case "unixRelative": | ||
files.push(default2(relativePath)); | ||
break; | ||
case "unixAbsolute": | ||
files.push(default2(location)); | ||
break; | ||
case "url": | ||
files.push(pathToFileURL(location).href); | ||
} | ||
} | ||
async function fsReadAll(location, options) { | ||
const normalizedLocation = typeof location === "string" ? location : fileURLToPath(location); | ||
const normalizedOptions = Object.assign({ absolute: false, sort: naturalSort }, options); | ||
const files = []; | ||
try { | ||
await stat(normalizedLocation); | ||
} catch (error) { | ||
if (normalizedOptions.ignoreMissingRoot) { | ||
return []; | ||
} | ||
throw error; | ||
} | ||
await readFiles(normalizedLocation, files, normalizedOptions, ""); | ||
if (normalizedOptions.filter) { | ||
return files.filter(normalizedOptions.filter).sort(normalizedOptions.sort); | ||
} | ||
return files.sort(normalizedOptions.sort); | ||
} | ||
// src/is_script_file.ts | ||
import { extname } from "node:path"; | ||
var JS_MODULES = [".js", ".json", ".cjs", ".mjs"]; | ||
function isScriptFile(filePath) { | ||
const ext = extname(filePath); | ||
if (JS_MODULES.includes(ext)) { | ||
return true; | ||
} | ||
if (ext === ".ts" && !filePath.endsWith(".d.ts")) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
// src/fs_import_all.ts | ||
async function importFile(basePath, fileURL, values, options) { | ||
const filePath = fileURLToPath2(fileURL); | ||
const fileExtension = extname2(filePath); | ||
const collectionKey = relative(basePath, filePath).replace(new RegExp(`${fileExtension}$`), "").split(sep); | ||
const exportedValue = fileExtension === ".json" ? await import(fileURL, { assert: { type: "json" } }) : await import(fileURL); | ||
lodash2.set( | ||
values, | ||
options.transformKeys ? options.transformKeys(collectionKey) : collectionKey, | ||
exportedValue.default ? exportedValue.default : { ...exportedValue } | ||
); | ||
} | ||
async function fsImportAll(location, options) { | ||
options = options || {}; | ||
const collection = {}; | ||
const normalizedLocation = typeof location === "string" ? location : fileURLToPath2(location); | ||
const files = await fsReadAll(normalizedLocation, { | ||
filter: isScriptFile, | ||
...options, | ||
pathType: "url" | ||
}); | ||
await Promise.all(files.map((file) => importFile(normalizedLocation, file, collection, options))); | ||
return collection; | ||
} | ||
// src/message_builder.ts | ||
var MessageBuilder = class { | ||
#getExpiryDate(expiresIn) { | ||
if (!expiresIn) { | ||
return void 0; | ||
} | ||
const expiryMs = milliseconds_default.parse(expiresIn); | ||
return new Date(Date.now() + expiryMs); | ||
} | ||
/** | ||
* Returns a boolean telling, if message has been expired or not | ||
*/ | ||
#isExpired(message) { | ||
if (!message.expiryDate) { | ||
return false; | ||
} | ||
const expiryDate = new Date(message.expiryDate); | ||
return Number.isNaN(expiryDate.getTime()) || expiryDate < /* @__PURE__ */ new Date(); | ||
} | ||
/** | ||
* Builds a message by encoding expiry date and purpose inside it. | ||
*/ | ||
build(message, expiresIn, purpose) { | ||
const expiryDate = this.#getExpiryDate(expiresIn); | ||
return main_default.safeStringify({ message, purpose, expiryDate }); | ||
} | ||
/** | ||
* Verifies the message for expiry and purpose. | ||
*/ | ||
verify(message, purpose) { | ||
const parsed = main_default.safeParse(message); | ||
if (typeof parsed !== "object" || !parsed) { | ||
return null; | ||
} | ||
if (!parsed.message) { | ||
return null; | ||
} | ||
if (parsed.purpose !== purpose) { | ||
return null; | ||
} | ||
if (this.#isExpired(parsed)) { | ||
return null; | ||
} | ||
return parsed.message; | ||
} | ||
}; | ||
// src/object_builder.ts | ||
var ObjectBuilder = class { | ||
#ignoreNull; | ||
values; | ||
constructor(initialValue, ignoreNull) { | ||
this.values = initialValue; | ||
this.#ignoreNull = ignoreNull === true ? true : false; | ||
} | ||
add(key, value) { | ||
if (value === void 0) { | ||
return this; | ||
} | ||
if (this.#ignoreNull === true && value === null) { | ||
return this; | ||
} | ||
; | ||
this.values[key] = value; | ||
return this; | ||
} | ||
/** | ||
* Remove key from the object | ||
*/ | ||
remove(key) { | ||
delete this.values[key]; | ||
return this; | ||
} | ||
/** | ||
* Find if a value exists | ||
*/ | ||
has(key) { | ||
return this.get(key) !== void 0; | ||
} | ||
/** | ||
* Get the existing value for a given key | ||
*/ | ||
get(key) { | ||
return this.values[key]; | ||
} | ||
/** | ||
* Get the underlying constructed object | ||
*/ | ||
toObject() { | ||
return this.values; | ||
} | ||
}; | ||
// src/safe_equal.ts | ||
import { Buffer } from "node:buffer"; | ||
import { timingSafeEqual } from "node:crypto"; | ||
function safeEqual(trustedValue, userInput) { | ||
if (typeof trustedValue === "string" && typeof userInput === "string") { | ||
const trustedLength = Buffer.byteLength(trustedValue); | ||
const trustedValueBuffer = Buffer.alloc(trustedLength, 0, "utf-8"); | ||
trustedValueBuffer.write(trustedValue); | ||
const userValueBuffer = Buffer.alloc(trustedLength, 0, "utf-8"); | ||
userValueBuffer.write(userInput); | ||
return timingSafeEqual(trustedValueBuffer, userValueBuffer) && trustedLength === Buffer.byteLength(userInput); | ||
} | ||
return timingSafeEqual( | ||
Buffer.from(trustedValue), | ||
Buffer.from(userInput) | ||
); | ||
} | ||
// src/exceptions/invalid_arguments_exception.ts | ||
var InvalidArgumentsException = class extends Exception { | ||
static code = "E_INVALID_ARGUMENTS_EXCEPTION"; | ||
static status = 500; | ||
}; | ||
// index.ts | ||
function getDirname(url) { | ||
return pathDirname(getFilename(url)); | ||
} | ||
function getFilename(url) { | ||
return fileURLToPath3(url); | ||
} | ||
export { | ||
Exception, | ||
InvalidArgumentsException, | ||
MessageBuilder, | ||
ObjectBuilder, | ||
RuntimeException, | ||
base64, | ||
compose, | ||
createError, | ||
defineStaticProperty, | ||
flatten, | ||
fsImportAll, | ||
fsReadAll, | ||
getDirname, | ||
getFilename, | ||
importDefault, | ||
isScriptFile, | ||
naturalSort, | ||
safeEqual, | ||
default2 as slash | ||
}; |
@@ -1,3 +0,14 @@ | ||
import { safeParse } from './safe_parse.js'; | ||
import { safeStringify } from './safe_stringify.js'; | ||
import { JSONReviver, JSONReplacer } from '../types.js'; | ||
/** | ||
* A drop-in replacement for JSON.parse with prototype poisoning protection. | ||
*/ | ||
declare function safeParse(jsonString: string, reviver?: JSONReviver): any; | ||
/** | ||
* String Javascript values to a JSON string. Handles circular | ||
* references and bigints | ||
*/ | ||
declare function safeStringify(value: any, replacer?: JSONReplacer, space?: string | number): string | undefined; | ||
declare const json: { | ||
@@ -7,2 +18,3 @@ safeParse: typeof safeParse; | ||
}; | ||
export default json; | ||
export { json as default }; |
@@ -1,7 +0,6 @@ | ||
import { safeParse } from './safe_parse.js'; | ||
import { safeStringify } from './safe_stringify.js'; | ||
const json = { | ||
safeParse, | ||
safeStringify, | ||
import { | ||
main_default | ||
} from "../../chunk-XHQBV7AF.js"; | ||
export { | ||
main_default as default | ||
}; | ||
export default json; |
@@ -1,23 +0,82 @@ | ||
export default class StringBuilder { | ||
/** | ||
* String builder to transform the string using the fluent API | ||
*/ | ||
declare class StringBuilder { | ||
#private; | ||
constructor(value: string | StringBuilder); | ||
/** | ||
* Applies dash case transformation | ||
*/ | ||
dashCase(): this; | ||
/** | ||
* Applies dot case transformation | ||
*/ | ||
dotCase(): this; | ||
/** | ||
* Applies snake case transformation | ||
*/ | ||
snakeCase(): this; | ||
/** | ||
* Applies pascal case transformation | ||
*/ | ||
pascalCase(): this; | ||
/** | ||
* Applies camelcase case transformation | ||
*/ | ||
camelCase(): this; | ||
/** | ||
* Applies capital case transformation | ||
*/ | ||
capitalCase(): this; | ||
/** | ||
* Applies title case transformation | ||
*/ | ||
titleCase(): this; | ||
/** | ||
* Applies sentence case transformation | ||
*/ | ||
sentenceCase(): this; | ||
/** | ||
* Removes all sorts of casing from the string | ||
*/ | ||
noCase(): this; | ||
/** | ||
* Converts value to its plural form | ||
*/ | ||
plural(): this; | ||
/** | ||
* Converts value to its singular form | ||
*/ | ||
singular(): this; | ||
/** | ||
* Converts value to a URL friendly slug | ||
*/ | ||
slugify(): this; | ||
/** | ||
* Removes a given suffix from the string | ||
*/ | ||
removeSuffix(suffix: string): this; | ||
/** | ||
* Adds suffix to the string | ||
*/ | ||
suffix(suffix: string): this; | ||
/** | ||
* Removes a given prefix from the string | ||
*/ | ||
removePrefix(prefix: string): this; | ||
/** | ||
* Adds prefix to the string | ||
*/ | ||
prefix(prefix: string): this; | ||
/** | ||
* Removes extension from the value | ||
*/ | ||
removeExtension(): this; | ||
/** | ||
* Adds extension to the value | ||
*/ | ||
ext(extension: string): this; | ||
toString(): string; | ||
} | ||
export { StringBuilder as default }; |
@@ -1,86 +0,148 @@ | ||
import { extname } from 'node:path'; | ||
import string from './string/main.js'; | ||
export default class StringBuilder { | ||
#value; | ||
constructor(value) { | ||
this.#value = typeof value === 'string' ? value : value.toString(); | ||
} | ||
dashCase() { | ||
this.#value = string.dashCase(this.#value); | ||
return this; | ||
} | ||
dotCase() { | ||
this.#value = string.dotCase(this.#value); | ||
return this; | ||
} | ||
snakeCase() { | ||
this.#value = string.snakeCase(this.#value); | ||
return this; | ||
} | ||
pascalCase() { | ||
this.#value = string.pascalCase(this.#value); | ||
return this; | ||
} | ||
camelCase() { | ||
this.#value = string.camelCase(this.#value); | ||
return this; | ||
} | ||
capitalCase() { | ||
this.#value = string.capitalCase(this.#value); | ||
return this; | ||
} | ||
titleCase() { | ||
this.#value = string.titleCase(this.#value); | ||
return this; | ||
} | ||
sentenceCase() { | ||
this.#value = string.sentenceCase(this.#value); | ||
return this; | ||
} | ||
noCase() { | ||
this.#value = string.noCase(this.#value); | ||
return this; | ||
} | ||
plural() { | ||
this.#value = string.pluralize(this.#value); | ||
return this; | ||
} | ||
singular() { | ||
this.#value = string.singular(this.#value); | ||
return this; | ||
} | ||
slugify() { | ||
this.#value = string.slug(this.#value); | ||
return this; | ||
} | ||
removeSuffix(suffix) { | ||
this.#value = this.#value.replace(new RegExp(`[-_]?${suffix}$`, 'i'), ''); | ||
return this; | ||
} | ||
suffix(suffix) { | ||
this.removeSuffix(suffix); | ||
this.#value = `${this.#value}${suffix}`; | ||
return this; | ||
} | ||
removePrefix(prefix) { | ||
this.#value = this.#value.replace(new RegExp(`^${prefix}[-_]?`, 'i'), ''); | ||
return this; | ||
} | ||
prefix(prefix) { | ||
this.removePrefix(prefix); | ||
this.#value = `${prefix}${this.#value}`; | ||
return this; | ||
} | ||
removeExtension() { | ||
this.#value = this.#value.replace(new RegExp(`${extname(this.#value)}$`), ''); | ||
return this; | ||
} | ||
ext(extension) { | ||
this.removeExtension(); | ||
this.#value = `${this.#value}.${extension.replace(/^\./, '')}`; | ||
return this; | ||
} | ||
toString() { | ||
return this.#value; | ||
} | ||
} | ||
import { | ||
main_default | ||
} from "../chunk-OKRMWJO4.js"; | ||
import "../chunk-PWRXO3NF.js"; | ||
// src/string_builder.ts | ||
import { extname } from "node:path"; | ||
var StringBuilder = class { | ||
#value; | ||
constructor(value) { | ||
this.#value = typeof value === "string" ? value : value.toString(); | ||
} | ||
/** | ||
* Applies dash case transformation | ||
*/ | ||
dashCase() { | ||
this.#value = main_default.dashCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies dot case transformation | ||
*/ | ||
dotCase() { | ||
this.#value = main_default.dotCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies snake case transformation | ||
*/ | ||
snakeCase() { | ||
this.#value = main_default.snakeCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies pascal case transformation | ||
*/ | ||
pascalCase() { | ||
this.#value = main_default.pascalCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies camelcase case transformation | ||
*/ | ||
camelCase() { | ||
this.#value = main_default.camelCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies capital case transformation | ||
*/ | ||
capitalCase() { | ||
this.#value = main_default.capitalCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies title case transformation | ||
*/ | ||
titleCase() { | ||
this.#value = main_default.titleCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Applies sentence case transformation | ||
*/ | ||
sentenceCase() { | ||
this.#value = main_default.sentenceCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Removes all sorts of casing from the string | ||
*/ | ||
noCase() { | ||
this.#value = main_default.noCase(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Converts value to its plural form | ||
*/ | ||
plural() { | ||
this.#value = main_default.pluralize(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Converts value to its singular form | ||
*/ | ||
singular() { | ||
this.#value = main_default.singular(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Converts value to a URL friendly slug | ||
*/ | ||
slugify() { | ||
this.#value = main_default.slug(this.#value); | ||
return this; | ||
} | ||
/** | ||
* Removes a given suffix from the string | ||
*/ | ||
removeSuffix(suffix) { | ||
this.#value = this.#value.replace(new RegExp(`[-_]?${suffix}$`, "i"), ""); | ||
return this; | ||
} | ||
/** | ||
* Adds suffix to the string | ||
*/ | ||
suffix(suffix) { | ||
this.removeSuffix(suffix); | ||
this.#value = `${this.#value}${suffix}`; | ||
return this; | ||
} | ||
/** | ||
* Removes a given prefix from the string | ||
*/ | ||
removePrefix(prefix) { | ||
this.#value = this.#value.replace(new RegExp(`^${prefix}[-_]?`, "i"), ""); | ||
return this; | ||
} | ||
/** | ||
* Adds prefix to the string | ||
*/ | ||
prefix(prefix) { | ||
this.removePrefix(prefix); | ||
this.#value = `${prefix}${this.#value}`; | ||
return this; | ||
} | ||
/** | ||
* Removes extension from the value | ||
*/ | ||
removeExtension() { | ||
this.#value = this.#value.replace(new RegExp(`${extname(this.#value)}$`), ""); | ||
return this; | ||
} | ||
/** | ||
* Adds extension to the value | ||
*/ | ||
ext(extension) { | ||
this.removeExtension(); | ||
this.#value = `${this.#value}.${extension.replace(/^\./, "")}`; | ||
return this; | ||
} | ||
toString() { | ||
return this.#value; | ||
} | ||
}; | ||
export { | ||
StringBuilder as default | ||
}; |
@@ -1,9 +0,114 @@ | ||
import { random } from './random.js'; | ||
import { excerpt } from './excerpt.js'; | ||
import { ordinal } from './ordinal.js'; | ||
import { truncate } from './truncate.js'; | ||
import { sentence } from './sentence.js'; | ||
import { interpolate } from './interpolate.js'; | ||
import { pluralize } from './pluralize.js'; | ||
import { noCase, dotCase, dashCase, camelCase, snakeCase, titleCase, pascalCase, capitalCase, sentenceCase } from './change_case.js'; | ||
import * as bytes from 'bytes'; | ||
import * as slugify from 'slugify'; | ||
import pluralizePkg from 'pluralize'; | ||
/** | ||
* Generates a random string of a given size | ||
*/ | ||
declare function random(size: number): string; | ||
/** | ||
* Truncate a sentence to be under a certain characters limit and strip | ||
* out HTML tags from it. | ||
* | ||
* Optionally, you can force the truncate logic to complete words, which | ||
* may exceed the defined characters limit. | ||
*/ | ||
declare function excerpt(sentence: string, charactersLimit: number, options?: { | ||
completeWords?: boolean; | ||
suffix?: string; | ||
}): string; | ||
/** | ||
* Ordinalize a give number or string | ||
*/ | ||
declare function ordinal(value: string | number): string; | ||
/** | ||
* Truncate a sentence to be under a certain characters limit. | ||
* | ||
* Optionally, you can force the truncate logic to complete words, which | ||
* may exceed the defined characters limit. | ||
*/ | ||
declare function truncate(sentence: string, charactersLimit: number, options?: { | ||
completeWords?: boolean; | ||
suffix?: string; | ||
}): string; | ||
/** | ||
* Convert an array of values to a sentence. | ||
*/ | ||
declare function sentence(values: any[], options?: { | ||
separator?: string; | ||
pairSeparator?: string; | ||
lastSeparator?: string; | ||
}): string; | ||
/** | ||
* A simple function interpolate values inside curly braces. | ||
* | ||
* ``` | ||
* interpolate('hello {{ username }}', { username: 'virk' }) | ||
* ``` | ||
*/ | ||
declare function interpolate(input: string, data: any): string; | ||
/** | ||
* Pluralize a word based upon the count. The method returns the | ||
* singular form when count is 1. | ||
*/ | ||
declare function pluralize(word: string, count?: number, inclusive?: boolean): string; | ||
declare namespace pluralize { | ||
var addPluralRule: typeof pluralizePkg.addPluralRule; | ||
var addSingularRule: typeof pluralizePkg.addSingularRule; | ||
var addIrregularRule: typeof pluralizePkg.addIrregularRule; | ||
var addUncountableRule: typeof pluralizePkg.addUncountableRule; | ||
} | ||
/** | ||
* The method is a copy/paste from the "title-case" package. They have | ||
* a dependency on "tslib", which I don't want. | ||
*/ | ||
declare function titleCase(input: string): string; | ||
/** | ||
* Convert string to camelcase | ||
*/ | ||
declare function camelCase(value: string): string; | ||
/** | ||
* Convert string to snakecase | ||
*/ | ||
declare function snakeCase(value: string): string; | ||
/** | ||
* Convert string to dashcase | ||
*/ | ||
declare function dashCase(value: string, options?: { | ||
capitalize?: boolean; | ||
}): string; | ||
/** | ||
* Convert string to pascal case | ||
*/ | ||
declare function pascalCase(value: string): string; | ||
/** | ||
* Convert string to capital case | ||
*/ | ||
declare function capitalCase(value: string): string; | ||
/** | ||
* Convert string to sentence case | ||
*/ | ||
declare function sentenceCase(value: string): string; | ||
/** | ||
* Convert string to dot case | ||
*/ | ||
declare function dotCase(value: string, options?: { | ||
lowerCase?: boolean; | ||
}): string; | ||
/** | ||
* Remove all sort of casing from the string. Copy-pasted from | ||
* "no-case" package with slight modifications. | ||
*/ | ||
declare function noCase(value: string, transform?: (part: string, index: number, parts: string[]) => string): string; | ||
/** | ||
* Condense multiple whitespaces from a string | ||
*/ | ||
declare function condenseWhitespace(value: string): string; | ||
@@ -13,9 +118,9 @@ declare const string: { | ||
truncate: typeof truncate; | ||
slug: typeof import("slugify").default; | ||
slug: typeof slugify.default; | ||
interpolate: typeof interpolate; | ||
plural: typeof import("pluralize").plural; | ||
plural: typeof pluralize.plural; | ||
pluralize: typeof pluralize; | ||
singular: typeof import("pluralize").singular; | ||
isPlural: typeof import("pluralize").isPlural; | ||
isSingular: typeof import("pluralize").isSingular; | ||
singular: typeof pluralize.singular; | ||
isPlural: typeof pluralize.isPlural; | ||
isSingular: typeof pluralize.isSingular; | ||
camelCase: typeof camelCase; | ||
@@ -42,3 +147,3 @@ capitalCase: typeof capitalCase; | ||
bytes: { | ||
format(valueInBytes: number, options?: import("bytes").BytesOptions | undefined): string; | ||
format(valueInBytes: number, options?: bytes.BytesOptions | undefined): string; | ||
parse(unit: string | number): number; | ||
@@ -48,2 +153,3 @@ }; | ||
}; | ||
export default string; | ||
export { string as default }; |
@@ -1,43 +0,7 @@ | ||
import bytes from './bytes.js'; | ||
import seconds from './seconds.js'; | ||
import { slug } from './slugify.js'; | ||
import { random } from './random.js'; | ||
import { excerpt } from './excerpt.js'; | ||
import { ordinal } from './ordinal.js'; | ||
import { truncate } from './truncate.js'; | ||
import milliseconds from './milliseconds.js'; | ||
import { sentence } from './sentence.js'; | ||
import { interpolate } from './interpolate.js'; | ||
import { plural, pluralize, singular, isPlural, isSingular } from './pluralize.js'; | ||
import { noCase, dotCase, dashCase, camelCase, snakeCase, titleCase, pascalCase, capitalCase, sentenceCase, } from './change_case.js'; | ||
function condenseWhitespace(value) { | ||
return value.trim().replace(/\s{2,}/g, ' '); | ||
} | ||
const string = { | ||
excerpt, | ||
truncate, | ||
slug, | ||
interpolate, | ||
plural, | ||
pluralize, | ||
singular, | ||
isPlural, | ||
isSingular, | ||
camelCase, | ||
capitalCase, | ||
dashCase, | ||
dotCase, | ||
noCase, | ||
pascalCase, | ||
sentenceCase, | ||
snakeCase, | ||
titleCase, | ||
random, | ||
sentence, | ||
condenseWhitespace, | ||
seconds, | ||
milliseconds, | ||
bytes, | ||
ordinal, | ||
import { | ||
main_default | ||
} from "../../chunk-OKRMWJO4.js"; | ||
import "../../chunk-PWRXO3NF.js"; | ||
export { | ||
main_default as default | ||
}; | ||
export default string; |
type PickKeysByValue<T, V> = { | ||
[K in keyof T]: T[K] extends V ? K : never; | ||
}[keyof T]; | ||
export type OmitProperties<T, P> = Omit<T, PickKeysByValue<T, P>>; | ||
type OmitProperties<T, P> = Omit<T, PickKeysByValue<T, P>>; | ||
type ScanFsBaseOptions = { | ||
@@ -10,14 +10,24 @@ ignoreMissingRoot?: boolean; | ||
}; | ||
export type ImportAllFilesOptions = ScanFsBaseOptions & { | ||
type ImportAllFilesOptions = ScanFsBaseOptions & { | ||
/** | ||
* A custom method to transform collection keys | ||
*/ | ||
transformKeys?: (keys: string[]) => string[]; | ||
}; | ||
export type ReadAllFilesOptions = ScanFsBaseOptions & { | ||
type ReadAllFilesOptions = ScanFsBaseOptions & { | ||
pathType?: 'relative' | 'unixRelative' | 'absolute' | 'unixAbsolute' | 'url'; | ||
}; | ||
export type JSONReplacer = (this: any, key: string, value: any) => any; | ||
export type JSONReviver = (this: any, key: string, value: any) => any; | ||
export type Constructor = new (...args: any[]) => any; | ||
export type NormalizeConstructor<T extends Constructor> = { | ||
type JSONReplacer = (this: any, key: string, value: any) => any; | ||
type JSONReviver = (this: any, key: string, value: any) => any; | ||
type Constructor = new (...args: any[]) => any; | ||
/** | ||
* Normalizes constructor to work with mixins. There is an open bug for mixins | ||
* to allow constructors other than `...args: any[]` | ||
* | ||
* https://github.com/microsoft/TypeScript/issues/37142 | ||
*/ | ||
type NormalizeConstructor<T extends Constructor> = { | ||
new (...args: any[]): InstanceType<T>; | ||
} & Omit<T, 'constructor'>; | ||
export {}; | ||
export { Constructor, ImportAllFilesOptions, JSONReplacer, JSONReviver, NormalizeConstructor, OmitProperties, ReadAllFilesOptions }; |
{ | ||
"name": "@poppinss/utils", | ||
"version": "6.5.0-3", | ||
"version": "6.5.0-4", | ||
"description": "Handy utilities for repetitive work", | ||
@@ -35,7 +35,7 @@ "main": "build/index.js", | ||
"typecheck": "tsc --noEmit", | ||
"compile": "npm run lint && npm run clean && tsc", | ||
"compile": "npm run lint && npm run clean && tsup-node", | ||
"build": "npm run compile && npm run build:lodash", | ||
"release": "np", | ||
"version": "npm run build", | ||
"prepublishOnly": "npm run build && cd build && node bin/test.js", | ||
"prepublishOnly": "npm run build", | ||
"lint": "eslint . --ext=.ts", | ||
@@ -65,3 +65,3 @@ "format": "prettier --write .", | ||
"del-cli": "^5.0.0", | ||
"eslint": "^8.43.0", | ||
"eslint": "^8.45.0", | ||
"fs-extra": "^11.1.1", | ||
@@ -74,4 +74,5 @@ "github-label-sync": "^2.3.1", | ||
"np": "^8.0.4", | ||
"prettier": "^2.8.8", | ||
"prettier": "^3.0.0", | ||
"ts-node": "^10.9.1", | ||
"tsup": "^7.1.0", | ||
"typescript": "^5.1.6" | ||
@@ -82,3 +83,3 @@ }, | ||
"@types/bytes": "^3.1.1", | ||
"@types/pluralize": "^0.0.29", | ||
"@types/pluralize": "0.0.30", | ||
"bytes": "^3.1.2", | ||
@@ -131,3 +132,17 @@ "case-anything": "^2.1.13", | ||
}, | ||
"prettier": "@adonisjs/prettier-config" | ||
"prettier": "@adonisjs/prettier-config", | ||
"tsup": { | ||
"entry": [ | ||
"./index.ts", | ||
"./src/string/main.ts", | ||
"./src/string_builder.ts", | ||
"./src/json/main.ts", | ||
"./src/types.ts" | ||
], | ||
"outDir": "./build", | ||
"clean": true, | ||
"format": "esm", | ||
"dts": true, | ||
"target": "esnext" | ||
} | ||
} |
@@ -560,2 +560,3 @@ # @poppinss/utils | ||
### String builder | ||
The string builder offers a fluent API for applying a set of transforms on a string value. You can create an instance of the string builder as follows. | ||
@@ -942,2 +943,3 @@ | ||
#### importDefault | ||
A helper function that assert a lazy import function output to have a `default export`, otherwise raises an exception. | ||
@@ -944,0 +946,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1168
1111
93439
25
15
1
+ Added@types/pluralize@0.0.30(transitive)
- Removed@types/pluralize@0.0.29(transitive)
Updated@types/pluralize@0.0.30