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

stringx-js

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stringx-js - npm Package Compare versions

Comparing version
1.0.1
to
1.0.2
+14
index.d.ts
/**
* StringX-JS - Main Type Definitions
* A comprehensive JavaScript string manipulation library inspired by Laravel's Str helper
*
* @version 1.0.1
* @author Ayman Atmeh
* @license MIT
*/
import Str from './src/Str';
import { Stringable } from './src/Stringable';
export { Stringable };
export default Str;
/**
* StringX-JS - TypeScript Type Definitions
* A comprehensive JavaScript string manipulation library inspired by Laravel's Str helper
*/
import { Stringable } from './Stringable';
/**
* Main Str class with static methods for string manipulation
*/
declare class Str {
/**
* Create a new Stringable instance for fluent method chaining
* @param string - The string value to wrap
* @returns A Stringable instance for chaining
* @example
* Str.of('hello').upper().toString() // 'HELLO'
*/
static of(string: string): Stringable;
// Case Conversion
/**
* Convert a value to camelCase
* @param value - The string to convert
* @returns The camelCase string
* @example
* Str.camel('foo_bar') // 'fooBar'
*/
static camel(value: string): string;
/**
* Convert a string to kebab-case
* @param value - The string to convert
* @returns The kebab-case string
* @example
* Str.kebab('fooBar') // 'foo-bar'
*/
static kebab(value: string): string;
/**
* Convert a string to snake_case
* @param value - The string to convert
* @param delimiter - The delimiter to use (default: '_')
* @returns The snake_case string
* @example
* Str.snake('fooBar') // 'foo_bar'
*/
static snake(value: string, delimiter?: string): string;
/**
* Convert a value to StudlyCase (PascalCase)
* @param value - The string to convert
* @returns The StudlyCase string
* @example
* Str.studly('foo_bar') // 'FooBar'
*/
static studly(value: string): string;
/**
* Convert a value to PascalCase (alias for studly)
* @param value - The string to convert
* @returns The PascalCase string
* @example
* Str.pascal('foo_bar') // 'FooBar'
*/
static pascal(value: string): string;
static title(value: string): string;
static headline(value: string): string;
static upper(value: string): string;
static lower(value: string): string;
static ucfirst(string: string): string;
static lcfirst(string: string): string;
static apa(value: string): string;
static convertCase(string: string, mode?: 'lower' | 'upper' | 'title', encoding?: string): string;
// String Extraction
static after(subject: string, search: string): string;
static afterLast(subject: string, search: string): string;
static before(subject: string, search: string): string;
static beforeLast(subject: string, search: string): string;
static between(subject: string, from: string, to: string): string;
static betweenFirst(subject: string, from: string, to: string): string;
static charAt(subject: string, index: number): string;
static substr(string: string, start: number, length?: number | null): string;
static take(string: string, limit: number): string;
// String Checking
static contains(haystack: string, needles: string | string[], ignoreCase?: boolean): boolean;
static containsAll(haystack: string, needles: string[], ignoreCase?: boolean): boolean;
static doesntContain(haystack: string, needles: string | string[], ignoreCase?: boolean): boolean;
static startsWith(haystack: string, needles: string | string[]): boolean;
static doesntStartWith(haystack: string, needles: string | string[]): boolean;
static endsWith(haystack: string, needles: string | string[]): boolean;
static doesntEndWith(haystack: string, needles: string | string[]): boolean;
static is(pattern: string | string[], value: string, ignoreCase?: boolean): boolean;
static isAscii(value: string): boolean;
static isJson(value: string): boolean;
static isUrl(value: string, protocols?: string[]): boolean;
static isUuid(value: string): boolean;
static isUlid(value: string): boolean;
static isMatch(pattern: RegExp | string, value: string): boolean;
// String Manipulation
static limit(value: string, limit?: number, end?: string): string;
static words(value: string, words?: number, end?: string): string;
static mask(string: string, character: string, index: number, length?: number | null): string;
static trim(value: string, charlist?: string | null): string;
static ltrim(value: string, charlist?: string | null): string;
static rtrim(value: string, charlist?: string | null): string;
static squish(value: string): string;
static chopStart(subject: string, needle: string | string[]): string;
static chopEnd(subject: string, needle: string | string[]): string;
static finish(value: string, cap: string): string;
static start(value: string, prefix: string): string;
static wrap(value: string, before: string, after?: string | null): string;
static unwrap(value: string, before: string, after?: string | null): string;
static reverse(value: string): string;
static ascii(value: string, language?: string): string;
static transliterate(string: string, unknown?: string, strict?: boolean): string;
static wordWrap(string: string, characters?: number, breakStr?: string, cutLongWords?: boolean): string;
// String Replacement
static replace(search: string | string[], replace: string | string[], subject: string, caseSensitive?: boolean): string;
static replaceFirst(search: string, replace: string, subject: string): string;
static replaceLast(search: string, replace: string, subject: string): string;
static replaceArray(search: string, replace: string[], subject: string): string;
static replaceStart(search: string, replace: string, subject: string): string;
static replaceEnd(search: string, replace: string, subject: string): string;
static replaceMatches(pattern: RegExp | string, replace: string, subject: string, limit?: number): string;
static remove(search: string | string[], subject: string, caseSensitive?: boolean): string;
static swap(map: Record<string, string>, subject: string): string;
static deduplicate(string: string, characters?: string | string[]): string;
static substrReplace(string: string, replace: string, offset?: number, length?: number | null): string;
// Pattern Matching
static match(pattern: RegExp | string, subject: string): string | null;
static matchAll(pattern: RegExp | string, subject: string): string[];
// Padding
static padBoth(value: string, length: number, pad?: string): string;
static padLeft(value: string, length: number, pad?: string): string;
static padRight(value: string, length: number, pad?: string): string;
// String Information
static length(value: string): number;
static wordCount(string: string): number;
static substrCount(haystack: string, needle: string, offset?: number, length?: number | null): number;
static position(haystack: string, needle: string, offset?: number): number | false;
// String Generation
static random(length?: number): string;
static password(length?: number, letters?: boolean, numbers?: boolean, symbols?: boolean, spaces?: boolean): string;
static uuid(): string;
static uuid7(): string;
static ulid(): string;
// Pluralization
static plural(value: string, count?: number): string;
static singular(value: string): string;
static pluralStudly(value: string, count?: number): string;
static pluralPascal(value: string, count?: number): string;
// Other Utilities
static slug(title: string, separator?: string): string;
static numbers(value: string): string;
static excerpt(text: string, phrase?: string, options?: ExcerptOptions): string;
static ucsplit(string: string): string[];
static repeat(string: string, times: number): string;
// Encoding
static toBase64(string: string): string;
static fromBase64(string: string, strict?: boolean): string;
// Factories
static createUuidsUsing(factory: (() => string) | null): void;
static createUuidsNormally(): void;
static createUlidsUsing(factory: (() => string) | null): void;
static createUlidsNormally(): void;
static createRandomStringsUsing(factory: ((length: number) => string) | null): void;
static createRandomStringsNormally(): void;
// Cache Management
static flushCache(): void;
}
/**
* Options for the excerpt method
*/
export interface ExcerptOptions {
radius?: number;
omission?: string;
}
export default Str;
/**
* Stringable - TypeScript Type Definitions
* Fluent interface for string manipulation with method chaining
*/
/**
* Stringable class for fluent string manipulation
*/
export declare class Stringable {
/** The underlying string value */
protected value: string;
/**
* Create a new Stringable instance
*/
constructor(value?: string);
// Value Extraction
toString(): string;
valueOf(): string;
toJSON(): string;
// Utility Methods
append(...values: string[]): this;
prepend(...values: string[]): this;
pipe(callback: (value: string) => string): this;
tap(callback: (value: string) => void): this;
// Conditional Methods
when(condition: boolean | ((str: this) => boolean), callback: (str: this, condition?: any) => this | void, defaultCallback?: ((str: this) => this | void) | null): this;
unless(condition: boolean | ((str: this) => boolean), callback: (str: this) => this | void, defaultCallback?: ((str: this) => this | void) | null): this;
whenEmpty(callback: (str: this) => this | void): this;
whenNotEmpty(callback: (str: this) => this | void): this;
// Debugging
dump(): this;
dd(): never;
// Checking Methods
isEmpty(): boolean;
isNotEmpty(): boolean;
test(pattern: RegExp | string): boolean;
// String Extraction
after(search: string): this;
afterLast(search: string): this;
before(search: string): this;
beforeLast(search: string): this;
between(from: string, to: string): this;
betweenFirst(from: string, to: string): this;
charAt(index: number): string;
substr(start: number, length?: number | null): this;
take(limit: number): this;
// Case Conversion
camel(): this;
kebab(): this;
snake(delimiter?: string): this;
studly(): this;
pascal(): this;
title(): this;
headline(): this;
upper(): this;
lower(): this;
ucfirst(): this;
lcfirst(): this;
apa(): this;
convertCase(mode?: 'lower' | 'upper' | 'title', encoding?: string): this;
// String Checking (returns boolean, not chainable)
contains(needles: string | string[], ignoreCase?: boolean): boolean;
containsAll(needles: string[], ignoreCase?: boolean): boolean;
doesntContain(needles: string | string[], ignoreCase?: boolean): boolean;
startsWith(needles: string | string[]): boolean;
doesntStartWith(needles: string | string[]): boolean;
endsWith(needles: string | string[]): boolean;
doesntEndWith(needles: string | string[]): boolean;
is(pattern: string | string[], ignoreCase?: boolean): boolean;
isAscii(): boolean;
isJson(): boolean;
isUrl(protocols?: string[]): boolean;
isUuid(): boolean;
isUlid(): boolean;
isMatch(pattern: RegExp | string): boolean;
// String Manipulation
limit(limit?: number, end?: string): this;
words(words?: number, end?: string): this;
mask(character: string, index: number, length?: number | null): this;
trim(charlist?: string | null): this;
ltrim(charlist?: string | null): this;
rtrim(charlist?: string | null): this;
squish(): this;
chopStart(needle: string | string[]): this;
chopEnd(needle: string | string[]): this;
finish(cap: string): this;
start(prefix: string): this;
wrap(before: string, after?: string | null): this;
unwrap(before: string, after?: string | null): this;
reverse(): this;
ascii(language?: string): this;
transliterate(unknown?: string, strict?: boolean): this;
wordWrap(characters?: number, breakStr?: string, cutLongWords?: boolean): this;
// String Replacement
replace(search: string | string[], replace: string | string[], caseSensitive?: boolean): this;
replaceFirst(search: string, replace: string): this;
replaceLast(search: string, replace: string): this;
replaceArray(search: string, replace: string[]): this;
replaceStart(search: string, replace: string): this;
replaceEnd(search: string, replace: string): this;
replaceMatches(pattern: RegExp | string, replace: string, limit?: number): this;
remove(search: string | string[], caseSensitive?: boolean): this;
swap(map: Record<string, string>): this;
deduplicate(characters?: string | string[]): this;
substrReplace(replace: string, offset?: number, length?: number | null): this;
// Pattern Matching (returns values, not chainable)
match(pattern: RegExp | string): string | null;
matchAll(pattern: RegExp | string): string[];
// Padding
padBoth(length: number, pad?: string): this;
padLeft(length: number, pad?: string): this;
padRight(length: number, pad?: string): this;
// String Information (returns values, not chainable)
length(): number;
wordCount(): number;
substrCount(needle: string, offset?: number, length?: number | null): number;
position(needle: string, offset?: number): number | false;
// Pluralization
plural(count?: number): this;
singular(): this;
pluralStudly(count?: number): this;
// Other Utilities
slug(separator?: string): this;
numbers(): this;
excerpt(phrase?: string, options?: { radius?: number; omission?: string }): this;
ucsplit(): string[];
repeat(times: number): this;
// Encoding
toBase64(): this;
fromBase64(strict?: boolean): this;
// Additional utilities
substring(start: number, length: number): this;
}
export default Stringable;
+44
-0

@@ -8,2 +8,45 @@ # Changelog

## [1.0.2] - 2024-10-28
### Added
- **🎯 Full TypeScript support with complete type definitions**
- `index.d.ts` - Main entry point type definitions
- `src/Str.d.ts` - Complete types for all 95+ static methods
- `src/Stringable.d.ts` - Complete types for all 95+ fluent methods
- Added `"types": "index.d.ts"` to package.json
- **✨ IDE Autocomplete & IntelliSense support**
- Full autocomplete when typing `Str.` (shows all 95+ methods)
- Parameter hints with type information
- Return type inference
- Hover documentation with JSDoc comments
- Works in JavaScript (.js) and TypeScript (.ts) files
- Zero configuration required - works automatically after npm install
- **📁 Better project organization**
- Created `examples/` folder for all example files
- Moved `examples.js` → `examples/examples.js`
- Moved `chaining-examples.js` → `examples/chaining-examples.js`
- Added `examples/typescript-example.ts` with comprehensive TypeScript examples
- Updated `.npmignore` to exclude examples folder
### Changed
- **Updated terminology to match Laravel**
- Changed "Stringable API" to "Fluent Strings" in README
- Aligned documentation with Laravel's official terminology
- **Enhanced type definitions**
- Added JSDoc comments to key methods for better IDE hover documentation
- Improved parameter descriptions and examples
- **Package metadata**
- Added "typescript" keyword for better npm discoverability
- Updated files array to include all TypeScript definition files
### Developer Experience
- ✅ Full IntelliSense in VS Code
- ✅ Smart autocomplete in WebStorm/PhpStorm
- ✅ Type checking in TypeScript projects
- ✅ Parameter hints in all modern IDEs
- ✅ Hover documentation with examples
- ✅ Go to definition support
- ✅ Works in both .js and .ts files
## [1.0.1] - 2024-10-27

@@ -75,3 +118,4 @@

[1.0.2]: https://github.com/yourusername/stringx-js/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/yourusername/stringx-js/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/yourusername/stringx-js/releases/tag/v1.0.0
+6
-1
{
"name": "stringx-js",
"version": "1.0.1",
"version": "1.0.2",
"description": "A comprehensive JavaScript string manipulation library inspired by Laravel's Str helper class with 95+ methods for case conversion, validation, manipulation, and generation. Now with fluent method chaining!",
"type": "module",
"main": "index.js",
"types": "index.d.ts",
"scripts": {

@@ -19,2 +20,3 @@ "test": "node --test src/tests/*.test.js",

"javascript",
"typescript",
"es6",

@@ -55,4 +57,7 @@ "string-manipulation",

"index.js",
"index.d.ts",
"src/Str.js",
"src/Str.d.ts",
"src/Stringable.js",
"src/Stringable.d.ts",
"src/helpers.js",

@@ -59,0 +64,0 @@ "README.md",

+368
-0

@@ -11,2 +11,30 @@ # StringX-JS

## TypeScript Support
StringX-JS includes full TypeScript type definitions out of the box! No need to install separate `@types` packages.
```typescript
import Str from 'stringx-js';
// Full type safety and IntelliSense support
const result: string = Str.of('hello_world')
.camel()
.append('Test')
.toString();
// Type inference works automatically
const slug = Str.slug('Hello World'); // Type: string
const isValid = Str.isUuid(value); // Type: boolean
const matches = Str.matchAll(/\d+/g, text); // Type: string[]
```
TypeScript features:
- ✅ Full type definitions for all methods
- ✅ Generic type support for callbacks
- ✅ Proper return type inference
- ✅ IntelliSense/autocomplete in VS Code
- ✅ Compile-time type checking
See [examples/typescript-example.ts](examples/typescript-example.ts) for comprehensive TypeScript usage examples.
## Usage

@@ -276,2 +304,298 @@

## Advanced Usage
### Custom Transformations with `pipe()`
The `pipe()` method allows you to pass the string through any custom function, enabling unlimited flexibility:
```javascript
// Complex email masking
const maskedEmail = Str.of('john.doe@example.com')
.pipe(email => {
const [name, domain] = email.split('@');
const maskedName = name[0] + '*'.repeat(name.length - 1);
return `${maskedName}@${domain}`;
})
.toString(); // 'j*******@example.com'
// Custom business logic
const processedText = Str.of('user_input_123')
.pipe(str => str.replace(/\d+/g, ''))
.pipe(str => str.toUpperCase())
.pipe(str => customBusinessLogic(str))
.toString();
// Integration with external libraries
import slugify from 'some-slugify-lib';
const slug = Str.of(title)
.trim()
.pipe(str => slugify(str, { strict: true }))
.toString();
```
### Debugging with `tap()` and `dump()`
Debug your transformation chains without breaking the flow:
```javascript
// Using tap() to inspect values at each step
const result = Str.of(' HELLO_WORLD ')
.tap(val => console.log('Original:', val)) // Original: HELLO_WORLD
.trim()
.tap(val => console.log('After trim:', val)) // After trim: HELLO_WORLD
.lower()
.tap(val => console.log('After lower:', val)) // After lower: hello_world
.camel()
.tap(val => console.log('After camel:', val)) // After camel: helloWorld
.toString();
// Using dump() for quick logging
const processed = Str.of(userInput)
.trim()
.dump() // Logs the value
.squish()
.dump() // Logs again
.ucfirst()
.toString();
// Conditional debugging
const debugMode = process.env.DEBUG === 'true';
const output = Str.of(data)
.trim()
.when(debugMode, str => str.dump()) // Only logs in debug mode
.camel()
.toString();
```
### Advanced Conditional Logic
Build complex conditional transformation chains:
```javascript
// Multiple conditions with fallbacks
const formatUsername = (name, options = {}) => {
return Str.of(name)
.trim()
.lower()
.when(options.removeSpaces, str => str.replace(' ', ''))
.when(options.maxLength, (str) => str.limit(options.maxLength, ''))
.whenEmpty(str => str.append('anonymous'))
.unless(options.allowSpecialChars, str => str.replace(/[^a-z0-9]/g, ''))
.when(
str => str.length() < 3,
str => str.padRight(3, 'x'),
str => str // else, return unchanged
)
.toString();
};
// Nested conditions
const displayPrice = Str.of(price.toString())
.when(
currency === 'USD',
str => str.prepend('$'),
str => str.append(` ${currency}`)
)
.when(
isDiscounted,
str => str.append(' (SALE!)').upper()
)
.whenNotEmpty(str => str.wrap('<span class="price">', '</span>'))
.toString();
// Condition based on string content
const processApiResponse = Str.of(response)
.when(
str => str.contains('error'),
str => str.upper().prepend('⚠️ '),
str => str.prepend('✅ ')
)
.when(
str => str.length() > 100,
str => str.limit(100)
)
.toString();
```
### Working with APIs and Data Transformation
Transform API responses and data structures:
```javascript
// Transform API error messages
const formatApiError = (errorCode) => {
return Str.of(errorCode)
.upper() // ERROR_USER_NOT_FOUND
.replace('_', ' ') // ERROR USER NOT FOUND
.after('ERROR ') // USER NOT FOUND
.lower() // user not found
.ucfirst() // User not found
.append('.') // User not found.
.toString();
};
// Generate API endpoints
const buildEndpoint = (resource, id, action) => {
return Str.of(resource)
.plural() // users
.kebab() // users (already kebab)
.prepend('/api/v1/') // /api/v1/users
.when(id, str => str.append(`/${id}`)) // /api/v1/users/123
.when(action, str => str.append(`/${action}`)) // /api/v1/users/123/activate
.finish('/') // /api/v1/users/123/activate/
.toString();
};
// Parse and format JSON paths
const formatJsonPath = Str.of('data.user.profile.email')
.explode('.') // Would return array if we had explode()
.pipe(parts => parts.join('.')) // Using pipe as alternative
.replace('.', ' → ') // data → user → profile → email
.title() // Data → User → Profile → Email
.toString();
```
### Text Processing and Sanitization
Advanced text cleaning and formatting:
```javascript
// Clean and format user-generated content
const sanitizeContent = (content) => {
return Str.of(content)
.trim()
.squish() // Remove extra whitespace
.replace(/[<>]/g, '') // Remove potential HTML
.deduplicate(['.', '!', '?']) // Remove duplicate punctuation
.limit(500) // Limit length
.when(
str => !str.test(/[.!?]$/),
str => str.append('...') // Add ellipsis if needed
)
.toString();
};
// Extract and format hashtags
const formatHashtags = (text) => {
return Str.of(text)
.matchAll(/#\w+/g)
.pipe(tags => tags.map(tag =>
Str.of(tag)
.chopStart('#')
.lower()
.toString()
))
.pipe(tags => tags.join(', '));
};
// Generate readable IDs
const generateReadableId = (text) => {
return Str.of(text)
.slug()
.append('-')
.append(Str.random(8).lower())
.toString(); // 'my-awesome-post-a3f7d9e2'
};
```
### Combining Static and Fluent Methods
Mix both approaches for optimal code:
```javascript
// Use static methods for simple checks
if (Str.contains(email, '@')) {
// Use fluent for complex transformations
const formatted = Str.of(email)
.lower()
.trim()
.before('@')
.toString();
}
// Static for generation, fluent for formatting
const userId = Str.uuid();
const formattedId = Str.of(userId)
.upper()
.replace(/-/g, '')
.limit(12)
.toString();
// Create reusable transformation functions
const toSlug = (text) => Str.of(text).slug().toString();
const toHandle = (name) => Str.of(name).lower().replace(' ', '').prepend('@').toString();
const slug = toSlug('Hello World'); // 'hello-world'
const handle = toHandle('John Doe'); // '@johndoe'
```
### Error Handling Patterns
Handle edge cases gracefully:
```javascript
// Safe transformations with fallbacks
const safeFormat = (input, fallback = 'N/A') => {
return Str.of(input ?? '')
.whenEmpty(str => str.append(fallback))
.trim()
.toString();
};
// Validate and transform
const processUsername = (username) => {
const processed = Str.of(username)
.trim()
.lower()
.toString();
// Validate using static methods
if (!Str.isMatch(/^[a-z0-9_]{3,20}$/, processed)) {
throw new Error('Invalid username format');
}
return processed;
};
// Try-catch with fluent chains
try {
const result = Str.of(jsonString)
.pipe(str => {
if (!Str.isJson(str)) throw new Error('Invalid JSON');
return JSON.parse(str);
})
.pipe(obj => obj.data.value)
.toString();
} catch (error) {
console.error('Processing failed:', error.message);
}
```
### Performance Optimization
Tips for optimal performance:
```javascript
// Cache Stringable instances for repeated use
const formatter = Str.of(template);
const results = data.map(item =>
formatter.replace('{name}', item.name).toString()
);
// Use static methods for single operations
const lower = Str.lower(text); // Faster than Str.of(text).lower().toString()
// Chain when doing multiple operations
const processed = Str.of(text) // Better than multiple Str calls
.trim()
.lower()
.camel()
.toString();
// Clear caches if processing lots of unique strings
Str.flushCache();
```
## Available Methods

@@ -1070,1 +1394,45 @@

Inspired by Laravel's [Str helper](https://laravel.com/docs/strings).
## Autocomplete & IntelliSense
StringX-JS includes full autocomplete support in all modern IDEs! 🎯
### What You Get
When you type `Str.` you'll see **all 95+ methods** with:
- ✅ Method names and descriptions
- ✅ Parameter types and hints
- ✅ Return type information
- ✅ Inline documentation
```javascript
import Str from 'stringx-js';
// Type "Str." and see autocomplete:
Str.camel() // ← Shows: (value: string): string
Str.contains() // ← Shows: (haystack: string, needles: string | string[]): boolean
Str.uuid() // ← Shows: (): string
// ... 92+ more methods with autocomplete
```
### Fluent Chaining Autocomplete
```javascript
// Type ".of('text')." to see all chainable methods:
Str.of('hello')
.upper() // ← Autocomplete shows this
.trim() // ← And this
.camel() // ← And this
.toString(); // ← And this
```
### Works Everywhere
- ✅ **VS Code** - Full IntelliSense support
- ✅ **WebStorm/PhpStorm** - Smart autocomplete
- ✅ **JavaScript files** - JSDoc-based autocomplete
- ✅ **TypeScript files** - Full type checking
- ✅ **Zero configuration** - Works automatically
See [AUTOCOMPLETE-GUIDE.md](AUTOCOMPLETE-GUIDE.md) for details and [autocomplete-demo.js](autocomplete-demo.js) for a hands-on demonstration.