@ppabari/strio 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +57 -3
- package/dist/bin/strio.js +53 -0
- package/dist/index.cjs +51 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -3
- package/dist/index.d.ts +51 -3
- package/dist/index.js +49 -1
- package/dist/index.js.map +1 -1
- package/dist/str.cjs +623 -0
- package/dist/str.cjs.map +1 -0
- package/dist/str.d.cts +579 -0
- package/dist/str.d.ts +579 -0
- package/dist/str.js +567 -0
- package/dist/str.js.map +1 -0
- package/dist/{zod-CINbFpp9.d.cts → zod-IWq12GIY.d.cts} +1 -1
- package/dist/{zod-CINbFpp9.d.ts → zod-IWq12GIY.d.ts} +1 -1
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/package.json +31 -8
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,48 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.1.0] — 2026-07-07
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
**String-utility toolkit** — new `@ppabari/strio/str` subpath export (~60 pure, tree-shakeable functions):
|
|
14
|
+
|
|
15
|
+
- **Manipulation** — `capitalize`, `capitalizeWords`, `reverse`, `truncate`, `truncateWords`, `trim`, `insert`, `mask`
|
|
16
|
+
- **Case conversion** — `camelize`, `pascalize`, `dasherize`, `underscore`
|
|
17
|
+
- **Validation** — `isEmpty`, `isBlank`, `isString`, `isAlpha`, `isNumeric`, `isAlphaNumeric`, `isUpperCase`, `isLowerCase`
|
|
18
|
+
- **Searching** — `contains`, `containsAll`, `containsAny`, `count`, `between`, `betweenAll`
|
|
19
|
+
- **Formatting** — `humanize`, `titleCase`, `slugify`, `ordinalize`, `pluralize`
|
|
20
|
+
- **Utilities** — `words`, `wordCount`, `join`, `template`, `random`, `randomAlpha`, `randomNumeric`, `randomAlphanumeric`, `similarity`, `transliterate`
|
|
21
|
+
- **Padding & indentation** — `padLeft`, `padRight`, `padCenter`, `indent`, `dedent`
|
|
22
|
+
- **Security** — `escapeHtml`, `unescapeHtml`, `escapeRegExp`, `stripTags`, `collapseWhitespace`, `stripPrefix`, `stripSuffix`
|
|
23
|
+
- **Ensuring** — `ensureLeft`, `ensureRight`
|
|
24
|
+
|
|
25
|
+
> The `random*` helpers reuse the same bias-free Web-Crypto engine as the core library, so they are cryptographically secure.
|
|
26
|
+
|
|
27
|
+
**Compatibility checks** (main export)
|
|
28
|
+
|
|
29
|
+
- `checkCompatibility()` — inspect the runtime (Web Crypto availability, detected runtime, Node version) without throwing
|
|
30
|
+
- `assertCompatible()` — throw a descriptive error on an unsupported runtime
|
|
31
|
+
- `MIN_NODE_VERSION` constant and `CompatibilityResult` / `Runtime` types
|
|
32
|
+
- CLI: new `--check` (alias `--compat`) flag prints a compatibility report
|
|
33
|
+
|
|
34
|
+
**Docs**
|
|
35
|
+
|
|
36
|
+
- New VitePress documentation site with a categorized API reference
|
|
37
|
+
|
|
38
|
+
### Maintenance
|
|
39
|
+
|
|
40
|
+
- Upgraded the entire dev toolchain to latest — `vitest` & `@vitest/coverage-v8` v4, `vitepress` v2, `typescript` v6, `@types/node` v26, `zod` v4 (dev/test only) — resolving **all** `npm audit` findings (6 → 0, including the vite dev-server high/critical advisories). All were dev-only and never affected the published package.
|
|
41
|
+
- Pinned transitive `esbuild` to a safe `0.27.2` via `overrides`.
|
|
42
|
+
- Added `"ignoreDeprecations": "6.0"` to `tsconfig.json` for TypeScript 6 compatibility.
|
|
43
|
+
- Note: building/testing the package now requires Node ≥ 20 (per vitest 4). The published library's **runtime** support is unchanged — still Node ≥ 18, browsers, Deno, Bun, and edge runtimes.
|
|
44
|
+
|
|
45
|
+
### Notes
|
|
46
|
+
|
|
47
|
+
- Fully backward compatible — no changes to the existing `.` or `/zod` surface. String utilities are isolated under `/str`, so names that overlap conceptually with the core API (`random`, `mask`) do not collide.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
9
51
|
## [1.0.0] — 2025
|
|
10
52
|
|
|
11
53
|
### Added
|
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# @ppabari/strio
|
|
2
2
|
|
|
3
|
-
Cryptographically secure string generation for Node.js and browsers.
|
|
4
|
-
Tokens · IDs · Passphrases · Patterns · Expiring tokens — bias-free, zero dependencies, fully typed.
|
|
3
|
+
Cryptographically secure string generation **and** a general-purpose string-utility toolkit for Node.js and browsers.
|
|
4
|
+
Tokens · IDs · Passphrases · Patterns · Expiring tokens · 60+ string helpers — bias-free, zero dependencies, fully typed.
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/@ppabari/strio)
|
|
7
7
|
[](./LICENSE)
|
|
8
|
-
[](https://github.com/parthpabari/strio/actions)
|
|
9
|
+
|
|
10
|
+
📖 **[Documentation](https://parthpabari.github.io/strio/)** · [API Reference](https://parthpabari.github.io/strio/api/overview)
|
|
9
11
|
|
|
10
12
|
---
|
|
11
13
|
|
|
@@ -61,11 +63,63 @@ npx @ppabari/strio --passphrase --words 5 --capitalize
|
|
|
61
63
|
npx @ppabari/strio --id --prefix usr
|
|
62
64
|
npx @ppabari/strio --expiring --ttl 900
|
|
63
65
|
npx @ppabari/strio --entropy --preset PASSWORD
|
|
66
|
+
npx @ppabari/strio --check # runtime compatibility report
|
|
64
67
|
npx @ppabari/strio --help
|
|
65
68
|
```
|
|
66
69
|
|
|
67
70
|
---
|
|
68
71
|
|
|
72
|
+
## String Utility Toolkit
|
|
73
|
+
|
|
74
|
+
Beyond secure generation, strio ships **60+ general-purpose string helpers** from the tree-shakeable `@ppabari/strio/str` subpath. Every function is a pure named export.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { slugify, camelize, truncate, pluralize } from '@ppabari/strio/str';
|
|
78
|
+
|
|
79
|
+
slugify('Héllo, World!'); // → 'hello-world'
|
|
80
|
+
camelize('foo-bar_baz'); // → 'fooBarBaz'
|
|
81
|
+
truncate('The quick brown fox', 12); // → 'The quick b…'
|
|
82
|
+
pluralize('child'); // → 'children'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| Category | Functions |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| **Manipulation** | `capitalize` `capitalizeWords` `reverse` `truncate` `truncateWords` `trim` `insert` `mask` |
|
|
88
|
+
| **Case Conversion** | `camelize` `pascalize` `dasherize` `underscore` |
|
|
89
|
+
| **Validation** | `isEmpty` `isBlank` `isString` `isAlpha` `isNumeric` `isAlphaNumeric` `isUpperCase` `isLowerCase` |
|
|
90
|
+
| **Searching** | `contains` `containsAll` `containsAny` `count` `between` `betweenAll` |
|
|
91
|
+
| **Formatting** | `humanize` `titleCase` `slugify` `ordinalize` `pluralize` |
|
|
92
|
+
| **Utilities** | `words` `wordCount` `join` `template` `random` `randomAlpha` `randomNumeric` `randomAlphanumeric` `similarity` `transliterate` |
|
|
93
|
+
| **Padding & Indentation** | `padLeft` `padRight` `padCenter` `indent` `dedent` |
|
|
94
|
+
| **Security** | `escapeHtml` `unescapeHtml` `escapeRegExp` `stripTags` `collapseWhitespace` `stripPrefix` `stripSuffix` |
|
|
95
|
+
| **Ensuring** | `ensureLeft` `ensureRight` |
|
|
96
|
+
|
|
97
|
+
> The `random*` helpers reuse the same bias-free Web-Crypto engine as the core library — they are cryptographically secure, not `Math.random`.
|
|
98
|
+
|
|
99
|
+
Full signatures and examples: **[API Reference →](https://parthpabari.github.io/strio/api/overview)**
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Compatibility Check
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { checkCompatibility, assertCompatible } from '@ppabari/strio';
|
|
107
|
+
|
|
108
|
+
const report = checkCompatibility();
|
|
109
|
+
// { ok: true, cryptoAvailable: true, runtime: 'node', nodeVersion: '20.11.0', warnings: [] }
|
|
110
|
+
|
|
111
|
+
assertCompatible(); // throws on an unsupported runtime
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Environment | Supported |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| Node.js | ✅ ≥ 18 |
|
|
117
|
+
| Browsers (modern) | ✅ |
|
|
118
|
+
| Deno · Bun · Cloudflare Workers | ✅ |
|
|
119
|
+
| TypeScript | ✅ ≥ 5.0 |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
69
123
|
## Core API
|
|
70
124
|
|
|
71
125
|
### `generateRandomString(options?)`
|
package/dist/bin/strio.js
CHANGED
|
@@ -1218,6 +1218,47 @@ function approximateCombinations(charsetSize, length) {
|
|
|
1218
1218
|
return Math.round(Math.pow(charsetSize, length)).toString();
|
|
1219
1219
|
}
|
|
1220
1220
|
|
|
1221
|
+
// src/compat.ts
|
|
1222
|
+
var MIN_NODE_VERSION = 18;
|
|
1223
|
+
function detectRuntime() {
|
|
1224
|
+
const g = globalThis;
|
|
1225
|
+
if (typeof g.Deno !== "undefined") return { runtime: "deno" };
|
|
1226
|
+
if (typeof g.Bun !== "undefined") return { runtime: "bun" };
|
|
1227
|
+
if (typeof g.process !== "undefined" && g.process?.versions?.node) {
|
|
1228
|
+
return { runtime: "node", nodeVersion: String(g.process.versions.node) };
|
|
1229
|
+
}
|
|
1230
|
+
if (typeof g.WebSocketPair !== "undefined") return { runtime: "workerd" };
|
|
1231
|
+
if (typeof g.window !== "undefined" || typeof g.document !== "undefined") {
|
|
1232
|
+
return { runtime: "browser" };
|
|
1233
|
+
}
|
|
1234
|
+
return { runtime: "unknown" };
|
|
1235
|
+
}
|
|
1236
|
+
function checkCompatibility() {
|
|
1237
|
+
const warnings = [];
|
|
1238
|
+
const { runtime, nodeVersion } = detectRuntime();
|
|
1239
|
+
const cryptoAvailable = typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.getRandomValues === "function";
|
|
1240
|
+
if (!cryptoAvailable) {
|
|
1241
|
+
warnings.push(
|
|
1242
|
+
"Web Crypto API (crypto.getRandomValues) is unavailable. Secure generation will fail. On Node.js, upgrade to v18 or newer."
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1245
|
+
if (runtime === "node" && nodeVersion) {
|
|
1246
|
+
const major = parseInt(nodeVersion.split(".")[0] ?? "0", 10);
|
|
1247
|
+
if (major < MIN_NODE_VERSION) {
|
|
1248
|
+
warnings.push(
|
|
1249
|
+
`Node.js ${nodeVersion} is below the supported minimum (v${MIN_NODE_VERSION}). Please upgrade.`
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
return {
|
|
1254
|
+
ok: cryptoAvailable && warnings.length === 0,
|
|
1255
|
+
cryptoAvailable,
|
|
1256
|
+
runtime,
|
|
1257
|
+
...nodeVersion ? { nodeVersion } : {},
|
|
1258
|
+
warnings
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1221
1262
|
// src/presets.ts
|
|
1222
1263
|
var PRESETS = {
|
|
1223
1264
|
/**
|
|
@@ -1380,6 +1421,7 @@ if (hasFlag("help") || hasFlag("h")) {
|
|
|
1380
1421
|
--payload <n> Payload length (default: 24)
|
|
1381
1422
|
|
|
1382
1423
|
--entropy Show entropy estimate only (no string generated)
|
|
1424
|
+
--check Check runtime compatibility and exit
|
|
1383
1425
|
|
|
1384
1426
|
PRESETS
|
|
1385
1427
|
TOKEN 32-char alphanumeric API token
|
|
@@ -1406,6 +1448,17 @@ if (hasFlag("help") || hasFlag("h")) {
|
|
|
1406
1448
|
`);
|
|
1407
1449
|
process.exit(0);
|
|
1408
1450
|
}
|
|
1451
|
+
if (hasFlag("check") || hasFlag("compat")) {
|
|
1452
|
+
const report = checkCompatibility();
|
|
1453
|
+
console.log(`Runtime : ${report.runtime}${report.nodeVersion ? ` (Node ${report.nodeVersion})` : ""}`);
|
|
1454
|
+
console.log(`Web Crypto : ${report.cryptoAvailable ? "available" : "MISSING"}`);
|
|
1455
|
+
console.log(`Compatible : ${report.ok ? "yes" : "no"}`);
|
|
1456
|
+
if (report.warnings.length > 0) {
|
|
1457
|
+
console.log("Warnings :");
|
|
1458
|
+
report.warnings.forEach((w) => console.log(` - ${w}`));
|
|
1459
|
+
}
|
|
1460
|
+
process.exit(report.ok ? 0 : 1);
|
|
1461
|
+
}
|
|
1409
1462
|
if (hasFlag("passphrase")) {
|
|
1410
1463
|
const words = parseInt(getFlag("words") ?? "4", 10);
|
|
1411
1464
|
const separator = getFlag("separator") ?? "-";
|
package/dist/index.cjs
CHANGED
|
@@ -1431,6 +1431,54 @@ function validatePattern(str, pattern) {
|
|
|
1431
1431
|
return errors;
|
|
1432
1432
|
}
|
|
1433
1433
|
|
|
1434
|
+
// src/compat.ts
|
|
1435
|
+
var MIN_NODE_VERSION = 18;
|
|
1436
|
+
function detectRuntime() {
|
|
1437
|
+
const g = globalThis;
|
|
1438
|
+
if (typeof g.Deno !== "undefined") return { runtime: "deno" };
|
|
1439
|
+
if (typeof g.Bun !== "undefined") return { runtime: "bun" };
|
|
1440
|
+
if (typeof g.process !== "undefined" && g.process?.versions?.node) {
|
|
1441
|
+
return { runtime: "node", nodeVersion: String(g.process.versions.node) };
|
|
1442
|
+
}
|
|
1443
|
+
if (typeof g.WebSocketPair !== "undefined") return { runtime: "workerd" };
|
|
1444
|
+
if (typeof g.window !== "undefined" || typeof g.document !== "undefined") {
|
|
1445
|
+
return { runtime: "browser" };
|
|
1446
|
+
}
|
|
1447
|
+
return { runtime: "unknown" };
|
|
1448
|
+
}
|
|
1449
|
+
function checkCompatibility() {
|
|
1450
|
+
const warnings = [];
|
|
1451
|
+
const { runtime, nodeVersion } = detectRuntime();
|
|
1452
|
+
const cryptoAvailable = typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.getRandomValues === "function";
|
|
1453
|
+
if (!cryptoAvailable) {
|
|
1454
|
+
warnings.push(
|
|
1455
|
+
"Web Crypto API (crypto.getRandomValues) is unavailable. Secure generation will fail. On Node.js, upgrade to v18 or newer."
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
if (runtime === "node" && nodeVersion) {
|
|
1459
|
+
const major = parseInt(nodeVersion.split(".")[0] ?? "0", 10);
|
|
1460
|
+
if (major < MIN_NODE_VERSION) {
|
|
1461
|
+
warnings.push(
|
|
1462
|
+
`Node.js ${nodeVersion} is below the supported minimum (v${MIN_NODE_VERSION}). Please upgrade.`
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return {
|
|
1467
|
+
ok: cryptoAvailable && warnings.length === 0,
|
|
1468
|
+
cryptoAvailable,
|
|
1469
|
+
runtime,
|
|
1470
|
+
...nodeVersion ? { nodeVersion } : {},
|
|
1471
|
+
warnings
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
function assertCompatible() {
|
|
1475
|
+
const report = checkCompatibility();
|
|
1476
|
+
if (!report.ok) {
|
|
1477
|
+
throw new Error(`@ppabari/strio: incompatible runtime.
|
|
1478
|
+
- ${report.warnings.join("\n- ")}`);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1434
1482
|
// src/presets.ts
|
|
1435
1483
|
var PRESETS = {
|
|
1436
1484
|
/**
|
|
@@ -1880,7 +1928,10 @@ async function generateRandomStringAsync(options = {}) {
|
|
|
1880
1928
|
|
|
1881
1929
|
exports.BUILT_IN_WORD_LIST = WORD_LIST;
|
|
1882
1930
|
exports.CHARSET_ALIASES = CHARSET_ALIASES;
|
|
1931
|
+
exports.MIN_NODE_VERSION = MIN_NODE_VERSION;
|
|
1883
1932
|
exports.PRESETS = PRESETS;
|
|
1933
|
+
exports.assertCompatible = assertCompatible;
|
|
1934
|
+
exports.checkCompatibility = checkCompatibility;
|
|
1884
1935
|
exports.estimateEntropy = estimateEntropy;
|
|
1885
1936
|
exports.generateAesKey = generateAesKey;
|
|
1886
1937
|
exports.generateApiKey = generateApiKey;
|