Compare commits

...

2 Commits

Author SHA1 Message Date
95f8d5762c Fixed import error
All checks were successful
Build / Build NPM Project (push) Successful in 57s
Build / Tag Version (push) Successful in 13s
Build / Publish Documentation (push) Successful in 48s
2025-05-06 16:01:57 -04:00
3bc82fab45 - Fixed cache.addAll()
Some checks failed
Build / Build NPM Project (push) Failing after 34s
Build / Publish Documentation (push) Has been skipped
Build / Tag Version (push) Has been skipped
- Renamed jwtDecode to decodeJWT to match conventions
- Added testCondition to search
2025-05-06 15:59:08 -04:00
6 changed files with 138 additions and 43 deletions

View File

@ -1,15 +1,104 @@
<!Doctype html>
<html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>@ztimson/utils sandbox</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>About Us | OurTrainingRoom</title>
<style>
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #fdfdfd;
color: #333;
line-height: 1.6;
}
header {
background: #004080;
color: #fff;
padding: 2rem 1rem;
text-align: center;
}
header h1 {
margin: 0;
font-size: 2.5rem;
}
main {
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
section {
margin-bottom: 2rem;
}
h2 {
color: #004080;
margin-bottom: 0.5rem;
}
ul {
padding-left: 1.25rem;
}
footer {
text-align: center;
font-size: 0.9rem;
color: #777;
padding: 2rem 1rem;
background: #f1f1f1;
margin-top: 4rem;
}
</style>
</head>
<body>
<script type="module">
import {PathEvent} from './dist/index.mjs';
<header>
<h1>About Us</h1>
<p>Empowering Learning Through Innovation</p>
</header>
console.log(PathEvent.filter(['payments/ztimson:cr', 'logs/momentum:c', 'data/Testing:r'], 'data'));
console.log(PathEvent.filter(['data/Submissions/Test:r'], 'data/Submissions/Test/test.html'));
</script>
<main>
<section>
<p>
E-learning has evolved significantly since its inception. Today, there's a shift towards
blended learning services, integrating online activities with practical, real-world applications.
</p>
</section>
<section>
<h2>What We Do</h2>
<p>At <strong>OurTrainingRoom.com</strong>, we specialize in content management and professional development training tailored for:</p>
<ul>
<li>School Boards</li>
<li>Municipalities</li>
<li>Hospitals</li>
<li>Large Corporations</li>
</ul>
</section>
<section>
<h2>Our Roots</h2>
<p>
Our parent company, <strong>The Auxilium Group</strong>, is a leader in online data management.
The formation of OurTrainingRoom.com was a natural progression to deliver state-of-the-art front-end e-learning programs.
</p>
</section>
<section>
<h2>Our Approach</h2>
<p>
Built on principles of quality and continuous improvement, our diverse delivery range continues to grow.
We set new trends by enhancing our existing products and attentively listening to our clients and their employees.
This unique approach has solidified our position in the industry, making a substantial impact for our clients.
</p>
</section>
<section>
<h2>Have a Question?</h2>
<p>
We value your inquiries and are here to assist you. Please reach out with any questions or feedback.
</p>
</section>
</main>
<footer>
&copy; 2025 OurTrainingRoom.com. All rights reserved.
</footer>
</body>
</html>

View File

@ -1,6 +1,6 @@
{
"name": "@ztimson/utils",
"version": "0.23.23",
"version": "0.24.0",
"description": "Utility library",
"author": "Zak Timson",
"license": "MIT",

View File

@ -22,7 +22,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Create new cache
*
* @param {keyof T} key Default property to use as primary key
* @param options
*/
@ -56,7 +55,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Get all cached items
*
* @return {T[]} Array of items
*/
all(): T[] {
@ -65,7 +63,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Add a new item to the cache. Like set, but finds key automatically
*
* @param {T} value Item to add to cache
* @param {number | undefined} ttl Override default expiry
* @return {this}
@ -78,12 +75,12 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Add several rows to the cache
*
* @param {T[]} rows Several items that will be cached using the default key
* @param complete Mark cache as complete & reliable, defaults to true
* @return {this}
*/
addAll(rows: T[], complete = true): this {
this.clear();
rows.forEach(r => this.add(r));
this.complete = complete;
return this;
@ -98,7 +95,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Delete an item from the cache
*
* @param {K} key Item's primary key
*/
delete(key: K) {
@ -126,7 +122,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Get a list of cached keys
*
* @return {K[]} Array of keys
*/
keys(): K[] {
@ -135,7 +130,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Get map of cached items
*
* @return {Record<K, T>}
*/
map(): Record<K, T> {
@ -144,7 +138,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Add an item to the cache manually specifying the key
*
* @param {K} key Key item will be cached under
* @param {T} value Item to cache
* @param {number | undefined} ttl Override default expiry in seconds
@ -163,7 +156,6 @@ export class Cache<K extends string | number | symbol, T> {
/**
* Get all cached items
*
* @return {T[]} Array of items
*/
values = this.all();

View File

@ -6,7 +6,7 @@ import {JSONAttemptParse} from './objects.ts';
* @param {string} token JWT to decode
* @return {unknown} JWT payload
*/
export function jwtDecode<T>(token: string): T {
export function decodeJwt<T>(token: string): T {
const base64 = token.split('.')[1]
.replace(/-/g, '+').replace(/_/g, '/');
return <T>JSONAttemptParse(decodeURIComponent(atob(base64).split('').map(function(c) {

View File

@ -109,7 +109,6 @@ export function encodeQuery(data: any): string {
).join('&');
}
/**
* Recursively flatten a nested object, while maintaining key structure
*

View File

@ -1,4 +1,4 @@
import {dotNotation, JSONAttemptParse} from './objects';
import {dotNotation, JSONAttemptParse} from './objects.ts';
export function search(rows: any[], search: string, regex?: boolean, transform: Function = (r: any) => r) {
if(!rows) return [];
@ -12,27 +12,42 @@ export function search(rows: any[], search: string, regex?: boolean, transform:
try { return RegExp(search, 'gm').test(v.toString()); }
catch { return false; }
}).length
} else {
return testCondition(search, r);
}
// Make sure at least one OR passes
const or = search.split('||').map(p => p.trim()).filter(p => !!p);
return -1 != or.findIndex(p => {
// Make sure all ANDs pass
const and = p.split('&&').map(p => p.trim()).filter(p => !!p);
return and.filter(p => {
// Boolean operator
const prop = /(\w+)\s*(==?|!=|>=|>|<=|<)\s*(\w+)/g.exec(p);
if(prop) {
const a = JSON.stringify(JSONAttemptParse(dotNotation<any>(value, prop[1])));
const operator = prop[2] == '=' ? '==' : prop[2];
const b = JSON.stringify(JSONAttemptParse(prop[3]));
return eval(`${a} ${operator} ${b}`);
}
// Case-sensitive
const v = Object.values(value).join('');
if(/[A-Z]/g.test(search)) return v.includes(p);
// Case-insensitive
return v.toLowerCase().includes(p);
}).length == and.length;
})
});
}
export function testCondition(condition: string, row: any) {
const evalBoolean = (a: any, op: string, b: any): boolean => {
switch(op) {
case '=':
case '==': return a == b;
case '!=': return a != b;
case '>': return a > b;
case '>=': return a >= b;
case '<': return a < b;
case '<=': return a <= b;
default: return false;
}
}
const or = condition.split('||').map(p => p.trim()).filter(p => !!p);
return -1 != or.findIndex(p => {
// Make sure all ANDs pass
const and = p.split('&&').map(p => p.trim()).filter(p => !!p);
return and.filter(p => {
// Boolean operator
const prop = /(\S+)\s*(==?|!=|>=|>|<=|<)\s*(\S+)/g.exec(p);
if(prop) {
const key = Object.keys(row).find(k => k.toLowerCase() == prop[1].toLowerCase());
return evalBoolean(dotNotation<any>(row, key || prop[1]), prop[2], JSONAttemptParse(prop[3]));
}
// Case-sensitive
const v = Object.values(row).map(v => typeof v == 'object' && v != null ? JSON.stringify(v) : v).join('');
if(/[A-Z]/g.test(condition)) return v.includes(p);
// Case-insensitive
return v.toLowerCase().includes(p);
}).length == and.length;
});
}