@splendidlabz/utils 1.11.2 → 1.11.4
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/dist/cjs/dom/accessibility.cjs +2 -0
- package/dist/cjs/dom/actions/index.cjs +392 -7
- package/dist/cjs/dom/actions/masonry.cjs +97 -6
- package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +58 -14
- package/dist/cjs/dom/actions/sticky.cjs +126 -6
- package/dist/cjs/dom/bounding-box.cjs +2 -0
- package/dist/cjs/dom/clipboard.cjs +2 -0
- package/dist/cjs/dom/cookie.cjs +3 -1
- package/dist/cjs/dom/css-vars.cjs +13 -3
- package/dist/cjs/dom/events.cjs +2 -0
- package/dist/cjs/dom/focusable.cjs +2 -0
- package/dist/cjs/dom/font-size.cjs +15 -3
- package/dist/cjs/dom/get-element.cjs +3 -1
- package/dist/cjs/dom/hash.cjs +2 -0
- package/dist/cjs/dom/index.cjs +1249 -47
- package/dist/cjs/dom/keyboard.cjs +2 -0
- package/dist/cjs/dom/local-store.cjs +3 -1
- package/dist/cjs/dom/media.cjs +2 -0
- package/dist/cjs/dom/observers/index.cjs +235 -9
- package/dist/cjs/dom/observers/intersection-observer.cjs +38 -6
- package/dist/cjs/dom/observers/mutation-observer.cjs +38 -6
- package/dist/cjs/dom/observers/observer.cjs +12 -2
- package/dist/cjs/dom/observers/resize-observer.cjs +38 -6
- package/dist/cjs/dom/observers/scroll-observer.cjs +62 -3
- package/dist/cjs/dom/pkce.cjs +13 -3
- package/dist/cjs/dom/query-params.cjs +3 -1
- package/dist/cjs/dom/random-string.cjs +2 -0
- package/dist/cjs/dom/sanitize.cjs +27 -3
- package/dist/cjs/dom/session-store.cjs +3 -1
- package/dist/cjs/dom/spam-prevention.cjs +2 -0
- package/dist/cjs/dom/trap-focus.cjs +131 -9
- package/dist/cjs/dom/ui/aria-current.cjs +2 -0
- package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +2 -0
- package/dist/cjs/dom/ui/index.cjs +87 -9
- package/dist/cjs/dom/ui/scroll-container.cjs +2 -0
- package/dist/cjs/dom/ui/traverse-and-scramble.cjs +2 -0
- package/dist/cjs/lib/arrays/index.cjs +121 -13
- package/dist/cjs/lib/arrays/item-position.cjs +2 -0
- package/dist/cjs/lib/arrays/join.cjs +10 -2
- package/dist/cjs/lib/arrays/shuffle.cjs +2 -0
- package/dist/cjs/lib/arrays/sort.cjs +11 -3
- package/dist/cjs/lib/arrays/split-array.cjs +2 -0
- package/dist/cjs/lib/arrays/unique.cjs +2 -0
- package/dist/cjs/lib/auth/index.cjs +35 -3
- package/dist/cjs/lib/auth/route-manager.cjs +2 -0
- package/dist/cjs/lib/checks.cjs +2 -0
- package/dist/cjs/lib/date/days.cjs +3 -1
- package/dist/cjs/lib/date/index.cjs +190 -7
- package/dist/cjs/lib/date/months.cjs +3 -1
- package/dist/cjs/lib/date/time.cjs +14 -2
- package/dist/cjs/lib/form/form-data.cjs +2 -0
- package/dist/cjs/lib/form/index.cjs +104 -5
- package/dist/cjs/lib/form/sanitize.cjs +2 -0
- package/dist/cjs/lib/functions/callback.cjs +2 -0
- package/dist/cjs/lib/functions/debounce.cjs +2 -0
- package/dist/cjs/lib/functions/env.cjs +2 -0
- package/dist/cjs/lib/functions/functional.cjs +2 -0
- package/dist/cjs/lib/functions/index.cjs +124 -11
- package/dist/cjs/lib/functions/throttle.cjs +2 -0
- package/dist/cjs/lib/functions/timeout.cjs +2 -0
- package/dist/cjs/lib/hash.cjs +2 -0
- package/dist/cjs/lib/index.cjs +1160 -29
- package/dist/cjs/lib/numbers/index.cjs +17 -4
- package/dist/cjs/lib/numbers/math.cjs +2 -0
- package/dist/cjs/lib/objects/camelcase-keys.cjs +45 -4
- package/dist/cjs/lib/objects/empty.cjs +2 -0
- package/dist/cjs/lib/objects/equal.cjs +2 -0
- package/dist/cjs/lib/objects/extend.cjs +117 -6
- package/dist/cjs/lib/objects/flatten.cjs +11 -3
- package/dist/cjs/lib/objects/index.cjs +360 -27
- package/dist/cjs/lib/objects/json.cjs +2 -0
- package/dist/cjs/lib/objects/loop.cjs +2 -0
- package/dist/cjs/lib/objects/mix/mix.cjs +5 -3
- package/dist/cjs/lib/objects/nested-property.cjs +2 -0
- package/dist/cjs/lib/objects/normalize-object.cjs +78 -4
- package/dist/cjs/lib/objects/omit-empty.cjs +2 -0
- package/dist/cjs/lib/objects/size.cjs +2 -0
- package/dist/cjs/lib/objects/split.cjs +2 -0
- package/dist/cjs/lib/promises/index.cjs +51 -3
- package/dist/cjs/lib/promises/reject.cjs +19 -2
- package/dist/cjs/lib/sse.cjs +29 -4
- package/dist/cjs/lib/strings/convert-case/convert-case.cjs +2 -0
- package/dist/cjs/lib/strings/index.cjs +179 -11
- package/dist/cjs/lib/strings/markdown.cjs +3 -1
- package/dist/cjs/lib/strings/name.cjs +2 -0
- package/dist/cjs/lib/strings/pluralize.cjs +3 -1
- package/dist/cjs/lib/strings/query-string.cjs +2 -0
- package/dist/cjs/lib/style/index.cjs +31 -2
- package/dist/cjs/lib/symbols/index.cjs +22 -3
- package/dist/cjs/lib/symbols/symbols.cjs +2 -0
- package/dist/cjs/node/context.cjs +0 -0
- package/dist/cjs/node/dirname.cjs +4 -2
- package/dist/cjs/node/file-cache.cjs +45 -3
- package/dist/cjs/node/file.cjs +4 -2
- package/dist/cjs/node/hash.cjs +3 -1
- package/dist/cjs/node/index.cjs +278 -15
- package/dist/cjs/node/pkce.cjs +20 -8
- package/dist/cjs/node/random-string.cjs +3 -1
- package/dist/cjs/node/sanitize.cjs +27 -3
- package/dist/cjs/node/uuid.cjs +2 -0
- package/dist/esm/node/context.js +0 -0
- package/dist/esm/node/file-cache.js +1 -1
- package/dist/esm/node/pkce.js +3 -2
- package/dist/types/node/context.d.cts +2 -0
- package/dist/types/node/index.d.cts +1 -1
- package/dist/types/node/pkce.d.cts +7 -1
- package/package.json +5 -2
- package/CHANGELOG.md +0 -231
- package/eslint.config.js +0 -2
- package/src/dom/accessibility.js +0 -58
- package/src/dom/actions/index.js +0 -3
- package/src/dom/actions/masonry.js +0 -43
- package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
- package/src/dom/actions/sticky.js +0 -85
- package/src/dom/bounding-box.js +0 -82
- package/src/dom/clipboard.js +0 -14
- package/src/dom/cookie.js +0 -32
- package/src/dom/css-vars.js +0 -19
- package/src/dom/events.js +0 -71
- package/src/dom/focusable.js +0 -165
- package/src/dom/font-size.js +0 -40
- package/src/dom/get-element.js +0 -176
- package/src/dom/hash.js +0 -9
- package/src/dom/index.js +0 -23
- package/src/dom/keyboard.js +0 -44
- package/src/dom/local-store.js +0 -66
- package/src/dom/media.js +0 -30
- package/src/dom/observers/index.js +0 -4
- package/src/dom/observers/intersection-observer.js +0 -43
- package/src/dom/observers/mutation-observer.js +0 -51
- package/src/dom/observers/observer.js +0 -18
- package/src/dom/observers/resize-observer.js +0 -66
- package/src/dom/observers/scroll-observer.js +0 -146
- package/src/dom/pkce.js +0 -34
- package/src/dom/query-params.js +0 -14
- package/src/dom/random-string.js +0 -18
- package/src/dom/random-string.test.js +0 -13
- package/src/dom/sanitize.js +0 -16
- package/src/dom/session-store.js +0 -29
- package/src/dom/spam-prevention.js +0 -40
- package/src/dom/trap-focus.js +0 -70
- package/src/dom/ui/aria-current.js +0 -20
- package/src/dom/ui/inconsistent-button-fix.js +0 -20
- package/src/dom/ui/index.js +0 -4
- package/src/dom/ui/scroll-container.js +0 -25
- package/src/dom/ui/traverse-and-scramble.js +0 -61
- package/src/lib/arrays/index.js +0 -6
- package/src/lib/arrays/item-position.js +0 -23
- package/src/lib/arrays/join.js +0 -20
- package/src/lib/arrays/shuffle.js +0 -21
- package/src/lib/arrays/sort.js +0 -88
- package/src/lib/arrays/sort.spec.js +0 -123
- package/src/lib/arrays/split-array.js +0 -15
- package/src/lib/arrays/unique.js +0 -3
- package/src/lib/auth/index.js +0 -1
- package/src/lib/auth/route-manager.js +0 -45
- package/src/lib/checks.js +0 -57
- package/src/lib/date/days.js +0 -9
- package/src/lib/date/index.js +0 -3
- package/src/lib/date/months.js +0 -74
- package/src/lib/date/time.js +0 -83
- package/src/lib/form/form-data.js +0 -73
- package/src/lib/form/index.js +0 -2
- package/src/lib/form/sanitize.js +0 -80
- package/src/lib/form/sanitize.spec.js +0 -126
- package/src/lib/functions/callback.js +0 -8
- package/src/lib/functions/debounce.js +0 -18
- package/src/lib/functions/env.js +0 -5
- package/src/lib/functions/functional.js +0 -113
- package/src/lib/functions/functional.test.js +0 -196
- package/src/lib/functions/index.js +0 -5
- package/src/lib/functions/throttle.js +0 -11
- package/src/lib/functions/timeout.js +0 -15
- package/src/lib/hash.js +0 -18
- package/src/lib/hash.spec.js +0 -163
- package/src/lib/index.js +0 -14
- package/src/lib/numbers/index.js +0 -12
- package/src/lib/numbers/math.js +0 -9
- package/src/lib/numbers/split-unit.test.js +0 -45
- package/src/lib/objects/camelcase-keys.js +0 -17
- package/src/lib/objects/camelcase-keys.test.js +0 -72
- package/src/lib/objects/empty.js +0 -10
- package/src/lib/objects/equal.js +0 -9
- package/src/lib/objects/extend.js +0 -16
- package/src/lib/objects/extend.test.js +0 -35
- package/src/lib/objects/flatten.js +0 -19
- package/src/lib/objects/index.js +0 -13
- package/src/lib/objects/json.js +0 -7
- package/src/lib/objects/loop.js +0 -11
- package/src/lib/objects/loop.test.js +0 -31
- package/src/lib/objects/mix/mix.js +0 -191
- package/src/lib/objects/mix/mix.md +0 -78
- package/src/lib/objects/mix/mix.test.js +0 -445
- package/src/lib/objects/nested-property.js +0 -41
- package/src/lib/objects/normalize-object.js +0 -10
- package/src/lib/objects/omit-empty.js +0 -23
- package/src/lib/objects/omit-empty.test.js +0 -85
- package/src/lib/objects/size.js +0 -41
- package/src/lib/objects/split.js +0 -19
- package/src/lib/promises/index.js +0 -1
- package/src/lib/promises/reject.js +0 -17
- package/src/lib/sse.js +0 -61
- package/src/lib/strings/convert-case/convert-case.js +0 -86
- package/src/lib/strings/convert-case/convert-case.md +0 -44
- package/src/lib/strings/convert-case/convert-case.test.js +0 -50
- package/src/lib/strings/index.js +0 -5
- package/src/lib/strings/markdown.js +0 -71
- package/src/lib/strings/name.js +0 -24
- package/src/lib/strings/name.test.js +0 -67
- package/src/lib/strings/pluralize.js +0 -2
- package/src/lib/strings/query-string.js +0 -18
- package/src/lib/style/index.js +0 -13
- package/src/lib/symbols/index.js +0 -1
- package/src/lib/symbols/symbols.js +0 -9
- package/src/node/dirname.js +0 -17
- package/src/node/file-cache.js +0 -184
- package/src/node/file.js +0 -13
- package/src/node/hash.js +0 -5
- package/src/node/index.js +0 -7
- package/src/node/pkce.js +0 -33
- package/src/node/random-string.js +0 -10
- package/src/node/random-string.test.js +0 -15
- package/src/node/sanitize.js +0 -13
- package/src/node/sanitize.spec.js +0 -142
- package/src/node/uuid.js +0 -5
- package/tsconfig.json +0 -23
- package/tsup.config.js +0 -38
- package/tsup.config.mjs +0 -45
package/src/lib/style/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { toKebab } from '../strings/convert-case/convert-case.js'
|
|
2
|
-
|
|
3
|
-
export function toStyleString(style) {
|
|
4
|
-
if (!style) return null
|
|
5
|
-
if (typeof style === 'string') return style
|
|
6
|
-
return Object.entries(style)
|
|
7
|
-
.map(([k, v]) => {
|
|
8
|
-
if (k.startsWith('--')) return `${k}:${v}`
|
|
9
|
-
else return `${toKebab(k)}:${v}`
|
|
10
|
-
})
|
|
11
|
-
.join('; ')
|
|
12
|
-
.concat(';')
|
|
13
|
-
}
|
package/src/lib/symbols/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './symbols.js'
|
package/src/node/dirname.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { fileURLToPath } from 'node:url'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns __dirname
|
|
6
|
-
* @param url — import.meta.url
|
|
7
|
-
* @returns
|
|
8
|
-
*/
|
|
9
|
-
export function __dirname(url) {
|
|
10
|
-
if (!url) throw Error("Please provide 'import.meta.url' to dirname")
|
|
11
|
-
return path.dirname(fileURLToPath(url))
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Just an alias
|
|
15
|
-
export function dirname(url) {
|
|
16
|
-
return __dirname(url)
|
|
17
|
-
}
|
package/src/node/file-cache.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises'
|
|
2
|
-
import { glob } from 'glob'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { sort } from '../lib/arrays/index.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Resolves a path to an absolute path, handling both absolute and relative paths
|
|
8
|
-
* @param {string} dirPath - Absolute or relative path to directory
|
|
9
|
-
* @returns {string} Absolute path
|
|
10
|
-
*/
|
|
11
|
-
function resolveDirPath(dirPath) {
|
|
12
|
-
return path.isAbsolute(dirPath) ? dirPath : path.join(process.cwd(), dirPath)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Creates a file cache instance for managing cached files in a directory
|
|
17
|
-
* @param {string} dir - Absolute or relative path to cache directory
|
|
18
|
-
* @returns {Promise<object>} Cache instance
|
|
19
|
-
* @property {function(string): Promise<number>} cacheAt - Returns the cached file's modified timestamp, or directory's last modified time if no file specified
|
|
20
|
-
* @property {function(string): string} getAbsPath - Returns absolute path for a file in cache
|
|
21
|
-
* @property {function(string): Promise<boolean>} hasFile - Checks if a file exists in cache
|
|
22
|
-
* @property {function(string): Promise<Buffer|undefined>} loadFile - Loads file contents from cache
|
|
23
|
-
* @property {function(string, string|Buffer): Promise<void>} saveFile - Saves data to cache file
|
|
24
|
-
* @property {function(string): Promise<object>} loadJSON - Loads and parses JSON from cache file
|
|
25
|
-
* @property {function(string, object): Promise<void>} saveJSON - Saves object as JSON to cache file
|
|
26
|
-
*/
|
|
27
|
-
export async function createCache(dir) {
|
|
28
|
-
const absDirpath = resolveDirPath(dir)
|
|
29
|
-
await fs.mkdir(absDirpath, { recursive: true })
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
async cacheAt(file) {
|
|
33
|
-
if (file) {
|
|
34
|
-
// Return the cached file's modified timestamp
|
|
35
|
-
const absFilepath = path.join(absDirpath, file)
|
|
36
|
-
try {
|
|
37
|
-
const stat = await fs.stat(absFilepath)
|
|
38
|
-
return stat.mtimeMs
|
|
39
|
-
} catch (error) {
|
|
40
|
-
return 0
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
// Return the last modified timestamp of the cache directory
|
|
44
|
-
return getLastModifiedTime(absDirpath + '/**/*')
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
getAbsPath(file) {
|
|
49
|
-
return path.join(absDirpath, file)
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
async hasFile(file) {
|
|
53
|
-
const absFilepath = path.join(absDirpath, file)
|
|
54
|
-
try {
|
|
55
|
-
await fs.stat(absFilepath)
|
|
56
|
-
return true
|
|
57
|
-
} catch (e) {
|
|
58
|
-
return false
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
async loadFile(file) {
|
|
63
|
-
try {
|
|
64
|
-
const absFilepath = path.join(absDirpath, file)
|
|
65
|
-
return fs.readFile(absFilepath)
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.warn(`File not found: ${file}`)
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
async saveFile(file, data) {
|
|
72
|
-
const absfilepath = path.join(absDirpath, file)
|
|
73
|
-
await fs.writeFile(absfilepath, data)
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
async loadJSON(file) {
|
|
77
|
-
const data = await this.loadFile(file)
|
|
78
|
-
try {
|
|
79
|
-
return JSON.parse(data.toString())
|
|
80
|
-
} catch (err) {
|
|
81
|
-
console.warn(`Error parsing JSON: ${file}`)
|
|
82
|
-
return {}
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
async saveJSON(file, data) {
|
|
87
|
-
await this.saveFile(file, JSON.stringify(data))
|
|
88
|
-
},
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Legacy file cache API for managing a single cached file
|
|
94
|
-
* @param {Object} options
|
|
95
|
-
* @param {string} options.dir - Absolute or relative path to cache directory
|
|
96
|
-
* @param {string} options.file - Filename to cache
|
|
97
|
-
* @returns {Promise<{
|
|
98
|
-
* modifiedAt: number,
|
|
99
|
-
* load: () => Promise<Buffer>,
|
|
100
|
-
* save: (data: string|Buffer) => Promise<void>,
|
|
101
|
-
* loadJSON: () => Promise<object>,
|
|
102
|
-
* saveJSON: (data: object) => Promise<void>
|
|
103
|
-
* }>}
|
|
104
|
-
*/
|
|
105
|
-
export async function fileCache({ dir, file }) {
|
|
106
|
-
// Makes the path if it doesn't exist
|
|
107
|
-
const absDirpath = resolveDirPath(dir)
|
|
108
|
-
await fs.mkdir(absDirpath, { recursive: true })
|
|
109
|
-
const cachePath = path.join(absDirpath, `${file}`)
|
|
110
|
-
|
|
111
|
-
let modifiedAt = 0
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const stat = await fs.stat(cachePath)
|
|
115
|
-
modifiedAt = stat.mtimeMs
|
|
116
|
-
} catch (error) {} // Silent error
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
modifiedAt,
|
|
120
|
-
|
|
121
|
-
async load() {
|
|
122
|
-
return fs.readFile(cachePath)
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
async save(data) {
|
|
126
|
-
await fs.writeFile(cachePath, data)
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
async loadJSON() {
|
|
130
|
-
const data = await fs.readFile(cachePath)
|
|
131
|
-
return JSON.parse(data.toString())
|
|
132
|
-
},
|
|
133
|
-
async saveJSON(data) {
|
|
134
|
-
await fs.writeFile(cachePath, JSON.stringify(data))
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Gets the most recent modification time of files matching the glob pattern
|
|
141
|
-
* @param {string|string[]} globPath - Glob pattern(s) to match files
|
|
142
|
-
* @returns {Promise<number>} Timestamp of most recently modified file, or 0 if no files found
|
|
143
|
-
*/
|
|
144
|
-
export async function getLastModifiedTime(globPath) {
|
|
145
|
-
let files
|
|
146
|
-
|
|
147
|
-
if (typeof globPath === 'string') {
|
|
148
|
-
files = await glob(removeFirstSlash(globPath))
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (Array.isArray(globPath)) {
|
|
152
|
-
const a = await Promise.all(
|
|
153
|
-
globPath.map(path => glob(removeFirstSlash(path))),
|
|
154
|
-
)
|
|
155
|
-
files = a.flat()
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const stats = await Promise.all(files.map(file => fs.stat(file)))
|
|
159
|
-
const timestamps = stats.map(stat => Number(stat.mtimeMs))
|
|
160
|
-
|
|
161
|
-
const sorted = sort(timestamps, { props: 'mtimeMs', reverse: true })
|
|
162
|
-
return sorted[0] || 0
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* @deprecated Use getLastModifiedTime instead
|
|
167
|
-
* @param {string|string[]} globPath - Glob pattern(s) to match files
|
|
168
|
-
* @returns {Promise<number>} Timestamp of most recently modified file, or 0 if no files found
|
|
169
|
-
*/
|
|
170
|
-
export async function getLatestModifiedTime(globPath) {
|
|
171
|
-
console.warn(
|
|
172
|
-
'`getLatestModifiedTime` has been renamed to `getLastModifiedTime` and will be deprecated in future versions. Please use `getLastModifiedTime` instead.',
|
|
173
|
-
)
|
|
174
|
-
return getLastModifiedTime(globPath)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Removes leading slash from a path string
|
|
179
|
-
* @param {string} x - Path string to process
|
|
180
|
-
* @returns {string} Path without leading slash
|
|
181
|
-
*/
|
|
182
|
-
export function removeFirstSlash(x) {
|
|
183
|
-
return x.startsWith('/') ? x.slice(1) : x
|
|
184
|
-
}
|
package/src/node/file.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Common FS stuff
|
|
2
|
-
import fs from 'node:fs/promises'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
|
|
5
|
-
export async function mkdir(path) {
|
|
6
|
-
return fs.mkdir(path, { recursive: true })
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export async function copyFile(from, to) {
|
|
10
|
-
const dir = path.dirname(to)
|
|
11
|
-
await mkdir(dir)
|
|
12
|
-
await fs.copyFile(from, to)
|
|
13
|
-
}
|
package/src/node/hash.js
DELETED
package/src/node/index.js
DELETED
package/src/node/pkce.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// For Node only.
|
|
2
|
-
// Check the utils version for browsers.
|
|
3
|
-
import crypto from 'node:crypto'
|
|
4
|
-
import { randomString } from './random-string.js'
|
|
5
|
-
|
|
6
|
-
export async function PKCE() {
|
|
7
|
-
const codeVerifier = await randomString()
|
|
8
|
-
const codeChallenge = await getCodeChallenge(codeVerifier)
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
state: await randomString(),
|
|
12
|
-
code_verifier: codeVerifier,
|
|
13
|
-
code_challenge: codeChallenge,
|
|
14
|
-
code_challenge_method: 'S256',
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Generates code challenge in node
|
|
20
|
-
* @param {string} verifier
|
|
21
|
-
* @returns string
|
|
22
|
-
*/
|
|
23
|
-
async function getCodeChallenge(verifier) {
|
|
24
|
-
// Hash to code verifier with SHA-256
|
|
25
|
-
const hash = crypto.createHash('sha256').update(verifier).digest()
|
|
26
|
-
|
|
27
|
-
// // Base64url encode the hash
|
|
28
|
-
return hash
|
|
29
|
-
.toString('base64')
|
|
30
|
-
.replace(/\+/g, '-')
|
|
31
|
-
.replace(/\//g, '_')
|
|
32
|
-
.replace(/=/g, '')
|
|
33
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import crypto from 'node:crypto'
|
|
2
|
-
|
|
3
|
-
export function randomString(length = 32) {
|
|
4
|
-
// Calculate bytes needed for desired character length
|
|
5
|
-
// Base64: 4 chars per 3 bytes, so we need ceil(length * 3 / 4) bytes
|
|
6
|
-
// Add extra bytes to ensure we have enough after encoding
|
|
7
|
-
const bytesNeeded = Math.ceil((length * 3) / 4) + 3
|
|
8
|
-
|
|
9
|
-
return crypto.randomBytes(bytesNeeded).toString('base64').slice(0, length)
|
|
10
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { randomString } from './random-string.js'
|
|
3
|
-
|
|
4
|
-
describe('randomString', () => {
|
|
5
|
-
it('should generate a random string', () => {
|
|
6
|
-
const str = randomString(32)
|
|
7
|
-
expect(str).toBeDefined()
|
|
8
|
-
expect(str.length).toBe(32)
|
|
9
|
-
|
|
10
|
-
const str2 = randomString(40)
|
|
11
|
-
expect(str2).toBeDefined()
|
|
12
|
-
expect(str2.length).toBe(40)
|
|
13
|
-
expect(str2).not.toBe(str)
|
|
14
|
-
})
|
|
15
|
-
})
|
package/src/node/sanitize.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import sanitizeHtml from 'sanitize-html'
|
|
2
|
-
import { sanitize as sanitizeLib } from '../lib/form/sanitize.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Sanitizes values using sanitize-html
|
|
6
|
-
* @param {*} value - Value to sanitize (string, array, or object)
|
|
7
|
-
* @param {Object} [options={}] - sanitize-html options
|
|
8
|
-
* @returns {*} Sanitized value
|
|
9
|
-
* @throws {Error} If input is a string but sanitize-html fails
|
|
10
|
-
*/
|
|
11
|
-
export function sanitize(value, options = {}) {
|
|
12
|
-
return sanitizeLib(value, { sanitizer: sanitizeHtml, ...options })
|
|
13
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { sanitize } from './sanitize.js'
|
|
3
|
-
|
|
4
|
-
describe('node sanitize', () => {
|
|
5
|
-
describe('sanitize', () => {
|
|
6
|
-
it('removes script tags', () => {
|
|
7
|
-
const input = '<script>alert("xss")</script>Hello'
|
|
8
|
-
expect(sanitize(input)).toBe('Hello')
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('allows safe HTML tags', () => {
|
|
12
|
-
const input = '<p>Hello <b>World</b></p>'
|
|
13
|
-
expect(sanitize(input, { allowedTags: ['b'] })).toBe('Hello <b>World</b>')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('sanitizes unsafe attributes', () => {
|
|
17
|
-
const input = '<a href="javascript:alert(1)">Click me</a>'
|
|
18
|
-
expect(
|
|
19
|
-
sanitize(input, {
|
|
20
|
-
allowedTags: ['a'],
|
|
21
|
-
allowedAttributes: { a: ['href'] },
|
|
22
|
-
}),
|
|
23
|
-
).toBe('<a>Click me</a>')
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('allows safe attributes', () => {
|
|
27
|
-
const input = '<a href="https://example.com">Safe link</a>'
|
|
28
|
-
expect(
|
|
29
|
-
sanitize(input, {
|
|
30
|
-
allowedTags: ['a'],
|
|
31
|
-
allowedAttributes: { a: ['href'] },
|
|
32
|
-
}),
|
|
33
|
-
).toBe('<a href="https://example.com">Safe link</a>')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('sanitizes HTML in string values', () => {
|
|
37
|
-
const input = {
|
|
38
|
-
name: '<script>alert("xss")</script>John',
|
|
39
|
-
bio: '<p>Hello <b>World</b> <script>alert("xss")</script></p>',
|
|
40
|
-
link: '<a href="javascript:alert(1)">Click me</a>',
|
|
41
|
-
safeLink: '<a href="https://example.com">Safe link</a>',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const expected = {
|
|
45
|
-
name: 'John',
|
|
46
|
-
bio: 'Hello <b>World</b> ',
|
|
47
|
-
link: '<a>Click me</a>',
|
|
48
|
-
safeLink: '<a href="https://example.com">Safe link</a>',
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
expect(
|
|
52
|
-
sanitize(input, {
|
|
53
|
-
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
|
|
54
|
-
allowedAttributes: { a: ['href'] },
|
|
55
|
-
}),
|
|
56
|
-
).toEqual(expected)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('sanitizes nested objects with HTML', () => {
|
|
60
|
-
const input = {
|
|
61
|
-
user: {
|
|
62
|
-
name: '<script>alert("xss")</script>John',
|
|
63
|
-
profile: {
|
|
64
|
-
bio: '<p>Hello <b>World</b></p>',
|
|
65
|
-
links: [
|
|
66
|
-
'<a href="javascript:alert(1)">Bad</a>',
|
|
67
|
-
'<a href="https://good.com">Good</a>',
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const expected = {
|
|
74
|
-
user: {
|
|
75
|
-
name: 'John',
|
|
76
|
-
profile: {
|
|
77
|
-
bio: 'Hello <b>World</b>',
|
|
78
|
-
links: ['<a>Bad</a>', '<a href="https://good.com">Good</a>'],
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
expect(
|
|
84
|
-
sanitize(input, {
|
|
85
|
-
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
|
|
86
|
-
allowedAttributes: { a: ['href'] },
|
|
87
|
-
}),
|
|
88
|
-
).toEqual(expected)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it('preserves non-string values and sanitizes arrays correctly', () => {
|
|
92
|
-
const input = {
|
|
93
|
-
name: '<script>alert("xss")</script>John',
|
|
94
|
-
age: 25,
|
|
95
|
-
active: true,
|
|
96
|
-
email: null,
|
|
97
|
-
role: undefined,
|
|
98
|
-
tags: ['<script>alert(1)</script>admin', 'user'],
|
|
99
|
-
numbers: [1, 2, 3],
|
|
100
|
-
mixed: ['<b>bold</b>', 42, null, '<script>alert(1)</script>text'],
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const expected = {
|
|
104
|
-
name: 'John',
|
|
105
|
-
age: 25,
|
|
106
|
-
active: true,
|
|
107
|
-
email: null,
|
|
108
|
-
role: undefined,
|
|
109
|
-
tags: ['admin', 'user'],
|
|
110
|
-
numbers: [1, 2, 3],
|
|
111
|
-
mixed: ['<b>bold</b>', 42, null, 'text'],
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
expect(
|
|
115
|
-
sanitize(input, {
|
|
116
|
-
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
|
|
117
|
-
allowedAttributes: { a: ['href'] },
|
|
118
|
-
}),
|
|
119
|
-
).toEqual(expected)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('allows custom sanitizer options', () => {
|
|
123
|
-
const input = {
|
|
124
|
-
content: '<p>Hello <span>World</span> <script>alert(1)</script></p>',
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Test with custom allowed tags
|
|
128
|
-
const withSpan = sanitize(input, {
|
|
129
|
-
allowedTags: ['b', 'i', 'em', 'strong', 'a', 'span'],
|
|
130
|
-
allowedAttributes: { a: ['href'] },
|
|
131
|
-
})
|
|
132
|
-
expect(withSpan.content).toBe('Hello <span>World</span> ')
|
|
133
|
-
|
|
134
|
-
// Test with no allowed tags
|
|
135
|
-
const noTags = sanitize(input, {
|
|
136
|
-
allowedTags: [],
|
|
137
|
-
allowedAttributes: { a: ['href'] },
|
|
138
|
-
})
|
|
139
|
-
expect(noTags.content).toBe('Hello World ')
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
})
|
package/src/node/uuid.js
DELETED
package/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"allowJs": true,
|
|
7
|
-
"checkJs": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"emitDeclarationOnly": false,
|
|
10
|
-
"outDir": "./dist/temp",
|
|
11
|
-
"strict": false,
|
|
12
|
-
"noImplicitAny": false,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"resolveJsonModule": true,
|
|
16
|
-
"isolatedModules": true,
|
|
17
|
-
"noEmit": true,
|
|
18
|
-
"esModuleInterop": true,
|
|
19
|
-
"allowSyntheticDefaultImports": true
|
|
20
|
-
},
|
|
21
|
-
"include": ["src/**/*"],
|
|
22
|
-
"exclude": ["node_modules", "**/*.test.js", "**/*.spec.js", "dist/**/*"]
|
|
23
|
-
}
|
package/tsup.config.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'tsup'
|
|
2
|
-
|
|
3
|
-
export default defineConfig([
|
|
4
|
-
// ESM build
|
|
5
|
-
{
|
|
6
|
-
entry: 'src/**/*.js',
|
|
7
|
-
format: ['esm'],
|
|
8
|
-
outDir: 'dist/esm',
|
|
9
|
-
clean: true,
|
|
10
|
-
splitting: false,
|
|
11
|
-
sourcemap: false,
|
|
12
|
-
dts: false,
|
|
13
|
-
ignoreWatch: ['**/*.test.js', '**/*.spec.js'],
|
|
14
|
-
},
|
|
15
|
-
// CJS build
|
|
16
|
-
{
|
|
17
|
-
entry: 'src/**/*.js',
|
|
18
|
-
format: ['cjs'],
|
|
19
|
-
outDir: 'dist/cjs',
|
|
20
|
-
outExtension: () => ({ js: '.cjs' }),
|
|
21
|
-
clean: false,
|
|
22
|
-
splitting: false,
|
|
23
|
-
sourcemap: false,
|
|
24
|
-
dts: false,
|
|
25
|
-
ignoreWatch: ['**/*.test.js', '**/*.spec.js'],
|
|
26
|
-
},
|
|
27
|
-
// Types build
|
|
28
|
-
{
|
|
29
|
-
entry: 'src/**/*.js',
|
|
30
|
-
dts: {
|
|
31
|
-
only: true,
|
|
32
|
-
},
|
|
33
|
-
outDir: 'dist/types',
|
|
34
|
-
outExtension: () => ({ dts: '.d.cts' }),
|
|
35
|
-
clean: false,
|
|
36
|
-
ignoreWatch: ['**/*.test.js', '**/*.spec.js'],
|
|
37
|
-
},
|
|
38
|
-
])
|
package/tsup.config.mjs
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { glob } from 'glob'
|
|
2
|
-
import { defineConfig } from 'tsup'
|
|
3
|
-
|
|
4
|
-
function getEntryPoints() {
|
|
5
|
-
// Get all JS files except test files
|
|
6
|
-
return glob.sync('src/**/*.js', {
|
|
7
|
-
ignore: ['**/*.test.js', '**/*.spec.js'],
|
|
8
|
-
})
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export default defineConfig([
|
|
12
|
-
// ESM build
|
|
13
|
-
{
|
|
14
|
-
entry: getEntryPoints(),
|
|
15
|
-
format: ['esm'],
|
|
16
|
-
outDir: 'dist/esm',
|
|
17
|
-
clean: true,
|
|
18
|
-
bundle: false,
|
|
19
|
-
splitting: false,
|
|
20
|
-
sourcemap: false,
|
|
21
|
-
dts: false,
|
|
22
|
-
},
|
|
23
|
-
// CJS build
|
|
24
|
-
{
|
|
25
|
-
entry: getEntryPoints(),
|
|
26
|
-
format: ['cjs'],
|
|
27
|
-
outDir: 'dist/cjs',
|
|
28
|
-
outExtension: () => ({ js: '.cjs' }),
|
|
29
|
-
clean: false,
|
|
30
|
-
bundle: false,
|
|
31
|
-
splitting: false,
|
|
32
|
-
sourcemap: false,
|
|
33
|
-
dts: false,
|
|
34
|
-
},
|
|
35
|
-
// Types build
|
|
36
|
-
{
|
|
37
|
-
entry: getEntryPoints(),
|
|
38
|
-
dts: {
|
|
39
|
-
only: true,
|
|
40
|
-
},
|
|
41
|
-
outDir: 'dist/types',
|
|
42
|
-
outExtension: () => ({ dts: '.d.cts' }),
|
|
43
|
-
clean: false,
|
|
44
|
-
},
|
|
45
|
-
])
|