Skip to content

Instantly share code, notes, and snippets.

@Shimilbi
Last active January 18, 2024 14:55
Show Gist options
  • Save Shimilbi/b4558667432cfaa021242395557cc093 to your computer and use it in GitHub Desktop.
Save Shimilbi/b4558667432cfaa021242395557cc093 to your computer and use it in GitHub Desktop.
Open raw, and search for keywords.
import { exec } from "child_process"
//#region //////////////////////////////////////////////////////
//#region Exdending API objects with new functions inJS (different from Class oriented Language like C# and Java)
//#region In order to be able to call them as: type.function() instead of function(type)
// Only do this in small-team projects not to crowd the prototype node too much!
//#region //////////////////////////////////////////////////////
// Extension functions (easier to do with Typescript thanks to the declare and interface statments)
// Note: "global" interfaces and functions are automatically exported, no need to add "export"
declare global {
interface Array<T> {
ReplaceEntry<T>(): boolean // not yet defined
}
interface Object {
implementOf<Interface>(): boolean
}
interface String {
getWorkingDirectory(): string
getFileName(): string
getExtension(): string
textToHTMLDocumentObject(): any
startsWithEither(...cues:string[]): boolean
endsWithEither(...cues:string[]): boolean
includesEither(...cues:string[]): boolean
remove(oldString:string): string
removeAll(oldString:string): string
removeLast(oldString:string): string
replaceAll(oldString:string, newString:string): string
replaceLast(oldString:string, newString:string): string
}
interface Date {
toUTC(): Date
getLapseSince(laterDate:Date): number
}
interface Map<K,V> {
hasValue<V>(value:V): boolean //DONE
valuesToArray(): V[] //DONE
keysToArray(): K[] //DONE
getFirst(): V //DONE
getLast(): V //DONE
getPrevious<K>(currentKey:K): V //DONE
getNext<K>(currentKey:K): V //DONE
firstKey(): K
lastKey(): K
previousKey<K>(currentKey:K): K //DONE
nextKey<K>(currentKey:K): K //DONE
indexOfKey(key:K): number //DONE
getByIndex(i:number): V //DONE
filter<K,V>(predicate: (entry:[K,V], index?:number) => unknown): Map<K,V> //DONE?
getPromiseResults<Promise, T>(): T //DONE
}
}
//#region New funcitons extending the objects
Map.prototype.hasValue = function<V>(value:V) {
for (let [k, v] of this)
if (v===value) return true
return false
}
Map.prototype.valuesToArray = function<V>() {
return [...this.values()]
}
Map.prototype.keysToArray = function<K>() {
return [...this.keys()]
}
Map.prototype.getFirst = function() {
return [...this.values()][0]
}
Map.prototype.getLast = function() {
const asArray = [...this.values()]
return asArray[asArray.length-1]
}
Map.prototype.getPrevious = function<K>(currentKey:K) {
const asArray = [...this.entries()]
const i = asArray.indexOf(this.get(currentKey))
return asArray[i-1]
}
Map.prototype.getNext = function<K>(currentKey:K) {
const asArray = [...this.entries()]
const i = asArray.indexOf(this.get(currentKey))
return asArray[i+1]
}
Map.prototype.firstKey = function() {
return [...this.keys()][0]
}
Map.prototype.lastKey = function() {
const asKeyArray = [...this.keys()]
return asKeyArray[asKeyArray.length-1]
}
Map.prototype.previousKey = function<K>(currentKey:K) {
const asKeyArray = [...this.keys()]
const i = asKeyArray.indexOf(this.get(currentKey))
return asKeyArray[i-1]
}
Map.prototype.nextKey = function<K>(currentKey:K) {
const asKeyArray = [...this.keys()]
const i = asKeyArray.indexOf(this.get(currentKey))
return asKeyArray[i+1]
}
Map.prototype.indexOfKey = function<K>(key:K) {
const asArray = [...this.values()]
return asArray.indexOf(this.get(key))
}
Map.prototype.getByIndex = function(i:number) {
const asArray = [...this.values()]
return asArray[i]
}
String.prototype.getWorkingDirectory = function () {
if (!IsValidUrl(this as string)) throw "(" + this + "is not an exiting url.)"
const tempPathCopy = this as string
tempPathCopy.split("/").pop()
return tempPathCopy
}
String.prototype.getFileName = function () {
if (!IsValidUrl(this as string)) throw "(" + this as string + "is not an exiting url.)"
const tempPathCopy = this as string
return tempPathCopy.split("/").pop()!
}
String.prototype.getExtension = function () {
const temp = this! as string
return "." + temp.split('.').pop()
}
/** Deletes all occurence of a substring in a string, and returns the result */
String.prototype.removeAll = function (oldString) {
if (!this.includes(oldString)) return this.toString()
return this.split(oldString).join("").toString()
}
/** Deletes the fist occurence of a substring in a string, and returns the result */
String.prototype.remove = function (oldString) {
if (!this.includes(oldString)) return this.toString()
let pieces = this.split(oldString)
pieces.shift()
return pieces.join(oldString).toString()
}
/** Deletes the last occurence of a substring in a string, and returns the result */
String.prototype.removeLast = function (oldString) {
if (!this.includes(oldString)) return this.toString()
let pieces = this.split(oldString)
pieces.pop()
return pieces.join(oldString).toString()
}
/** Replaces all occurence of a substring in a string, and returns the result */
String.prototype.replaceAll = function (oldString, newString) {
if (!this.includes(oldString.toString())) return this.toString()
return this.split(oldString).join(newString.toString())
}
/** Replaces the last occurence of a substring in a string, and returns the result */
String.prototype.replaceLast = function (oldString, newString) {
if (!this.includes(oldString)) return this.toString()
let pieces = this.split(oldString)
pieces.pop()
return (pieces.join(oldString) + newString).toString()
}
String.prototype.startsWithEither = function(...cues:string[]) {
return cues.some(cue => this.trim().toLowerCase().startsWith(cue.trim().toLowerCase()))
}
String.prototype.endsWithEither = function(...cues:string[]) {
return cues.some(cue => this.trim().toLowerCase().endsWith(cue.trim().toLowerCase()))
}
String.prototype.includesEither = function(...cues:string[]) {
return cues.some(cue => this.trim().toLowerCase().includes(cue.trim().toLowerCase()))
}
Date.prototype.toUTC = function() {
// Returns a Date: YYYY-MM-DD HH-MM-SS UTC
return new Date(this.getUTCFullYear(), this.getUTCMonth(), this.getUTCDay(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds())
}
//#region Other functions
export const DateNow_asUTC = () =>
new Date(Date.now()).toUTC()
/** Format: YYYY_MM_DD_HH_MM_SS */
export const DateNow_asUTCstring = () =>
DateNow_asUTC().toUTCString()
export class Randomizer<T> {
Pool :T[]
UsedEntries? :T[]
LastPick? :T
DebugErrorTolerence :number = 5
constructor(...list:T[]) {
this.Pool = list as T[]
// console.log("\n(F.Randomizer: Pool is: " + this.PoolOfUnused().join("|")+" )")
}
// Optional call
#Cheat (edgeTowardThisValue:T) {
if (this.LastPick===undefined)
throw "(Randomizer.#Cheat: Please first get a random pick before cheating on it.)"
const remnents = this.PoolOfUnused()
if (!remnents.includes(this.LastPick))
throw "(Randomizer.#Cheat: Please don't eliminate the initial random pick before cheating on it.)"
let pickedIndex = remnents.includes(this.LastPick)
? remnents.indexOf(this.LastPick)
: this.Pool.indexOf(this.LastPick)
// console.log("Randomizer.#Cheat (DEBUG) of index "+pickedIndex)
let indexToEdgeTowardOf = remnents.indexOf(edgeTowardThisValue)
// console.log("edgeTowardThisValue="+edgeTowardThisValue)
if (indexToEdgeTowardOf > pickedIndex && pickedIndex < remnents.length-1) pickedIndex += 1
else if (indexToEdgeTowardOf < pickedIndex && pickedIndex > 0) pickedIndex -= 1
// console.log("index changed for "+pickedIndex)
this.LastPick = remnents[pickedIndex]
// console.log("favored value: "+this.LastPick)
return this
}
// Optional call
#ThenEliminate () {
if (this.LastPick===undefined)
throw "(Randomizer.#ThenEliminate: Please first get a random pick, then eventually cheat about it, before eliminating it.)"
this.UsedEntries ??= []
this.UsedEntries.push(this.LastPick)
if (this.UsedEntries.length>0)
// If all values were picked once, All are available again
if (this.UsedEntries.every(usedEntry =>
this.PoolOfUnused().includes(usedEntry))
)
this.UsedEntries = []
return this
}
PoolOfUnused() {
if (this.UsedEntries===undefined||this.UsedEntries?.length<1)
return this.Pool
else {
let unused: T[] = this.Pool.filter(entry => !this.UsedEntries!.includes(entry))
return unused.length < 1 ? this.Pool : unused
}
}
getRandom(avoidDuplicates?:boolean, entryToFavor?:T) {
const remnants = this.PoolOfUnused()
// console.log("(Randomizer.GetRandom (DEBUG) Pool: \n- "+remnants.join("\n- "))
this.LastPick = remnants.length==1
? remnants[0]
: remnants[Math.floor( (Math.random() * remnants.length) + 1 )]
// console.log("> "+this.LastPick+" <")
if (this.LastPick===undefined && this.DebugErrorTolerence>0) {
this.DebugErrorTolerence-=1
console.log("(repicking)")
this.getRandom()
}
else if (this.LastPick===undefined && this.DebugErrorTolerence==0) {
this.LastPick = remnants[0]
// throw "A random result could not be picked (and present function might have been looping endlessly by now, so recursivity was limited to 5 consecutive times.)\nWhy are there erros? Maybe because the core function (not my own code) is bugged."
}
const hasFavorite = entryToFavor!==undefined
if (hasFavorite) this.#Cheat(entryToFavor)
if (avoidDuplicates) this.#ThenEliminate()
return this.LastPick
}
}
export const ExecuteInTerminal = (nodeJsCommandLine: string) => {
exec(nodeJsCommandLine, (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`)
return
}
if (stderr) {
console.log(`stderr: ${stderr}`)
return
}
console.log(`stdout: ${stdout}`)
})
}
const ConvertMsTo = {
secs: (timestamp_in_milliseconds:number) => {
const aSecInMs = 1000
return laterDate.getLapseSince(timestamp_in_milliseconds) / aSecInMs
},
mins: (timestamp_in_milliseconds:number) => {
const aMinInMs = 1000 * 60
return laterDate.getLapseSince(timestamp_in_milliseconds) / aMinInMs
},
hours: (timestamp_in_milliseconds:number) => {
const anHourInMs = 1000 * 60 * 60
return laterDate.getLapseSince(timestamp_in_milliseconds) / anHourInMs
},
days: (timestamp_in_milliseconds:number) => {
const aDayInMs = 1000 * 60 * 60 * 24
return laterDate.getLapseSince(timestamp_in_milliseconds) / aDayInMs
}
}
export var always_varying_value: symbol = Symbol()
export const IsValidUrl = (url:string) => {
try {
return Boolean(new URL(url))
}
catch(e){
return false
}
}
/**
* SUPER PRECIOUS!
GENERATES A DOM in an environment where the browser is availiable but it's not possible to write on the webpage!
GENERATES A DOM from a string, without writing a file on any drive!
So that we can use the tools of that interface, such as filepicker, textarea for linbreak supported copying, page formatting, etc.
* How to use:
const storedHtml = '<html><body></body></html>'
const doc = storedHtml.textToHTMLdocument()
*/
String.prototype.textToHTMLDocumentObject = function () {
let parseXml: (xmlStr: String) => any
if (globalThis.DOMParser)
parseXml = function(xmlStr:String) {
return ( new globalThis.DOMParser() ).parseFromString(xmlStr, "text/xml")
}
else if (typeof globalThis.ActiveXObject != "undefined" && new globalThis.ActiveXObject("Microsoft.XMLDOM"))
parseXml = function(xmlStr:String) {
let xmlDoc = new globalThis.ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async = "false"
xmlDoc.loadXML(xmlStr)
return xmlDoc
}
else
throw this+"\n could not be converted into a HTMLDocument."
return parseXml(this).implementation.createHTMLDocument()
}
//#region Ranges
export class Range {
Min: number
Max: number
AllowedValues: number[]
Field: number
constructor(min_: number|string, max_: number, field_: number) {
this.Min = min_==="unlimited" && max_===undefined? 0 : (min_ as number)
this.Max = min_==="unlimited" && max_===undefined? 999999999999999 : max_
this.AllowedValues = [this.Min]
for (let i = this.Min; i <= this.Max; i++)
this.AllowedValues.push(i)
if (!this.AllowedValues.includes(field_))
throw "Can't create range of ("+this.Min+"-"+this.Max+"), because default value " +field_+ " is out of range."
this.Field = field_
}
canIncrement (step_?: number) {
let step = step_ ?? 1
return this.Field + step <= this.Max
}
increment (step_?: number) {
let step = step_ ?? 1
if (this.Field + step>this.Max)
console.log("Range.OperateWithinRange: " + this.Field + " would exceed the maximum of " + this.Max)
else
return this.Field += step as number
}
canDecrement (step_?: number) {
let step = step_ ?? 1
return this.Field - step >= (this.Min as number)
}
decrement (step_?: number) {
let step = step_ ?? 1
if (this.Field - step<(this.Min as number))
console.log("Range.OperateWithinRange: " + this.Field + " would be below the minimum of " + this.Max)
else
return this.Field -= step as number
}
IsWithinRange (value_: number) {
return this.AllowedValues.includes(value_)
}
override (newValue_: number) {
if (!this.IsWithinRange(newValue_))
throw "Range.OperateWithinRange: " + newValue_ + " is not within authorised range of (" + this.Min + ", " + this.Max + ")"
return this.Field = newValue_
}
tryOverride (newValue_: number) {
return this.Field = this.IsWithinRange(newValue_) ? newValue_ : this.Field
}
}
// To use vales as a ts type in order to limite allowed values
export const MetaMetaGenerateRangeOfValues = ()=> {
// Generates A Range Of Values In The Terminal, For The Unique Purpose Of Copy-Pasting It In The Code
const Range = (min: number, max: number, step_?: number) => {
const step = step_ ??= 1
Array.from( new Array( max > min ? Math.ceil((max - min)/step) : Math.ceil((min - max)/step) ), ( x, i ) => max > min ? i*step + min : min - i*step ).join(" | ")
}
console.log(Range(3,10))
// Note: the function itself won't be accepted by typescript as a valid value.
// must use the console.log and copy paste it as a value in the typescript code hre
}
export async function GetOuterJson_Content(url = "", asJson?:boolean) { // but doesn't copy/import it in website deploy
const response = await fetch(url, {
method: "GET",
mode: "cors", // no-cors, *cors, same-origin
credentials: "same-origin", // include, *same-origin, omit
headers: {"Content-Type": "application/json"}
})
return JSON.parse(await response.json() as any) as { [key: string]:any }
}
export async function GetOuterFile_Content(url = "") { // but doesn't copy/import it in website deploy
const response = await fetch(url)
return await (response.text()) as string
}
export async function PostIntoGlobalDATABASE(key:string, newValue:string) {
const url = ""
const newObj:{ [key: string]:any } = await GetOuterJson_Content(url, true) as { [key: string]:any }
newObj[key] = newValue
const response = await fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, *cors, same-origin
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: "follow", // manual, *follow, error
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(newObj) // le type utilisé pour le corps doit correspondre à l'en-tête "Content-Type"
})
return response.json() // transforme la réponse JSON reçue en objet JavaScript natif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment